title: Save an audiofile from Google Text-to-Speech to Firebase Storage using Google Cloud Storage?
body: <p>We're trying to get an audiofile from Google Text-to-Speech and save it to Firebase Storage, using a Google Cloud Function. The <a href="https://cloud.google.com/text-to-speech/docs/reference/libraries#client-libraries-install-nodejs" rel="nofollow noreferrer">documentation</a> for Google Text-to-Speech show how to get an audiofile and save it locally:</p>
  
  <pre class="lang-js prettyprint-override"><code>// 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');
  </code></pre>
  
  <p>This results in an error message <code>Error: EROFS: read-only file system</code>. Google Cloud Storage doesn't allow writing files locally.</p>
  
  <p>Using Firebase Storage <code>bucket.upload()</code> has a few problems:</p>
  
  <pre class="lang-js prettyprint-override"><code>   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
     ));
  </code></pre>
  
  <p>The error message is <code>TypeError: Path must be a string</code>. The first parameter of <code>bucket.upload()</code> is <code>The fully qualified path to the file you wish to upload to your bucket.</code> and is expected to be a string so <code>response.audioContent</code> doesn't work.</p>
  
  <p>The <a href="https://cloud.google.com/nodejs/docs/reference/storage/2.3.x/Bucket#upload" rel="nofollow noreferrer">documentation</a> for <code>bucket.upload()</code> suggests that <code>destination: destinationPath</code> is where we should put the path to the Firebase Storage location. Is this correct?</p>
  
  <p>How do we take the audiofile from Google Text-to-Speech (<code>response.audioContent</code>) and save it as a string that <code>bucket.upload()</code> can access? Or should we use something else instead of <code>bucket.upload()</code>?</p>
  
  <p>Here's our full cloud function:</p>
  
  <pre class="lang-js prettyprint-override"><code>exports.Google_T2S = functions.firestore.document('Users/{userID}/Spanish/T2S_Request').onUpdate((change, context) =&gt; {
    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"
  });
  </code></pre>