使用Google Cloud Storage将音频文件从Google文本语音转换保存到Firebase存储吗? [英] Save an audiofile from Google Text-to-Speech to Firebase Storage using Google Cloud Storage?

查看:92
本文介绍了使用Google Cloud Storage将音频文件从Google文本语音转换保存到Firebase存储吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正尝试使用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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆