简体   繁体   English

使用 Google Cloud Storage 将 Google Text-to-Speech 中的音频文件保存到 Firebase Storage?

[英]Save an audiofile from Google Text-to-Speech to Firebase Storage using Google Cloud Storage?

We're trying to get an audiofile from Google Text-to-Speech and save it to Firebase Storage, using a Google Cloud Function.我们正在尝试使用 Google Cloud Function 从 Google Text-to-Speech 获取音频文件并将其保存到 Firebase Storage。 The documentation for Google Text-to-Speech show how to get an audiofile and save it locally: Google Text-to-Speech 的文档展示了如何获取音频文件并将其保存在本地:

// 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');

This results in an error message Error: EROFS: read-only file system .这会导致错误消息Error: EROFS: read-only file system Google Cloud Storage doesn't allow writing files locally. Google Cloud Storage 不允许在本地写入文件。

Using Firebase Storage bucket.upload() has a few problems:使用 Firebase Storage bucket.upload()有几个问题:

   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
   ));

The error message is TypeError: Path must be a string .错误消息是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. bucket.upload()的第一个参数是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.并且应该是一个字符串,所以response.audioContent不起作用。

The documentation for bucket.upload() suggests that destination: destinationPath is where we should put the path to the Firebase Storage location. bucket.upload()文档建议destination: destinationPath是我们应该放置 Firebase 存储位置路径的地方。 Is this correct?这样对吗?

How do we take the audiofile from Google Text-to-Speech ( response.audioContent ) and save it as a string that bucket.upload() can access?我们如何从 Google Text-to-Speech ( response.audioContent ) 获取bucket.upload()并将其保存为bucket.upload()可以访问的字符串? Or should we use something else instead of bucket.upload() ?或者我们应该使用其他东西而不是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() was the answer. file.save()就是答案。 util.promisify was unnecessary, and causes an error message about original something. util.promisify是不必要的,并导致有关original内容的错误消息。 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

We're getting an error TypeError: [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type function at Object.promisify .我们收到一个错误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.此错误似乎不会影响云功能。

To reiterate the stuff that didn't work, fs.createWriteStream didn't work because Google Cloud Functions can't handle Node file system commands.重申无效的内容, fs.createWriteStream无效,因为 Google Cloud Functions 无法处理Node 文件系统命令。 Instead, Google Cloud Functions have their own methods that wrap the Node file system commands.相反,Google Cloud Functions 有自己的方法来包装 Node 文件系统命令。 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. bucket.upload()会将本地文件上传到存储桶,但本地文件的路径必须是字符串,而不是缓冲区或来自 API 的流。 file.save() is documented as file.save()记录为

Write arbitrary data to a file.将任意数据写入文件。

This is a convenience method which wraps File#createWriteStream .这是一种包装File#createWriteStream的便捷方法。

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.之后,我们只需要理顺contentTypeaudio/mpeg ,而不是mp3 )和文件路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将映像从Expressjs更新到Google Cloud Storage / Firebase Storage - How update an image from Expressjs to Google Cloud Storage / Firebase Storage Vuejs 应用程序中的谷歌云/文本到语音验证 - google-cloud/text-to-speech authentification in Vuejs App 将谷歌云文本到语音的音频文件从节点服务器发送到反应应用程序 - send google cloud text-to-speech audio file from node server to a react application 如何将 Google Cloud 文本上传到语音 API 对 Cloud Storage [Node.js] 的响应 - How to upload Google Cloud text to speech API's response to Cloud Storage [Node.js] 无法使用Firebase功能删除Google Cloud Storage文件 - Cannot delete Google Cloud Storage files using Firebase Functions 无法从Node.js上传到Google Cloud或Firebase存储桶 - Can't upload to google cloud or firebase storage bucket from nodejs 在node.js下将Firebase参数与Google云端存储配合使用 - Using Firebase parameters with Google Cloud Storage under node.js 使用Node fs.writeFile将文件从Google Cloud Function写入Firebase存储吗? - Write a file from a Google Cloud Function to Firebase Storage using Node fs.writeFile? 如何使用 google-cloud 和 node js 从 firebase 存储中检索图像并将其显示在网页上 - how to retrieve image from firebase storage and display it on a webpage using google-cloud and node js 谷歌云存储的修订 - Revisions in google cloud storage
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM