简体   繁体   中英

Downloading an API file to Firebase Cloud Storage?

How do I save an audio file (about 10K) from IBM Watson Text-to-speech to Firebase Cloud Storage? Here's my code, copied from the IBM Watson documentation :

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

var TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
var fs = require('fs');    

exports.TextToSpeech = functions.firestore.document('Test_Value').onUpdate((change, context) => {

  var textToSpeech = new TextToSpeechV1({
    username: 'groucho',
    password: 'swordfish',
    url: 'https://stream.watsonplatform.net/text-to-speech/api'
  });

  var synthesizeParams = {
    text: 'Hello world',
    accept: 'audio/wav',
    voice: 'en-US_AllisonVoice'
  };

  textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
    console.log(error);
  }).pipe(fs.createWriteStream('hello_world.wav')); // what goes here?

  const file = ?????
  file.download()
  .then(function(data) {
    console.log("File downloaded."
  })
  .catch(error => {
    console.error(error);
  });
});

The missing code is between

}).pipe(fs.createWriteStream('hello_world.wav'));

and

file.download()

Somehow I have to convert the file provided by IBM Watson into a file that Firebase Cloud Storage recognizes. Is fs not allowed in Google Cloud Functions?

Also, shouldn't line 6 be

var fs = require('fs-js');

not

var fs = require('fs'); 

According to NPM the fs package is deprecated.

Is pipe allowed in Google Cloud Functions? If so, what do I pipe the file to? I need something that looks like this:

}).pipe(file);
file.download()

Okay, reviewing the documentation for file.download() , I think you can make this work with little change to your code. file needs to be type File from the Google Storage library (you'll need to install this library ). This type has a method called createWriteStream that you can stream the results of synthesize to. I didn't test this but I believe it should be correct or should at least point you in the right direction:

// looks like you'll need to require this package also
const { Storage } = require('@google-cloud/storage');

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

var TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
var fs = require('fs');    

const storage = new Storage();
const myBucket = storage.bucket('my-bucket');

exports.TextToSpeech = functions.firestore.document('Test_Value').onUpdate((change, context) => {

  var textToSpeech = new TextToSpeechV1({
    username: 'groucho',
    password: 'swordfish',
    url: 'https://stream.watsonplatform.net/text-to-speech/api'
  });

  var synthesizeParams = {
    text: 'Hello world',
    accept: 'audio/wav',
    voice: 'en-US_AllisonVoice'
  };

  const file = myBucket.file('my-file'); // name your file something here

  textToSpeech
    .synthesize(synthesizeParams)
    .on('error', function(error) {
      console.log(error);
    })
    .pipe(file.createWriteStream()) // the File object has a `createWriteStream` method for writing streams to it
    .on('error', function(err) {
      console.log(err);
    })
    .on('finish', function() {
      // The file upload is complete.
      file.download()
        .then(function(data) {
          console.log("File downloaded.");
        })
        .catch(error => {
          console.error(error);
        });
    });
});

For the record:

  • pipe() should be allowed in Google Cloud Functions and it is async. This is why you need to listen for the finish event before downloading the file
  • fs is only deprecated on public NPM but that is not the package you were importing, the fs (file system) module is one of Node's core built-in packages . That said, it looks like you might not need it in your code at all

Thanks dpopp07, I got it!

exports.TextToSpeech = functions.firestore.document('Test_Word').onUpdate((change, context) => {

if (change.after.data().word != undefined) {
    myWord = change.after.data().word;
    myWordFileType = myWord + '.ogg';

  var synthesizeParams = {
        text: myWord,
        accept: 'audio/ogg',
        voice: 'en-US_AllisonVoice'
      };

      const {Storage} = require('@google-cloud/storage');
      const storage = new Storage();
      const bucket = storage.bucket('myapp.appspot.com');
      const file = bucket.file('Test_Folder' + myWordFileType);

      var TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');

      var textToSpeech = new TextToSpeechV1({
        username: 'groucho',
        password: 'swordfish',
        url: 'https://stream.watsonplatform.net/text-to-speech/api'
      });

      textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
        console.log(error);
      }).pipe(file.createWriteStream({contentType: 'auto'}))
      .on('error', function(err) {})
      .on('finish', function() {
        console.log("Complete.");
      });
      }
      return 0;
    });

The function triggers when a new word is written to a Firestore location, then extracts the word and calls it myWord . Adding .ogg makes myWordFileType . The functions sends an HTTP request to IBM Watson Text-to-speech, which returns a callback, not a promise, so the code is a bit ugly. The crux is where the HTTP response goes through Node command pipe to the send the file to the Google Cloud Storage command file.createWriteStream . The contentType must be set to get a readable file, but auto makes this easy. The file is then written to the bucket, which is set to my Firebase Cloud Storage folder Test_Folder and the filename is myWordFileType .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM