Search code examples
node.jsexpressffmpeggoogle-cloud-storagefluent-ffmpeg

Passing streams from Fluent-ffmpeg to Google Cloud Storage


Is there a way to pass a stream from Fluent-mmpeg to Google Cloud Storage? I'm trying to allow the user to upload any kind of media (audio or video), and I want to convert it to flac before uploading it to GCS.

I'm using a few middlewares on my route, such as:


routes.post(
  '/upload',
  multer.single('audio'),
  ConvertController.convert,
  UploadController.upload,
  FileController.save,
  (req, res, next) => res.send('ok')
);

I was able to stream from Multer to Fluent-mmpeg and save to a file using this code on ConvertController:

async convert(req, res, next) {
    ffmpeg(streamifier.createReadStream(req.file.buffer))
      .format('flac')
      .output('outputfile.flac')
      .audioChannels(1)
      .on('progress', function(progress) {
        console.log(progress);
      })
      .run();
  }

But I would like to use .pipe() to pass it to UploadController, where I would then upload to GCS:

class UploadController {
  async upload(req, res, next) {
    const gcsHelpers = require('../helpers/google-cloud-storage');
    const { storage } = gcsHelpers;

    const DEFAULT_BUCKET_NAME = 'my-bucket-name';

    const bucketName = DEFAULT_BUCKET_NAME;
    const bucket = storage.bucket(bucketName);
    const fileName = `test.flac`;
    const newFile = bucket.file(fileName);

    newFile.createWriteStream({
      metadata: {
        contentType: file.mimetype
      }
    })

    file.on('error', err => {
      throw err;
    });

    file.on('finish', () => console.log('finished'));
  }

The problem is that I cannot find anywhere explaining how I can pass down a stream to the next middleware.

Is it possible?


Solution

  • Attach your ffmpeg stream to the req object, and then you can pass your ffmpeg stream to the next middleware using the next(). Then you can pipe the stream to your GCS file.

    Something like this:

    // ConvertController
    req.ffpmegStream = ffmpeg(streamifier.createReadStream(req.file.buffer))
      .on('finish', next)
    
    // UploadController
    req.ffmpegStream.pipe(newFile.createWriteStream())
    

    Reference: