使用Google Cloud Storage将音频文件从Google文本语音转换保存到Firebase存储吗? [英] Save an audiofile from Google Text-to-Speech to Firebase Storage using Google Cloud Storage?
问题描述
我们正尝试使用Google Cloud Function从Google文本语音转换获取音频文件并将其保存到Firebase存储. Google的文档文字转语音显示如何获取音频文件并将其保存在本地:
We're trying to get an audiofile from Google Text-to-Speech and save it to Firebase Storage, using a Google Cloud Function. The documentation for Google Text-to-Speech show how to get an audiofile and save it locally:
// 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('output.mp3', response.audioContent, 'binary');
console.log('Audio content written to file: output.mp3');
这将导致错误消息Error: EROFS: read-only file system
. Google Cloud Storage不允许在本地写入文件.
This results in an error message Error: EROFS: read-only file system
. Google Cloud Storage doesn't allow writing files locally.
使用Firebase Storage bucket.upload()
有一些问题:
Using Firebase Storage bucket.upload()
has a few problems:
const destinationPath = 'Audio/Spanish' + filename.ogg;
// Performs the Text-to-Speech request
const [response] = await client.synthesizeSpeech(request);
// response.audioContent is the downloaded file
await bucket.upload(response.audioContent, {
destination: destinationPath
));
错误消息是TypeError: Path must be a string
. bucket.upload()
的第一个参数是The fully qualified path to the file you wish to upload to your bucket.
,并且应为字符串,因此response.audioContent
不起作用.
The error message is TypeError: Path must be a string
. The first parameter of bucket.upload()
is The fully qualified path to the file you wish to upload to your bucket.
and is expected to be a string so response.audioContent
doesn't work.
destination: destinationPath
是我们应将路径放置到Firebase存储位置的位置.这是正确的吗?
The documentation for bucket.upload()
suggests that destination: destinationPath
is where we should put the path to the Firebase Storage location. Is this correct?
我们如何从Google文本语音转换(response.audioContent
)中获取音频文件并将其另存为bucket.upload()
可以访问的字符串?还是我们应该使用其他内容代替bucket.upload()
?
How do we take the audiofile from Google Text-to-Speech (response.audioContent
) and save it as a string that bucket.upload()
can access? Or should we use something else instead of bucket.upload()
?
这是我们的完整云功能:
Here's our full cloud function:
exports.Google_T2S = functions.firestore.document('Users/{userID}/Spanish/T2S_Request').onUpdate((change, context) => {
if (change.after.data().word != undefined) {
// Performs the Text-to-Speech request
async function test() {
try {
const word = change.after.data().word; // the text
const longLanguage = 'Spanish';
const audioFormat = '.mp3';
// copied from https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries#client-libraries-usage-nodejs
const fs = require('fs');
const util = require('util');
const textToSpeech = require('@google-cloud/text-to-speech'); // Imports the Google Cloud client library
const client = new textToSpeech.TextToSpeechClient(); // Creates a client
let myWordFile = word.replace(/ /g,"_"); // replace spaces with underscores in the file name
myWordFile = myWordFile.toLowerCase(); // convert the file name to lower case
myWordFile = myWordFile + audioFormat; // append .mp3 to the file name;
// copied from https://cloud.google.com/blog/products/gcp/use-google-cloud-client-libraries-to-store-files-save-entities-and-log-data
const {Storage} = require('@google-cloud/storage');
const storage = new Storage();
const bucket = storage.bucket('myProject-cd99d.appspot.com');
const destinationPath = 'Audio/Spanish/' + myWordFile;
const request = { // Construct the request
input: {text: word},
// Select the language and SSML Voice Gender (optional)
voice: {languageCode: 'es-ES', ssmlGender: 'FEMALE'},
// Select the type of audio encoding
audioConfig: {audioEncoding: 'MP3'},
};
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile('output.mp3', response.audioContent, 'binary');
console.log('Audio content written to file: output.mp3')
// response.audioContent is the downloaded file
await bucket.upload(response.audioContent, {
destination: destinationPath
});
}
catch (error) {
console.error(error);
}
}
test();
} // close if
return 0; // prevents an error message "Function returned undefined, expected Promise or value"
});
推荐答案
file.save()
是答案. util.promisify
是不必要的,并且会导致有关original
内容的错误消息.这是完成的云功能:
file.save()
was the answer. util.promisify
was unnecessary, and causes an error message about original
something. Here's the finished cloud function:
const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });
async function textToSpeechRequest()
{
try
{
const word = change.after.data().word; // the text
const longLanguage = 'Spanish';
const audioFormat = '.mp3';
// copied from https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries#client-libraries-usage-nodejs
const util = require('util');
const textToSpeech = require('@google-cloud/text-to-speech'); // Imports the Google Cloud client library
const client = new textToSpeech.TextToSpeechClient(); // Creates a client
let myWordFile = word.replace(/ /g,"_"); // replace spaces with underscores in the file name
myWordFile = myWordFile.toLowerCase(); // convert the file name to lower case
myWordFile = myWordFile + audioFormat; // append .mp3 to the file name;
// copied from https://cloud.google.com/blog/products/gcp/use-google-cloud-client-libraries-to-store-files-save-entities-and-log-data
const {Storage} = require('@google-cloud/storage');
const storage = new Storage();
//const bucket = storage.bucket('myProject-cd99d.appspot.com');
var file = bucket.file('Audio/Spanish/' + myWordFile);
const request = { // Construct the request
input: {text: word},
// Select the language and SSML Voice Gender (optional)
voice: {languageCode: 'es-ES', ssmlGender: 'FEMALE'},
// Select the type of audio encoding
audioConfig: {audioEncoding: 'MP3'},
};
const options = { // construct the file to write
metadata: {
contentType: 'audio/mpeg',
metadata: {
source: 'Google Text-to-Speech'
}
}
};
// copied from https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries#client-libraries-usage-nodejs
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
// response.audioContent is the downloaded file
return await file.save(response.audioContent, options)
.then(() => {
console.log("File written to Firebase Storage.")
return;
})
.catch((error) => {
console.error(error);
});
} // close try
catch (error) {
console.error(error);
} // close catch
} // close async function declaration
exports.Google_T2S = functions.firestore.document('Users/{userID}/Spanish/T2S_Request').onUpdate((change, context) => {
if (change.after.data().word !== undefined)
{
textToSpeechRequest();
} // close if
}); // close Google_T2S
我们遇到错误TypeError: [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type function at Object.promisify
.该错误似乎并未影响云功能.
We're getting an error TypeError: [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type function at Object.promisify
. This error doesn't appear to effect the cloud function.
要重申无效的内容,fs.createWriteStream
无效,因为Google Cloud Functions无法处理方法包装节点文件系统命令. bucket.upload()将上传一个存储桶中的本地文件,但本地文件的路径必须是字符串,而不是来自API的缓冲区或流. file.save()记录为
To reiterate the stuff that didn't work, fs.createWriteStream
didn't work because Google Cloud Functions can't handle Node file system commands. Instead, Google Cloud Functions have their own methods that wrap the Node file system commands. bucket.upload() will upload a local file to a bucket, but the path to the local file has to be a string, not a buffer or a stream coming from an API. file.save() is documented as
将任意数据写入文件.
Write arbitrary data to a file.
这是包装File#createWriteStream
的便捷方法.
这就是我想要的!如果我的数据有问题,那是任意的.也许天生就相反.之后,我们只需要弄清楚contentType
(audio/mpeg
,而不是mp3
)和文件路径.
That's what I want! If there's one thing about my data, it's arbitrary. Or maybe contrary by nature. After that we just had to straighten out the contentType
(audio/mpeg
, not mp3
) and the file path.
这篇关于使用Google Cloud Storage将音频文件从Google文本语音转换保存到Firebase存储吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!