diff --git a/samples/resources/hello.ssml b/samples/resources/hello.ssml new file mode 100644 index 00000000..9e525c48 --- /dev/null +++ b/samples/resources/hello.ssml @@ -0,0 +1,7 @@ + + + Hello there. + diff --git a/samples/resources/hello.txt b/samples/resources/hello.txt new file mode 100644 index 00000000..c12abce9 --- /dev/null +++ b/samples/resources/hello.txt @@ -0,0 +1 @@ +Hello there. diff --git a/samples/system-test/synthesizeText.test.js b/samples/system-test/synthesizeText.test.js deleted file mode 100644 index ab0ddfe0..00000000 --- a/samples/system-test/synthesizeText.test.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright 2018, Google, Inc. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -const path = require(`path`); -const test = require(`ava`); -const tools = require(`@google-cloud/nodejs-repo-tools`); - -const cmd = `node synthesizeText.js`; -const cwd = path.join(__dirname, `..`); -const files = [ - `sample.ssml`, -].map(name => { - return { - name, - localPath: path.resolve(path.join(__dirname, `../resources/${name}`)), - }; -}); - -test.before(tools.checkCredentials); - -test(`should list voice`, async t => { - const output = await tools.runAsync( - `${cmd} list-voices`, - cwd - ); - t.true(output.includes(`Name: ana`)); - t.true(output.includes(`SSML Gender: FEMALE`)); -}); diff --git a/samples/system-test/textToSpeech.test.js b/samples/system-test/textToSpeech.test.js new file mode 100644 index 00000000..beafc258 --- /dev/null +++ b/samples/system-test/textToSpeech.test.js @@ -0,0 +1,97 @@ +/** + * Copyright 2018, Google, Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const fs = require(`fs`); +const path = require(`path`); +const test = require(`ava`); +const tools = require(`@google-cloud/nodejs-repo-tools`); + +const cmd = `node textToSpeech.js`; +const cwd = path.join(__dirname, `..`); +const text = `Hello there.`; +const ssml = ` + +Hello there. +`; +const outputFile = `test-output.mp3`; +const files = [ + `hello.txt`, + `hello.ssml`, +].map(name => { + return { + name, + localPath: path.resolve(path.join(__dirname, `../resources/${name}`)), + }; +}); + +test.before(tools.checkCredentials); + +test.after.always(async () => { + await fs.unlink(outputFile); +}); + +test(`should list voice`, async t => { + const output = await tools.runAsync( + `${cmd} list-voices`, + cwd + ); + t.true(output.includes(`SSML Gender: FEMALE`)); + t.true(output.includes(`Natural Sample Rate Hertz: 24000`)); +}); + +test(`should synthesize audio from text`, async t => { + t.false(fs.existsSync(outputFile)); + const output = await tools.runAsync( + `${cmd} synthesize-text '${text}' --outputFile '${outputFile}'`, + cwd + ); + t.true(output.includes(`Saved synthesized text to local audio file ${outputFile}`)); + t.true(fs.existsSync(outputFile)); +}); + +test(`should synthesize audio from ssml`, async t => { + t.false(fs.existsSync(outputFile)); + const output = await tools.runAsync( + `${cmd} synthesize-ssml '${ssml}' --outputFile '${outputFile}'`, + cwd + ); + t.true(output.includes(`Saved synthesized text to local audio file ${outputFile}`)); + t.true(fs.existsSync(outputFile)); +}); + +test(`should synthesize audio from text file`, async t => { + t.false(fs.existsSync(outputFile)); + const output = await tools.runAsync( + `${cmd} synthesize-text-file '${files[0].localPath}' --outputFile '${outputFile}'`, + cwd + ); + t.true(output.includes(`Saved synthesized text to local audio file ${outputFile}`)); + t.true(fs.existsSync(outputFile)); +}); + +test(`should synthesize audio from ssml file`, async t => { + t.false(fs.existsSync(outputFile)); + const output = await tools.runAsync( + `${cmd} synthesize-ssml-file '${files[1].localPath}' --outputFile '${outputFile}'`, + cwd + ); + t.true(output.includes(`Saved synthesized text to local audio file ${outputFile}`)); + t.true(fs.existsSync(outputFile)); +}); diff --git a/samples/textToSpeech.js b/samples/textToSpeech.js index 86ff1dd6..2c3895ab 100644 --- a/samples/textToSpeech.js +++ b/samples/textToSpeech.js @@ -42,6 +42,134 @@ function listVoices() { // [END tts_list_voices] } +function synthesizeText(text, outputFile) { + // [START tts_synthesize_text] + const textToSpeech = require('@google-cloud/text-to-speech'); + const fs = require('fs'); + + var client = new textToSpeech.TextToSpeechClient(); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const text = 'Text to synthesize, eg. hello'; + // const outputFile = 'Local path to save audio file to, e.g. output.mp3'; + + var request = { + input: { text: text }, + voice: { languageCode: 'en-US', ssmlGender: 'FEMALE' }, + audioConfig: { audioEncoding: 'MP3' } + }; + + client.synthesizeSpeech(request) + .then(results => { + const audioContent = results[0].audioContent; + + fs.writeFileSync(outputFile, audioContent, 'binary'); + console.log(`Saved synthesized text to local audio file ${outputFile}`); + }) + .catch(err => { + console.error('ERROR:', err); + }); + // [END tts_synthesize_text] +} + +function synthesizeSsml(ssml, outputFile) { + // [START tts_synthesize_ssml] + const textToSpeech = require('@google-cloud/text-to-speech'); + const fs = require('fs'); + + var client = new textToSpeech.TextToSpeechClient(); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const ssml = 'SSML to synthesize, eg. { + const audioContent = results[0].audioContent; + + fs.writeFileSync(outputFile, audioContent, 'binary'); + console.log(`Saved synthesized text to local audio file ${outputFile}`); + }) + .catch(err => { + console.error('ERROR:', err); + }); + // [END tts_synthesize_ssml] +} + +function synthesizeTextFile(textFile, outputFile) { + // [START tts_synthesize_text_file] + const textToSpeech = require('@google-cloud/text-to-speech'); + const fs = require('fs'); + + var client = new textToSpeech.TextToSpeechClient(); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const textFile = 'Local path to text file, eg. input.txt'; + // const outputFile = 'Local path to save audio file to, e.g. output.mp3'; + + var request = { + input: { text: fs.readFileSync(textFile) }, + voice: { languageCode: 'en-US', ssmlGender: 'FEMALE' }, + audioConfig: { audioEncoding: 'MP3' } + }; + + client.synthesizeSpeech(request) + .then(results => { + const audioContent = results[0].audioContent; + + fs.writeFileSync(outputFile, audioContent, 'binary'); + console.log(`Saved synthesized text to local audio file ${outputFile}`); + }) + .catch(err => { + console.error('ERROR:', err); + }); + // [END tts_synthesize_text_file] +} + +function synthesizeSsmlFile(ssmlFile, outputFile) { + // [START tts_synthesize_ssml_file] + const textToSpeech = require('@google-cloud/text-to-speech'); + const fs = require('fs'); + + var client = new textToSpeech.TextToSpeechClient(); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const ssmlFile = 'Local path to SSML file, eg. input.ssml'; + // const outputFile = 'Local path to save audio file to, e.g. output.mp3'; + + var request = { + input: { ssml: fs.readFileSync(ssmlFile) }, + voice: { languageCode: 'en-US', ssmlGender: 'FEMALE' }, + audioConfig: { audioEncoding: 'MP3' } + }; + + client.synthesizeSpeech(request) + .then(results => { + const audioContent = results[0].audioContent; + + fs.writeFileSync(outputFile, audioContent, 'binary'); + console.log(`Saved synthesized text to local audio file ${outputFile}`); + }) + .catch(err => { + console.error('ERROR:', err); + }); + // [END tts_synthesize_ssml_file] +} + require(`yargs`) // eslint-disable-line .demand(1) .command( @@ -50,7 +178,44 @@ require(`yargs`) // eslint-disable-line {}, opts => listVoices() ) + .command( + `synthesize-text `, + `Synthesizes audio file from text`, + {}, + opts => synthesizeText(opts.text, opts.outputFile) + ) + .command( + `synthesize-ssml `, + `Synthesizes audio file from SSML`, + {}, + opts => synthesizeSsml(opts.ssml, opts.outputFile) + ) + .command( + `synthesize-text-file `, + `Synthesizes audio file from text in a file`, + {}, + opts => synthesizeTextFile(opts.textFile, opts.outputFile) + ) + .command( + `synthesize-ssml-file `, + `Synthesizes audio file from SSML in a file`, + {}, + opts => synthesizeSsmlFile(opts.ssmlFile, opts.outputFile) + ) + .options({ + outputFile: { + alias: 'o', + default: 'output.mp3', + global: true, + requiresArg: true, + type: 'string' + } + }) .example(`node $0 list-voices`) + .example(`node $0 synthesize-text "hello" -o hello.mp3`) + .example(`node $0 synthesize-ssml "