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

Tho*_*hoe 4 node.js google-text-to-speech firebase google-cloud-functions firebase-storage

我们正在尝试使用 Google Cloud Function 从 Google Text-to-Speech 获取音频文件并将其保存到 Firebase Storage。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');
Run Code Online (Sandbox Code Playgroud)

这会导致错误消息Error: EROFS: read-only file system。Google Cloud Storage 不允许在本地写入文件。

使用 Firebase Storagebucket.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
   ));
Run Code Online (Sandbox Code Playgroud)

错误信息是TypeError: Path must be a stringbucket.upload()is The fully qualified path to the file you wish to upload to your bucket.and的第一个参数应该是一个字符串,所以response.audioContent不起作用。

文档bucket.upload()建议destination: destinationPath是,我们应该把路径火力地堡的存储位置。这样对吗?

我们如何从 Google Text-to-Speech ( response.audioContent) 中获取音频文件并将其保存为bucket.upload()可以访问的字符串?或者我们应该使用其他东西而不是bucket.upload()?

这是我们完整的云功能:

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"
});
Run Code Online (Sandbox Code Playgroud)

Tho*_*hoe 7

file.save()是答案。util.promisify是不必要的,并导致有关original某事的错误消息。这是完成的云功能:

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
Run Code Online (Sandbox Code Playgroud)

我们收到一个错误TypeError: [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type function at Object.promisify。此错误似乎不会影响云功能。

重申无效的内容,fs.createWriteStream因为 Google Cloud Functions 无法处理Node 文件系统命令而无效。相反,Google Cloud Functions 有自己的方法来包装 Node 文件系统命令。bucket.upload()会将本地文件上传到存储桶,但本地文件的路径必须是字符串,而不是缓冲区或来自 API 的流。file.save()记录为

将任意数据写入文件。

这是一种方便的方法,它包装File#createWriteStream.

这就是我想要的!如果我的数据只有一件事,那就是任意的。或者可能与本性相反。之后,我们只需要理顺contentType( audio/mpeg, not mp3) 和文件路径。