translate/hybridGlossaries.js (114 lines of code) (raw):
// Copyright 2019 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
//
// 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';
async function main(
projectId = process.env.GCLOUD_PROJECT, // Your GCP Project Id
inFile = 'resources/example.png',
outFile = 'resources/example.mp3',
glossaryLangs = ['fr', 'en'],
glossaryName = 'bistro-glossary',
glossaryUri = 'gs://cloud-samples-data/translation/bistro_glossary.csv'
) {
// [START translate_hybrid_imports]
// Imports the Google Cloud client library
const textToSpeech = require('@google-cloud/text-to-speech');
const translate = require('@google-cloud/translate').v3beta1;
const vision = require('@google-cloud/vision');
// Import other required libraries
const fs = require('fs');
//const escape = require('escape-html');
const util = require('util');
// [END translate_hybrid_imports]
// [START translate_hybrid_vision]
/**
* Detects text in an image file
*
* ARGS
* inputFile: path to image file
* RETURNS
* string of text detected in the input image
**/
async function picToText(inputFile) {
// Creates a client
const client = new vision.ImageAnnotatorClient();
// Performs text detection on the local file
const [result] = await client.textDetection(inputFile);
return result.fullTextAnnotation.text;
}
// [END translate_hybrid_vision]
// [START translate_hybrid_create_glossary]
/** Creates a GCP glossary resource
* Assumes you've already manually uploaded a glossary to Cloud Storage
*
* ARGS
* languages: list of languages in the glossary
* projectId: GCP project id
* glossaryName: name you want to give this glossary resource
* glossaryUri: the uri of the glossary you uploaded to Cloud Storage
* RETURNS
* nothing
**/
async function createGlossary(
languages,
projectId,
glossaryName,
glossaryUri
) {
// Instantiates a client
const translationClient = await new translate.TranslationServiceClient();
// Construct glossary
const glossary = {
languageCodesSet: {
languageCodes: languages,
},
inputConfig: {
gcsSource: {
inputUri: glossaryUri,
},
},
name: translationClient.glossaryPath(
projectId,
'us-central1',
glossaryName
),
};
// Construct request
const request = {
parent: translationClient.locationPath(projectId, 'us-central1'),
glossary: glossary,
};
// Create glossary using a long-running operation.
try {
const [operation] = await translationClient.createGlossary(request);
// Wait for operation to complete.
await operation.promise();
console.log('Created glossary ' + glossaryName + '.');
} catch (AlreadyExists) {
console.log(
'The glossary ' +
glossaryName +
' already exists. No new glossary was created.'
);
}
}
// [END translate_hybrid_create_glossary]
// [START translate_hybrid_translate]
/**
* Translates text to a given language using a glossary
*
* ARGS
* text: String of text to translate
* sourceLanguageCode: language of input text
* targetLanguageCode: language of output text
* projectId: GCP project id
* glossaryName: name you gave your project's glossary
* resource when you created it
* RETURNS
* String of translated text
**/
async function translateText(
text,
sourceLanguageCode,
targetLanguageCode,
projectId,
glossaryName
) {
// Instantiates a client
const translationClient = new translate.TranslationServiceClient();
const glossary = translationClient.glossaryPath(
projectId,
'us-central1',
glossaryName
);
const glossaryConfig = {
glossary: glossary,
};
// Construct request
const request = {
parent: translationClient.locationPath(projectId, 'us-central1'),
contents: [text],
mimeType: 'text/plain', // mime types: text/plain, text/html
sourceLanguageCode: sourceLanguageCode,
targetLanguageCode: targetLanguageCode,
glossaryConfig: glossaryConfig,
};
// Run request
const [response] = await translationClient.translateText(request);
// Extract the string of translated text
return response.glossaryTranslations[0].translatedText;
}
// [END translate_hybrid_translate]
// [START translate_hybrid_tts]
/**
* Generates synthetic audio from plaintext tagged with SSML.
*
* Given the name of a text file and an output file name, this function
* tags the text in the text file with SSML. This function then
* calls the Text-to-Speech API. The API returns a synthetic audio
* version of the text, formatted according to the SSML commands. This
* function saves the synthetic audio to the designated output file.
*
* ARGS
* text: String of plaintext
* outFile: String name of file under which to save audio output
* RETURNS
* nothing
*
*/
async function syntheticAudio(text, outFile) {
// Replace special characters with HTML Ampersand Character Codes
// These codes prevent the API from confusing text with SSML tags
// For example, '<' --> '<' and '&' --> '&'
let escapedLines = text.replace(/&/g, '&');
escapedLines = escapedLines.replace(/"/g, '"');
escapedLines = escapedLines.replace(/</g, '<');
escapedLines = escapedLines.replace(/>/g, '>');
// Convert plaintext to SSML
// Tag SSML so that there is a 2 second pause between each address
const expandedNewline = escapedLines.replace(/\n/g, '\n<break time="2s"/>');
const ssmlText = '<speak>' + expandedNewline + '</speak>';
// Creates a client
const client = new textToSpeech.TextToSpeechClient();
// Constructs the request
const request = {
// Select the text to synthesize
input: {ssml: ssmlText},
// Select the language and SSML Voice Gender (optional)
voice: {languageCode: 'en-US', ssmlGender: 'MALE'},
// Select the type of audio encoding
audioConfig: {audioEncoding: 'MP3'},
};
// Performs the Text-to-Speech request
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile(outFile, response.audioContent, 'binary');
console.log('Audio content written to file ' + outFile);
}
// [END translate_hybrid_tts]
// [START translate_hybrid_integration]
await createGlossary(glossaryLangs, projectId, glossaryName, glossaryUri);
const text = await picToText(inFile);
const translatedText = await translateText(
text,
'fr',
'en',
projectId,
glossaryName
);
syntheticAudio(translatedText, outFile);
// [END translate_hybrid_integration]
}
main(...process.argv.slice(2));