From 5e3c0d665ff5057692a60ba35f5846108717766b Mon Sep 17 00:00:00 2001 From: "Benjamin E. Coe" Date: Wed, 18 Mar 2020 21:32:08 -0700 Subject: [PATCH 01/29] feat!: initial library generation (#1) --- media-translation/package.json | 23 +++++++++++++++++ media-translation/quickstart.js | 38 ++++++++++++++++++++++++++++ media-translation/test/quickstart.js | 36 ++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 media-translation/package.json create mode 100644 media-translation/quickstart.js create mode 100644 media-translation/test/quickstart.js diff --git a/media-translation/package.json b/media-translation/package.json new file mode 100644 index 0000000000..cd505f739b --- /dev/null +++ b/media-translation/package.json @@ -0,0 +1,23 @@ +{ + "name": "media-translation-samples", + "private": true, + "license": "Apache-2.0", + "author": "Google LLC", + "engines": { + "node": ">=10" + }, + "files": [ + "*.js" + ], + "scripts": { + "test": "c8 mocha --timeout 600000 test/*.js" + }, + "dependencies": { + "@google-cloud/media-translation": "^0.1.0" + }, + "devDependencies": { + "c8": "^7.0.0", + "chai": "^4.2.0", + "mocha": "^7.0.0" + } +} diff --git a/media-translation/quickstart.js b/media-translation/quickstart.js new file mode 100644 index 0000000000..a10a56d3f1 --- /dev/null +++ b/media-translation/quickstart.js @@ -0,0 +1,38 @@ +// Copyright 2020 Google LLC +// +// 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 +// +// https://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'; + +async function quickstart() { + // parent = 'projects/my-project' // Project to list dashboards for. + // [START media_translation_quickstart] + // Imports the Google Cloud client library + const { + SpeechTranslationServiceClient, + } = require('@google-cloud/media-translation'); + + // Creates a client + const translate = new SpeechTranslationServiceClient(); + + // parent = 'projects/my-project', // Project to list dashboards for. + + // TODO: add an actual sample. + console.info(translate); + + // [END media_translation_quickstart] +} + +const args = process.argv.slice(2); +quickstart(...args).catch(console.error); diff --git a/media-translation/test/quickstart.js b/media-translation/test/quickstart.js new file mode 100644 index 0000000000..6fdf66492e --- /dev/null +++ b/media-translation/test/quickstart.js @@ -0,0 +1,36 @@ +// Copyright 2020 Google LLC +// +// 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 +// +// https://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 {assert} = require('chai'); +const cp = require('child_process'); +const {describe, it} = require('mocha'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +const PROJECT_ID = process.env.GCLOUD_PROJECT; + +describe('Sample Integration Tests', () => { + it('should run quickstart.js', async () => { + const stdout = execSync(`node ./quickstart.js projects/${PROJECT_ID}`, { + cwd, + }); + assert(stdout); + }); +}); From fb08a99b4e4e5e18668e7de210945c2b207592b3 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2020 12:22:03 -0700 Subject: [PATCH 02/29] chore: release 1.0.0 (#4) --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index cd505f739b..3cb8e4f5a5 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^0.1.0" + "@google-cloud/media-translation": "^1.0.0" }, "devDependencies": { "c8": "^7.0.0", From bad953f2e9846426277d046e63941955a6e5e4a8 Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Tue, 24 Mar 2020 13:41:43 -0700 Subject: [PATCH 03/29] feat: adds media translation file, mic samples * feat: adds streaming samples * fix: linter errors * fix: per reviewer * fix: per reviewer * fix: updates package.json --- media-translation/package.json | 3 +- media-translation/quickstart.js | 91 ++++++++++-- media-translation/resources/audio.raw | Bin 0 -> 57958 bytes .../{quickstart.js => quickstart.test.js} | 25 ++-- .../test/translate_from_file.test.js | 31 ++++ media-translation/translate_from_file.js | 101 +++++++++++++ media-translation/translate_from_mic.js | 134 ++++++++++++++++++ 7 files changed, 355 insertions(+), 30 deletions(-) create mode 100644 media-translation/resources/audio.raw rename media-translation/test/{quickstart.js => quickstart.test.js} (56%) create mode 100644 media-translation/test/translate_from_file.test.js create mode 100644 media-translation/translate_from_file.js create mode 100644 media-translation/translate_from_mic.js diff --git a/media-translation/package.json b/media-translation/package.json index 3cb8e4f5a5..017cda4def 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,8 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^1.0.0" + "@google-cloud/media-translation": "^1.0.0", + "node-record-lpcm16": "1.0.1" }, "devDependencies": { "c8": "^7.0.0", diff --git a/media-translation/quickstart.js b/media-translation/quickstart.js index a10a56d3f1..6d32bdc92e 100644 --- a/media-translation/quickstart.js +++ b/media-translation/quickstart.js @@ -1,38 +1,101 @@ -// Copyright 2020 Google LLC -// +// Copyright 2020, Google LLC. // 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 // -// https://www.apache.org/licenses/LICENSE-2.0 +// https://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'; -async function quickstart() { - // parent = 'projects/my-project' // Project to list dashboards for. +/** + * Translate text from an audio file. + * @param {string} filename local path to + * @param {string} encoding the encoding of the audio rate, e.g. Linear16 + * @param {string} sourceLanguage language translating from, as BCP-47 code + * @param {string} targetLanguage languate translating to, as BCP-47 code + */ +function main(filename, encoding, sourceLanguage, targetLanguage) { // [START media_translation_quickstart] - // Imports the Google Cloud client library + const fs = require('fs'); + + // Imports the CLoud Media Translation client library const { SpeechTranslationServiceClient, } = require('@google-cloud/media-translation'); // Creates a client - const translate = new SpeechTranslationServiceClient(); + const client = new SpeechTranslationServiceClient(); + + async function quickstart() { + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const filename = 'Local path to audio file, e.g. /path/to/audio.raw'; + // const encoding = 'Encoding of the audio file, e.g. LINEAR16'; + // const sourceLanguage = 'BCP-47 source language code, e.g. en-US'; + // const targetLangauge = 'BCP-47 target language code, e.g. es-ES'; + + const config = { + audioConfig: { + audioEncoding: encoding, + sourceLanguageCode: sourceLanguage, + targetLanguageCode: targetLanguage, + }, + }; + + // First request needs to have only a streaming config, no data. + const initialRequest = { + streamingConfig: config, + audioContent: null, + }; + + const readStream = fs.createReadStream(filename, { + highWaterMark: 4096, + encoding: 'base64', + }); - // parent = 'projects/my-project', // Project to list dashboards for. + const chunks = []; + readStream + .on('data', chunk => { + const request = { + streamingConfig: config, + audioContent: chunk.toString(), + }; + chunks.push(request); + }) + .on('close', () => { + // Config-only request should be first in stream of requests + stream.write(initialRequest); + for (let i = 0; i < chunks.length; i++) { + stream.write(chunks[i]); + } + stream.end(); + }); - // TODO: add an actual sample. - console.info(translate); + const stream = client.streamingTranslateSpeech().on('data', response => { + const {result} = response; + if (result.textTranslationResult.isFinal) { + console.log( + `\nFinal translation: ${result.textTranslationResult.translation}` + ); + console.log(`Final recognition result: ${result.recognitionResult}`); + } else { + console.log( + `\nPartial translation: ${result.textTranslationResult.translation}` + ); + console.log(`Partial recognition result: ${result.recognitionResult}`); + } + }); - // [END media_translation_quickstart] + // [END media_translation_quickstart] + } + quickstart(); } -const args = process.argv.slice(2); -quickstart(...args).catch(console.error); +main(...process.argv.slice(2)); diff --git a/media-translation/resources/audio.raw b/media-translation/resources/audio.raw new file mode 100644 index 0000000000000000000000000000000000000000..5ebf79d3c9c548f3d08c36e790059f3c2915af37 GIT binary patch literal 57958 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
  • ?dZ^!ab%qlspp&C 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 literal 0 HcmV?d00001 diff --git a/media-translation/test/quickstart.js b/media-translation/test/quickstart.test.js similarity index 56% rename from media-translation/test/quickstart.js rename to media-translation/test/quickstart.test.js index 6fdf66492e..c031c44129 100644 --- a/media-translation/test/quickstart.js +++ b/media-translation/test/quickstart.test.js @@ -1,36 +1,31 @@ -// Copyright 2020 Google LLC +// Copyright 2017 Google LLC // // 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 // -// https://www.apache.org/licenses/LICENSE-2.0 +// https://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 {assert} = require('chai'); -const cp = require('child_process'); const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const cmd = 'node quickstart.js'; -const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); - -const cwd = path.join(__dirname, '..'); - -const PROJECT_ID = process.env.GCLOUD_PROJECT; +const filePath = path.join(__dirname, '..', 'resources/audio.raw'); +const exec = cmd => execSync(cmd, {encoding: 'utf-8'}); -describe('Sample Integration Tests', () => { - it('should run quickstart.js', async () => { - const stdout = execSync(`node ./quickstart.js projects/${PROJECT_ID}`, { - cwd, - }); - assert(stdout); +describe('Quickstart', () => { + it('should translate from a streamed file', async () => { + const stdout = exec(`${cmd} ${filePath} linear16 en-US es-ES`); + assert.include(stdout, 'Partial translation'); }); }); diff --git a/media-translation/test/translate_from_file.test.js b/media-translation/test/translate_from_file.test.js new file mode 100644 index 0000000000..193b3b6555 --- /dev/null +++ b/media-translation/test/translate_from_file.test.js @@ -0,0 +1,31 @@ +// Copyright 2017 Google LLC +// +// 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 +// +// https://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 {assert} = require('chai'); +const {describe, it} = require('mocha'); +const execSync = require('child_process').execSync; +const cmd = 'node translate_from_file.js'; + +const filePath = path.join(__dirname, '..', 'resources/audio.raw'); +const exec = cmd => execSync(cmd, {encoding: 'utf-8'}); + +describe('MediaTranslation', () => { + it('should translate from a streamed file', async () => { + const stdout = exec(`${cmd} ${filePath} linear16 en-US es-ES`); + assert.include(stdout, 'Partial translation'); + }); +}); diff --git a/media-translation/translate_from_file.js b/media-translation/translate_from_file.js new file mode 100644 index 0000000000..896eafc7cd --- /dev/null +++ b/media-translation/translate_from_file.js @@ -0,0 +1,101 @@ +// Copyright 2020, Google LLC. +// 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 +// +// https://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'; + +/** + * Translate text from an audio file. + * @param {string} filename local path to + * @param {string} encoding the encoding of the audio rate, e.g. Linear16 + * @param {string} sourceLanguage language translating from, as BCP-47 code + * @param {string} targetLanguage languate translating to, as BCP-47 code + */ +function main(filename, encoding, sourceLanguage, targetLanguage) { + // [START media_translation_translate_from_file] + const fs = require('fs'); + + // Imports the CLoud Media Translation client library + const { + SpeechTranslationServiceClient, + } = require('@google-cloud/media-translation'); + + // Creates a client + const client = new SpeechTranslationServiceClient(); + + async function translate_from_file() { + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const filename = 'Local path to audio file, e.g. /path/to/audio.raw'; + // const encoding = 'Encoding of the audio file, e.g. LINEAR16'; + // const sourceLanguage = 'BCP-47 source language code, e.g. en-US'; + // const targetLangauge = 'BCP-47 target language code, e.g. es-ES'; + + const config = { + audioConfig: { + audioEncoding: encoding, + sourceLanguageCode: sourceLanguage, + targetLanguageCode: targetLanguage, + }, + }; + + // First request needs to have only a streaming config, no data. + const initialRequest = { + streamingConfig: config, + audioContent: null, + }; + + const readStream = fs.createReadStream(filename, { + highWaterMark: 4096, + encoding: 'base64', + }); + + const chunks = []; + readStream + .on('data', chunk => { + const request = { + streamingConfig: config, + audioContent: chunk.toString(), + }; + chunks.push(request); + }) + .on('close', () => { + // Config-only request should be first in stream of requests + stream.write(initialRequest); + for (let i = 0; i < chunks.length; i++) { + stream.write(chunks[i]); + } + stream.end(); + }); + + const stream = client.streamingTranslateSpeech().on('data', response => { + const {result} = response; + if (result.textTranslationResult.isFinal) { + console.log( + `\nFinal translation: ${result.textTranslationResult.translation}` + ); + console.log(`Final recognition result: ${result.recognitionResult}`); + } else { + console.log( + `\nPartial translation: ${result.textTranslationResult.translation}` + ); + console.log(`Partial recognition result: ${result.recognitionResult}`); + } + }); + + // [END media_translation_translate_from_file] + } + translate_from_file(); +} + +main(...process.argv.slice(2)); diff --git a/media-translation/translate_from_mic.js b/media-translation/translate_from_mic.js new file mode 100644 index 0000000000..7161b5b31f --- /dev/null +++ b/media-translation/translate_from_mic.js @@ -0,0 +1,134 @@ +// Copyright 2020, Google LLC. +// 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 +// +// https://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'; + +/** + * This application demonstrates how to perform basic translation operations + * with the Google Cloud Media Translation API. + * + * Note: Correct microphone settings is required: check enclosed link, and make + * sure the following conditions are met: + * 1. SoX must be installed and available in your $PATH- it can be found here: + * http://sox.sourceforge.net/ + * 2. Microphone must be working + * 3. Encoding, sampleRateHertz, and # of channels must match header of audio file you're + * recording to. + * 4. Get Node-Record-lpcm16 https://www.npmjs.com/package/node-record-lpcm16 + * More Info: https://cloud.google.com/speech-to-text/docs/streaming-recognize + */ + +/** + * Translates audio streaming from a microphone + * @param {string} encoding the audio encoding codec + * @param {string} sampleRateHertz the sampling rate of the audio stream + * @param {string} sourceLanguageCode the language to translate from + * @param {string} targetLanguageCode the language to translate to + */ +function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { + sampleRateHertz = Number(sampleRateHertz); + + // [START media_translation_translate_from_mic] + + // Node-Record-lpcm16 + const recorder = require('node-record-lpcm16'); + + // Imports the Cloud Media Translation client library + const { + SpeechTranslationServiceClient, + } = require('@google-cloud/media-translation'); + + // Creates a client + const client = new SpeechTranslationServiceClient(); + + function translateFromMicrophone() { + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + //const encoding = 'linear16'; + //const sampleRateHertz = 16000; + //const sourceLanguage = 'Language to translate from, as BCP-47 locale'; + //const targetLanguage = 'Language to translate to, as BCP-47 locale'; + + const config = { + audioConfig: { + audioEncoding: encoding, + sourceLanguageCode: sourceLanguage, + targetLanguageCode: targetLanguage, + }, + }; + + // First request needs to have only a streaming config, no data. + const initialRequest = { + streamingConfig: config, + audioContent: null, + }; + + // Create a recognize stream + const stream = client + .streamingTranslateSpeech() + .on('error', e => { + if (e.code && e.code === 4) { + console.log('Streaming translation reached its deadline.'); + } else { + console.log(e); + } + }) + .on('data', response => { + const {result} = response; + if (result.textTranslationResult.isFinal) { + console.log( + `\nFinal translation: ${result.textTranslationResult.translation}` + ); + console.log(`Final recognition result: ${result.recognitionResult}`); + } else { + console.log( + `\nPartial translation: ${result.textTranslationResult.translation}` + ); + console.log( + `Partial recognition result: ${result.recognitionResult}` + ); + } + }); + + let isFirst = true; + // Start recording and send microphone input to the Media Translation API + recorder + .record({ + sampleRateHertz: sampleRateHertz, + threshold: 0, //silence threshold + recordProgram: 'rec', + silence: '5.0', //seconds of silence before ending + }) + .stream() + .on('data', chunk => { + if (isFirst) { + stream.write(initialRequest); + isFirst = false; + } + const request = { + streamingConfig: config, + audioContent: chunk.toString('base64'), + }; + stream.write(request); + }) + .on('error', console.log) + .pipe(stream); + + console.log('Listening, press Ctrl+C to stop.'); + } + + translateFromMicrophone(); + + // [END media_translation_translate_from_mic] +} +main(...process.argv.slice(2)); From 49a3b7110d758a70a7bb55bedbb55dafed9e4162 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2020 17:05:34 -0700 Subject: [PATCH 04/29] chore: release 2.0.0 (#18) * updated CHANGELOG.md [ci skip] * updated package.json [ci skip] * updated samples/package.json [ci skip] Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 017cda4def..8d6089f04e 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^1.0.0", + "@google-cloud/media-translation": "^2.0.0", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 2cfc3fb39535796ff4a86aae610e4eaa3f45d943 Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Mon, 13 Apr 2020 09:29:39 -0700 Subject: [PATCH 05/29] feat: adds 'single_utterance' to stream from file sample (#20) * feat: adds streaming samples * fix: updates package.json Co-authored-by: Justin Beckwith --- media-translation/translate_from_file.js | 1 + 1 file changed, 1 insertion(+) diff --git a/media-translation/translate_from_file.js b/media-translation/translate_from_file.js index 896eafc7cd..f8c9af9137 100644 --- a/media-translation/translate_from_file.js +++ b/media-translation/translate_from_file.js @@ -47,6 +47,7 @@ function main(filename, encoding, sourceLanguage, targetLanguage) { sourceLanguageCode: sourceLanguage, targetLanguageCode: targetLanguage, }, + single_utterance: true, }; // First request needs to have only a streaming config, no data. From a89f6ac1c54561ece6b2cb939b20e1acca33c45a Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Wed, 27 May 2020 15:34:03 -0700 Subject: [PATCH 06/29] fix: streaming mic sample --- media-translation/translate_from_mic.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/media-translation/translate_from_mic.js b/media-translation/translate_from_mic.js index 7161b5b31f..b9557c3b2e 100644 --- a/media-translation/translate_from_mic.js +++ b/media-translation/translate_from_mic.js @@ -120,9 +120,7 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { audioContent: chunk.toString('base64'), }; stream.write(request); - }) - .on('error', console.log) - .pipe(stream); + }); console.log('Listening, press Ctrl+C to stop.'); } From 52e7a586a87e428dd68667625a8cc616ec27f465 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2020 19:38:13 +0000 Subject: [PATCH 07/29] chore: release 2.1.0 (#27) :robot: I have created a release \*beep\* \*boop\* --- ## [2.1.0](https://www.github.com/googleapis/nodejs-media-translation/compare/v2.0.0...v2.1.0) (2020-06-04) ### Features * adds 'single_utterance' to stream from file sample ([#20](https://www.github.com/googleapis/nodejs-media-translation/issues/20)) ([9455e20](https://www.github.com/googleapis/nodejs-media-translation/commit/9455e207de7ff9c9f72936dd3a908b694eee59fe)) ### Bug Fixes * regen protos and tests, formatting ([#39](https://www.github.com/googleapis/nodejs-media-translation/issues/39)) ([684f355](https://www.github.com/googleapis/nodejs-media-translation/commit/684f355cbecec36c18763b59ddec613c0ea097a9)) * remove eslint, update gax, fix generated protos, run the generator ([#24](https://www.github.com/googleapis/nodejs-media-translation/issues/24)) ([3aca62a](https://www.github.com/googleapis/nodejs-media-translation/commit/3aca62aed3a4e49e4892f9ad29c3d0166c57fa56)) * streaming mic sample ([488c235](https://www.github.com/googleapis/nodejs-media-translation/commit/488c23522b31e26b419c9a4cb5829969e9050928)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 8d6089f04e..420207c0bb 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.0.0", + "@google-cloud/media-translation": "^2.1.0", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 5163fdee693731450ef2f5d2313a6fee4b45442c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 11 Jun 2020 17:46:40 +0200 Subject: [PATCH 08/29] chore(deps): update dependency mocha to v8 (#49) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [mocha](https://mochajs.org/) ([source](https://togithub.com/mochajs/mocha)) | devDependencies | major | [`^7.0.0` -> `^8.0.0`](https://renovatebot.com/diffs/npm/mocha/7.2.0/8.0.1) | --- ### Release Notes
    mochajs/mocha ### [`v8.0.1`](https://togithub.com/mochajs/mocha/blob/master/CHANGELOG.md#​801--2020-06-10) [Compare Source](https://togithub.com/mochajs/mocha/compare/v8.0.0...v8.0.1) The obligatory patch after a major. #### :bug: Fixes - [#​4328](https://togithub.com/mochajs/mocha/issues/4328): Fix `--parallel` when combined with `--watch` ([**@​boneskull**](https://togithub.com/boneskull)) ### [`v8.0.0`](https://togithub.com/mochajs/mocha/blob/master/CHANGELOG.md#​800--2020-06-10) [Compare Source](https://togithub.com/mochajs/mocha/compare/v7.2.0...v8.0.0) In this major release, Mocha adds the ability to _run tests in parallel_. Better late than never! Please note the **breaking changes** detailed below. Let's welcome [**@​giltayar**](https://togithub.com/giltayar) and [**@​nicojs**](https://togithub.com/nicojs) to the maintenance team! #### :boom: Breaking Changes - [#​4164](https://togithub.com/mochajs/mocha/issues/4164): **Mocha v8.0.0 now requires Node.js v10.0.0 or newer.** Mocha no longer supports the Node.js v8.x line ("Carbon"), which entered End-of-Life at the end of 2019 ([**@​UlisesGascon**](https://togithub.com/UlisesGascon)) - [#​4175](https://togithub.com/mochajs/mocha/issues/4175): Having been deprecated with a warning since v7.0.0, **`mocha.opts` is no longer supported** ([**@​juergba**](https://togithub.com/juergba)) :sparkles: **WORKAROUND:** Replace `mocha.opts` with a [configuration file](https://mochajs.org/#configuring-mocha-nodejs). - [#​4260](https://togithub.com/mochajs/mocha/issues/4260): Remove `enableTimeout()` (`this.enableTimeout()`) from the context object ([**@​craigtaub**](https://togithub.com/craigtaub)) :sparkles: **WORKAROUND:** Replace usage of `this.enableTimeout(false)` in your tests with `this.timeout(0)`. - [#​4315](https://togithub.com/mochajs/mocha/issues/4315): The `spec` option no longer supports a comma-delimited list of files ([**@​juergba**](https://togithub.com/juergba)) :sparkles: **WORKAROUND**: Use an array instead (e.g., `"spec": "foo.js,bar.js"` becomes `"spec": ["foo.js", "bar.js"]`). - [#​4309](https://togithub.com/mochajs/mocha/issues/4309): Drop support for Node.js v13.x line, which is now End-of-Life ([**@​juergba**](https://togithub.com/juergba)) - [#​4282](https://togithub.com/mochajs/mocha/issues/4282): `--forbid-only` will throw an error even if exclusive tests are avoided via `--grep` or other means ([**@​arvidOtt**](https://togithub.com/arvidOtt)) - [#​4223](https://togithub.com/mochajs/mocha/issues/4223): The context object's `skip()` (`this.skip()`) in a "before all" (`before()`) hook will no longer execute subsequent sibling hooks, in addition to hooks in child suites ([**@​juergba**](https://togithub.com/juergba)) - [#​4178](https://togithub.com/mochajs/mocha/issues/4178): Remove previously soft-deprecated APIs ([**@​wnghdcjfe**](https://togithub.com/wnghdcjfe)): - `Mocha.prototype.ignoreLeaks()` - `Mocha.prototype.useColors()` - `Mocha.prototype.useInlineDiffs()` - `Mocha.prototype.hideDiff()` #### :tada: Enhancements - [#​4245](https://togithub.com/mochajs/mocha/issues/4245): Add ability to run tests in parallel for Node.js (see [docs](https://mochajs.org/#parallel-tests)) ([**@​boneskull**](https://togithub.com/boneskull)) :exclamation: See also [#​4244](https://togithub.com/mochajs/mocha/issues/4244); [Root Hook Plugins (docs)](https://mochajs.org/#root-hook-plugins) -- _root hooks must be defined via Root Hook Plugins to work in parallel mode_ - [#​4304](https://togithub.com/mochajs/mocha/issues/4304): `--require` now works with ES modules ([**@​JacobLey**](https://togithub.com/JacobLey)) - [#​4299](https://togithub.com/mochajs/mocha/issues/4299): In some circumstances, Mocha can run ES modules under Node.js v10 -- _use at your own risk!_ ([**@​giltayar**](https://togithub.com/giltayar)) #### :book: Documentation - [#​4246](https://togithub.com/mochajs/mocha/issues/4246): Add documentation for parallel mode and Root Hook plugins ([**@​boneskull**](https://togithub.com/boneskull)) #### :bug: Fixes (All bug fixes in Mocha v8.0.0 are also breaking changes, and are listed above)
    --- ### Renovate configuration :date: **Schedule**: "after 9am and before 3pm" (UTC). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. :no_bell: **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/nodejs-media-translation). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 420207c0bb..1c40036de2 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -19,6 +19,6 @@ "devDependencies": { "c8": "^7.0.0", "chai": "^4.2.0", - "mocha": "^7.0.0" + "mocha": "^8.0.0" } } From 41ee3ad38bfc77260b29ed3525dcca5d3187a478 Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Tue, 16 Jun 2020 15:06:16 -0700 Subject: [PATCH 09/29] feat(samples): demonstrate real-time conversation translation (#48) This PR improves the Media Translation microphone sample so that it is more aware of "state." When the API returns the SpeechEventType.END_OF_SINGLE_UTTERANCE event, the stream is closed and the user can initiate another call to the API. The following region tags are affected: media_translation_translate_from_mic --- media-translation/translate_from_mic.js | 67 ++++++++++++++++--------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/media-translation/translate_from_mic.js b/media-translation/translate_from_mic.js index b9557c3b2e..73339c9290 100644 --- a/media-translation/translate_from_mic.js +++ b/media-translation/translate_from_mic.js @@ -39,6 +39,24 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { // [START media_translation_translate_from_mic] + // Allow user input from terminal + const readline = require('readline'); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + function doTranslationLoop() { + rl.question("Press any key to translate or 'q' to quit: ", answer => { + if (answer.toLowerCase() === 'q') { + rl.close(); + } else { + translateFromMicrophone(); + } + }); + } + // Node-Record-lpcm16 const recorder = require('node-record-lpcm16'); @@ -58,6 +76,7 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { //const sampleRateHertz = 16000; //const sourceLanguage = 'Language to translate from, as BCP-47 locale'; //const targetLanguage = 'Language to translate to, as BCP-47 locale'; + console.log('Begin speaking ...'); const config = { audioConfig: { @@ -65,6 +84,7 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { sourceLanguageCode: sourceLanguage, targetLanguageCode: targetLanguage, }, + singleUtterance: true, }; // First request needs to have only a streaming config, no data. @@ -73,6 +93,8 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { audioContent: null, }; + let currentTranslation = ''; + let currentRecognition = ''; // Create a recognize stream const stream = client .streamingTranslateSpeech() @@ -84,31 +106,30 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { } }) .on('data', response => { - const {result} = response; - if (result.textTranslationResult.isFinal) { - console.log( - `\nFinal translation: ${result.textTranslationResult.translation}` - ); - console.log(`Final recognition result: ${result.recognitionResult}`); + const {result, speechEventType} = response; + if (speechEventType === 'END_OF_SINGLE_UTTERANCE') { + console.log(`\nFinal translation: ${currentTranslation}`); + console.log(`Final recognition result: ${currentRecognition}`); + + stream.destroy(); + recording.stop(); } else { - console.log( - `\nPartial translation: ${result.textTranslationResult.translation}` - ); - console.log( - `Partial recognition result: ${result.recognitionResult}` - ); + currentTranslation = result.textTranslationResult.translation; + currentRecognition = result.recognitionResult; + console.log(`\nPartial translation: ${currentTranslation}`); + console.log(`Partial recognition result: ${currentRecognition}`); } }); let isFirst = true; // Start recording and send microphone input to the Media Translation API - recorder - .record({ - sampleRateHertz: sampleRateHertz, - threshold: 0, //silence threshold - recordProgram: 'rec', - silence: '5.0', //seconds of silence before ending - }) + const recording = recorder.record({ + sampleRateHertz: sampleRateHertz, + threshold: 0, //silence threshold + recordProgram: 'rec', + silence: '5.0', //seconds of silence before ending + }); + recording .stream() .on('data', chunk => { if (isFirst) { @@ -120,13 +141,13 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { audioContent: chunk.toString('base64'), }; stream.write(request); + }) + .on('close', () => { + doTranslationLoop(); }); - - console.log('Listening, press Ctrl+C to stop.'); } - translateFromMicrophone(); - + doTranslationLoop(); // [END media_translation_translate_from_mic] } main(...process.argv.slice(2)); From d5617ba400a3b2d8ecbca22d18d20e964863aa95 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:05:47 -0700 Subject: [PATCH 10/29] chore: release 2.2.0 (#47) --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 1c40036de2..1ecad5178a 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.1.0", + "@google-cloud/media-translation": "^2.2.0", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 05e2b56fd1b71935b3da8a4343aff87a99a63e58 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Nov 2020 14:28:05 -0800 Subject: [PATCH 11/29] chore: release 2.2.1 (#95) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 1ecad5178a..ee2eeeb011 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.2.0", + "@google-cloud/media-translation": "^2.2.1", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From eee3583c5b155aea31bc918ac0ec9ab907d7cdcf Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 19:42:13 +0000 Subject: [PATCH 12/29] chore: release 2.2.2 (#98) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.2](https://www.github.com/googleapis/nodejs-media-translation/compare/v2.2.1...v2.2.2) (2020-11-25) ### Bug Fixes * **browser:** check for fetch on window ([c0245c5](https://www.github.com/googleapis/nodejs-media-translation/commit/c0245c54d8c45f1f3171e9066bc7bab3c4162b69)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index ee2eeeb011..4253c36bfa 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.2.1", + "@google-cloud/media-translation": "^2.2.2", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From cda9db5e144154b32ee504e5f7889f0403b67829 Mon Sep 17 00:00:00 2001 From: awoehler Date: Wed, 3 Feb 2021 10:58:00 -0900 Subject: [PATCH 13/29] =?UTF-8?q?fix:=20Added=20check=20to=20see=20if=20st?= =?UTF-8?q?ream=20has=20been=20destroyed=20before=20writing=20result?= =?UTF-8?q?=E2=80=A6=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- media-translation/translate_from_mic.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/media-translation/translate_from_mic.js b/media-translation/translate_from_mic.js index 73339c9290..1ea70744b4 100644 --- a/media-translation/translate_from_mic.js +++ b/media-translation/translate_from_mic.js @@ -140,7 +140,9 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { streamingConfig: config, audioContent: chunk.toString('base64'), }; - stream.write(request); + if (!stream.destroyed) { + stream.write(request); + } }) .on('close', () => { doTranslationLoop(); From 850a88f1775e25cc7a182ac51ba296a9d834829c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 17:28:50 -0800 Subject: [PATCH 14/29] chore: release 2.2.3 (#109) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 4253c36bfa..028680f7a9 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.2.2", + "@google-cloud/media-translation": "^2.2.3", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 2d52a661eb8ddeccf1fe7c0bc55c1237acd6994c Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Fri, 18 Jun 2021 13:07:24 -0700 Subject: [PATCH 15/29] samples: fixes a typo (#154) --- media-translation/translate_from_file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/translate_from_file.js b/media-translation/translate_from_file.js index f8c9af9137..472ff82f30 100644 --- a/media-translation/translate_from_file.js +++ b/media-translation/translate_from_file.js @@ -39,7 +39,7 @@ function main(filename, encoding, sourceLanguage, targetLanguage) { // const filename = 'Local path to audio file, e.g. /path/to/audio.raw'; // const encoding = 'Encoding of the audio file, e.g. LINEAR16'; // const sourceLanguage = 'BCP-47 source language code, e.g. en-US'; - // const targetLangauge = 'BCP-47 target language code, e.g. es-ES'; + // const targetLanguage = 'BCP-47 target language code, e.g. es-ES'; const config = { audioConfig: { From fcb5d38e21d1ca2e897ea639b68f72c954f9c2f0 Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Tue, 22 Jun 2021 11:21:09 -0700 Subject: [PATCH 16/29] samples: another typo in comments (#155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: another typo in comments * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/master/packages/owl-bot/README.md Co-authored-by: Owl Bot --- media-translation/quickstart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/quickstart.js b/media-translation/quickstart.js index 6d32bdc92e..1232e4fdaa 100644 --- a/media-translation/quickstart.js +++ b/media-translation/quickstart.js @@ -39,7 +39,7 @@ function main(filename, encoding, sourceLanguage, targetLanguage) { // const filename = 'Local path to audio file, e.g. /path/to/audio.raw'; // const encoding = 'Encoding of the audio file, e.g. LINEAR16'; // const sourceLanguage = 'BCP-47 source language code, e.g. en-US'; - // const targetLangauge = 'BCP-47 target language code, e.g. es-ES'; + // const targetLanguage = 'BCP-47 target language code, e.g. es-ES'; const config = { audioConfig: { From a98aec7dfc1336c29cb99eb69b9a34cb6701c091 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 25 Jun 2021 09:20:55 -0700 Subject: [PATCH 17/29] chore: release 2.3.0 (#159) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 028680f7a9..80bad208f8 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.2.3", + "@google-cloud/media-translation": "^2.3.0", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From e07d9c13a3440948cef275ec31eb5799f0ba1f4d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 30 Jun 2021 16:28:27 +0000 Subject: [PATCH 18/29] chore: release 2.3.1 (#163) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.1](https://www.github.com/googleapis/nodejs-media-translation/compare/v2.3.0...v2.3.1) (2021-06-30) ### Bug Fixes * **deps:** google-gax v2.17.0 with mTLS ([#161](https://www.github.com/googleapis/nodejs-media-translation/issues/161)) ([bbd1415](https://www.github.com/googleapis/nodejs-media-translation/commit/bbd141565364bc0bbb15f1240d98683033da3001)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 80bad208f8..1e08b6247e 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.3.0", + "@google-cloud/media-translation": "^2.3.1", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 4a8eaa5e87eabe07d5247c6074c1dd800e2b56ad Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 23:00:53 +0000 Subject: [PATCH 19/29] chore: release 2.3.2 (#165) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.2](https://www.github.com/googleapis/nodejs-media-translation/compare/v2.3.1...v2.3.2) (2021-07-12) ### Bug Fixes * **deps:** google-gax v2.17.1 ([#164](https://www.github.com/googleapis/nodejs-media-translation/issues/164)) ([6c7caad](https://www.github.com/googleapis/nodejs-media-translation/commit/6c7caadc989cfe0e898ce2034d2fbac71208d888)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 1e08b6247e..b9fe45b762 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.3.1", + "@google-cloud/media-translation": "^2.3.2", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From a848ad3c40f47a84f0cd5a5ef57103b229fe88e1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 21 Jul 2021 00:32:15 +0000 Subject: [PATCH 20/29] chore: release 2.3.3 (#167) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.3](https://www.github.com/googleapis/nodejs-media-translation/compare/v2.3.2...v2.3.3) (2021-07-21) ### Bug Fixes * Updating WORKSPACE files to use the newest version of the Typescript generator. ([#166](https://www.github.com/googleapis/nodejs-media-translation/issues/166)) ([a1899d2](https://www.github.com/googleapis/nodejs-media-translation/commit/a1899d2f2f7bfa0894c0b1823ce75759638ff91b)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index b9fe45b762..e8285d5646 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.3.2", + "@google-cloud/media-translation": "^2.3.3", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From de19fee7ba2f53372432d6538320efc40caf0118 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 17 Aug 2021 03:26:38 +0000 Subject: [PATCH 21/29] chore: release 2.3.4 (#175) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.4](https://www.github.com/googleapis/nodejs-media-translation/compare/v2.3.3...v2.3.4) (2021-08-17) ### Bug Fixes * **deps:** google-gax v2.24.1 ([#174](https://www.github.com/googleapis/nodejs-media-translation/issues/174)) ([b90cf10](https://www.github.com/googleapis/nodejs-media-translation/commit/b90cf1034235ab0416011de7a1b77afed5597dfc)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index e8285d5646..e714fd35ad 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.3.3", + "@google-cloud/media-translation": "^2.3.4", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 3b19dd4c6b874b69fc58822df44659b32619346f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 08:08:43 -0700 Subject: [PATCH 22/29] chore: release 2.4.0 (#177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: release 2.4.0 * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index e714fd35ad..ad10a4d34c 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.3.4", + "@google-cloud/media-translation": "^2.4.0", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From e96e2fa1e75ac721a0f22c10348710fe9e515499 Mon Sep 17 00:00:00 2001 From: sofisl <55454395+sofisl@users.noreply.github.com> Date: Wed, 18 May 2022 10:52:29 -0700 Subject: [PATCH 23/29] build!: update library to use Node 12 (#225) * build!: Update library to use Node 12 Co-authored-by: Owl Bot --- media-translation/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/media-translation/package.json b/media-translation/package.json index ad10a4d34c..8a0de83ba1 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -4,7 +4,7 @@ "license": "Apache-2.0", "author": "Google LLC", "engines": { - "node": ">=10" + "node": ">=12.0.0" }, "files": [ "*.js" @@ -21,4 +21,4 @@ "chai": "^4.2.0", "mocha": "^8.0.0" } -} +} \ No newline at end of file From 1842574c7f3585fc221650d392f670863db9ab67 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 20 Jun 2022 16:10:46 -0400 Subject: [PATCH 24/29] chore(main): release 3.0.0 (#227) See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot Co-authored-by: Benjamin E. Coe --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 8a0de83ba1..40a84cddc4 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^2.4.0", + "@google-cloud/media-translation": "^3.0.0", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From ca9d240202becedd5750ff174291b972bb082105 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 30 Jun 2022 19:10:14 +0000 Subject: [PATCH 25/29] chore(main): release 3.0.1 (#234) :robot: I have created a release *beep* *boop* --- ## [3.0.1](https://github.com/googleapis/nodejs-media-translation/compare/v3.0.0...v3.0.1) (2022-06-30) ### Bug Fixes * **docs:** describe fallback rest option ([#233](https://github.com/googleapis/nodejs-media-translation/issues/233)) ([f83d3ed](https://github.com/googleapis/nodejs-media-translation/commit/f83d3ed1a04e4d382071df6202a1b2fb394ee2d0)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 40a84cddc4..73702b8a04 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^3.0.0", + "@google-cloud/media-translation": "^3.0.1", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 8a711a118292ec8c4ac7085c59d4990c1ba60741 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 26 Aug 2022 12:31:25 -0700 Subject: [PATCH 26/29] chore(main): release 3.0.2 (#245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(main): release 3.0.2 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 73702b8a04..a044e1252d 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^3.0.1", + "@google-cloud/media-translation": "^3.0.2", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From ca62be6ae2621584f5f828e101695836cc0e9168 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 17:50:11 -0400 Subject: [PATCH 27/29] chore(main): release 3.0.3 (#250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(main): release 3.0.3 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index a044e1252d..42153d5fe5 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^3.0.2", + "@google-cloud/media-translation": "^3.0.3", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From cad25b125006203d37bedbd8c247b266d8ce29ba Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 22 Sep 2022 14:48:56 -0700 Subject: [PATCH 28/29] chore(main): release 3.0.4 (#252) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(main): release 3.0.4 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- media-translation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media-translation/package.json b/media-translation/package.json index 42153d5fe5..9759a14c1a 100644 --- a/media-translation/package.json +++ b/media-translation/package.json @@ -13,7 +13,7 @@ "test": "c8 mocha --timeout 600000 test/*.js" }, "dependencies": { - "@google-cloud/media-translation": "^3.0.3", + "@google-cloud/media-translation": "^3.0.4", "node-record-lpcm16": "1.0.1" }, "devDependencies": { From 4e10b570ba97f0bd8b505b5dafb86bf99cf3260e Mon Sep 17 00:00:00 2001 From: Karl Weinmeister Date: Tue, 8 Nov 2022 15:27:39 -0600 Subject: [PATCH 29/29] add CI workflow and remove hyphen --- .github/workflows/mediatranslation.yaml | 67 ++++++++++++++++++ .github/workflows/workflows.json | 1 + .../package.json | 2 +- .../quickstart.js | 4 +- .../resources/audio.raw | Bin .../test/quickstart.test.js | 0 .../test/translate_from_file.test.js | 0 .../translate_from_file.js | 4 +- .../translate_from_mic.js | 4 +- 9 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/mediatranslation.yaml rename {media-translation => mediatranslation}/package.json (91%) rename {media-translation => mediatranslation}/quickstart.js (97%) rename {media-translation => mediatranslation}/resources/audio.raw (100%) rename {media-translation => mediatranslation}/test/quickstart.test.js (100%) rename {media-translation => mediatranslation}/test/translate_from_file.test.js (100%) rename {media-translation => mediatranslation}/translate_from_file.js (96%) rename {media-translation => mediatranslation}/translate_from_mic.js (98%) diff --git a/.github/workflows/mediatranslation.yaml b/.github/workflows/mediatranslation.yaml new file mode 100644 index 0000000000..8fd636337c --- /dev/null +++ b/.github/workflows/mediatranslation.yaml @@ -0,0 +1,67 @@ +name: mediatranslation +on: + push: + branches: + - main + paths: + - 'mediatranslation/**' + pull_request: + paths: + - 'mediatranslation/**' + pull_request_target: + types: [labeled] + schedule: + - cron: '0 0 * * 0' +jobs: + test: + if: ${{ github.event.action != 'labeled' || github.event.label.name == 'actions:force-run' }} + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: 'write' + pull-requests: 'write' + id-token: 'write' + steps: + - uses: actions/checkout@v3.1.0 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + - uses: 'google-github-actions/auth@v0.8.3' + with: + workload_identity_provider: 'projects/1046198160504/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'kokoro-system-test@long-door-651.iam.gserviceaccount.com' + create_credentials_file: 'true' + access_token_lifetime: 600s + - uses: actions/setup-node@v3.5.1 + with: + node-version: 16 + - run: npm install + working-directory: mediatranslation + - run: npm test + working-directory: mediatranslation + env: + MOCHA_REPORTER_SUITENAME: mediatranslation + MOCHA_REPORTER_OUTPUT: mediatranslation_sponge_log.xml + MOCHA_REPORTER: xunit + - if: ${{ github.event.action == 'labeled' && github.event.label.name == 'actions:force-run' }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + try { + await github.rest.issues.removeLabel({ + name: 'actions:force-run', + owner: 'GoogleCloudPlatform', + repo: 'nodejs-docs-samples', + issue_number: context.payload.pull_request.number + }); + } catch (e) { + if (!e.message.includes('Label does not exist')) { + throw e; + } + } + - if: ${{ github.event_name == 'schedule'}} + run: | + curl https://github.com/googleapis/repo-automation-bots/releases/download/flakybot-1.1.0/flakybot -o flakybot -s -L + chmod +x ./flakybot + ./flakybot --repo GoogleCloudPlatform/nodejs-docs-samples --commit_hash ${{github.sha}} --build_url https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} diff --git a/.github/workflows/workflows.json b/.github/workflows/workflows.json index 149b84bbb7..5fc1908212 100644 --- a/.github/workflows/workflows.json +++ b/.github/workflows/workflows.json @@ -40,6 +40,7 @@ "healthcare/dicom", "healthcare/fhir", "healthcare/hl7v2", + "mediatranslation", "monitoring/opencensus", "monitoring/prometheus", "datacatalog/cloud-client", diff --git a/media-translation/package.json b/mediatranslation/package.json similarity index 91% rename from media-translation/package.json rename to mediatranslation/package.json index 9759a14c1a..3ffacb174d 100644 --- a/media-translation/package.json +++ b/mediatranslation/package.json @@ -1,5 +1,5 @@ { - "name": "media-translation-samples", + "name": "mediatranslation-samples", "private": true, "license": "Apache-2.0", "author": "Google LLC", diff --git a/media-translation/quickstart.js b/mediatranslation/quickstart.js similarity index 97% rename from media-translation/quickstart.js rename to mediatranslation/quickstart.js index 1232e4fdaa..7e73b0f228 100644 --- a/media-translation/quickstart.js +++ b/mediatranslation/quickstart.js @@ -21,7 +21,7 @@ * @param {string} targetLanguage languate translating to, as BCP-47 code */ function main(filename, encoding, sourceLanguage, targetLanguage) { - // [START media_translation_quickstart] + // [START mediatranslation_quickstart] const fs = require('fs'); // Imports the CLoud Media Translation client library @@ -93,7 +93,7 @@ function main(filename, encoding, sourceLanguage, targetLanguage) { } }); - // [END media_translation_quickstart] + // [END mediatranslation_quickstart] } quickstart(); } diff --git a/media-translation/resources/audio.raw b/mediatranslation/resources/audio.raw similarity index 100% rename from media-translation/resources/audio.raw rename to mediatranslation/resources/audio.raw diff --git a/media-translation/test/quickstart.test.js b/mediatranslation/test/quickstart.test.js similarity index 100% rename from media-translation/test/quickstart.test.js rename to mediatranslation/test/quickstart.test.js diff --git a/media-translation/test/translate_from_file.test.js b/mediatranslation/test/translate_from_file.test.js similarity index 100% rename from media-translation/test/translate_from_file.test.js rename to mediatranslation/test/translate_from_file.test.js diff --git a/media-translation/translate_from_file.js b/mediatranslation/translate_from_file.js similarity index 96% rename from media-translation/translate_from_file.js rename to mediatranslation/translate_from_file.js index 472ff82f30..4fa6b718b1 100644 --- a/media-translation/translate_from_file.js +++ b/mediatranslation/translate_from_file.js @@ -21,7 +21,7 @@ * @param {string} targetLanguage languate translating to, as BCP-47 code */ function main(filename, encoding, sourceLanguage, targetLanguage) { - // [START media_translation_translate_from_file] + // [START mediatranslation_translate_from_file] const fs = require('fs'); // Imports the CLoud Media Translation client library @@ -94,7 +94,7 @@ function main(filename, encoding, sourceLanguage, targetLanguage) { } }); - // [END media_translation_translate_from_file] + // [END mediatranslation_translate_from_file] } translate_from_file(); } diff --git a/media-translation/translate_from_mic.js b/mediatranslation/translate_from_mic.js similarity index 98% rename from media-translation/translate_from_mic.js rename to mediatranslation/translate_from_mic.js index 1ea70744b4..37d18f578e 100644 --- a/media-translation/translate_from_mic.js +++ b/mediatranslation/translate_from_mic.js @@ -37,7 +37,7 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { sampleRateHertz = Number(sampleRateHertz); - // [START media_translation_translate_from_mic] + // [START mediatranslation_translate_from_mic] // Allow user input from terminal const readline = require('readline'); @@ -150,6 +150,6 @@ function main(encoding, sampleRateHertz, sourceLanguage, targetLanguage) { } doTranslationLoop(); - // [END media_translation_translate_from_mic] + // [END mediatranslation_translate_from_mic] } main(...process.argv.slice(2));