Сохранить аудиофайл из Google Text-to-Speech в Firebase Storage, используя Google Cloud Storage? - PullRequest
0 голосов
/ 17 января 2019

Мы пытаемся получить аудиофайл из Google Text-to-Speech и сохранить его в Firebase Storage, используя облачную функцию Google. Документация для 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');

Это приводит к сообщению об ошибке Error: EROFS: read-only file system. Облачное хранилище Google не позволяет записывать файлы локально.

Использование 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
   ));

Сообщение об ошибке TypeError: Path must be a string. Первый параметр bucket.upload() равен The fully qualified path to the file you wish to upload to your bucket. и, как ожидается, будет строкой, поэтому response.audioContent не работает.

Документация для bucket.upload() предполагает, что destination: destinationPath - это место, куда мы должны указать путь к месту хранения Firebase. Это правильно?

Как взять аудиофайл из 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"
});

1 Ответ

0 голосов
/ 18 января 2019

file.save() был ответ. util.promisify был не нужен, и вызывает сообщение об ошибке original что-то. Вот законченная функция облака:

exports.Google_T2S = functions.firestore.document('Users/{userID}/Spanish/T2S_Request').onUpdate((change, context) => {
  if (change.after.data().word != undefined) {

    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(function() {
          console.log("File written to Firebase Storage.")
        })
        .catch(function(error) {
          console.error(error);
        });
      );
    } // close try
    catch (error) {
      console.error(error);
    } // close catch
  } // close async
  textToSpeechRequest();
} // close if
}); // close Google_T2S

Мы получаем ошибку TypeError: [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type function at Object.promisify. Эта ошибка не влияет на функцию облака.

Чтобы повторить то, что не сработало, fs.createWriteStream не сработало, потому что облачные функции Google не могут обрабатывать Node file system команды. Вместо этого облачные функции Google имеют свои собственные методы , которые обертывают команды файловой системы Node. bucket.upload () загрузит локальный файл в корзину, но путь к локальному файлу должен быть строкой, а не буфером или потоком, поступающим из API. file.save () задокументировано как

Запись произвольных данных в файл.

Это удобный метод, который упаковывает File#createWriteStream.

Вот чего я хочу! Если есть что-то в моих данных, это произвольно. Или, может быть, противоречит природе. После этого нам просто нужно было исправить contentType (audio/mpeg, а не mp3) и путь к файлу.

...