0

My ultimate goal is to transcode video files uploaded to one GCS bucket, transcode them for HLS using App Engine, then store them in another bucket for streaming. I started with code someone else made which closely fit my use case. Right now I just have it set up to save the files as mp4 to see if it works and I receive no error messages and is logs 'Success' to the console but when I check GCS the output file it has created is only around a kb (basically its just the metadata). I believe the issue has to do with the .pipe(remoteWriteStream, { end: true }); line and something with ffmpeg because if I instead run the line originStream.pipe(remoteWriteStream, {end: true}); to test the .pipe functionality I get what I'd expect (a copy of the file of the correct size). I've seen a lot of other people such as here use essentially the same method just with cloud functions and have success. Any idea where I went wrong?

import { Storage } from '@google-cloud/storage';

import ffmpegInstaller from '@ffmpeg-installer/ffmpeg';
import ffmpeg from 'fluent-ffmpeg';

ffmpeg.setFfmpegPath(ffmpegInstaller.path);

export default async function transcode(
  //My try
  name: String,
  bucket: String,
  suffix: String,
  size: String,

): Promise<void> {
  return new Promise((resolve, reject) => {
    const storage = new Storage();

    const originBucket = storage.bucket(bucket);
    const destinationBucket = storage.bucket('storieshls-2e4b1');

    const originFile = originBucket.file(name);
    const originStream = originFile.createReadStream();

    const remoteWriteStream = destinationBucket.file(name.replace(".MOV", ".mp4")).createWriteStream({
      metadata: {
        contentType: 'video/mp4', // This could be whatever else you are transcoding to
      },
    });

    //originStream.pipe(remoteWriteStream, {end: true});

    ffmpeg()
      .input(originStream)
      .outputOptions('-c:v copy') // Change these options to whatever suits your needs
      .outputOptions('-c:a aac')
      .outputOptions('-b:a 160k')
      .outputOptions('-f mp4')
      .outputOptions('-preset fast')
      .outputOptions('-movflags frag_keyframe+empty_moov')
      .on('start', cmdLine => {
        console.log(`[${suffix}] Started FFMpeg`, cmdLine);
      })
      .on('end', () => {
        console.log(`[${suffix}] Success!.`);
        resolve();
      })
      .on('error', (err: Error, stdout, stderr) => {
        console.log(`[${suffix}] Error:`, err.message);
        console.error('stdout:', stdout);
        console.error('stderr:', stderr);

        reject();
      })
      .pipe(remoteWriteStream, { end: true });
  });
}

1 Answers1

0

You need to generate pubic URL of GCS file and pass that url in ffmpeg function.

ffmpeg(file_url)
        .output(basename + '-1280x720.mp4')
        .videoCodec('libx264')  
        .size('1280x720')

        .output(basename + '-1920x1080.mp4')
        .videoCodec('libx264')
        .size('1920x1080')

        .on('error', function(err) {
            console.log('An error occurred: ' + err.message);
        })  
        .on('progress', function(progress) { 
            console.log('... frames: ' + progress.frames);
        })
        .on('end', function() { 
            console.log('Finished processing'); 
        })
        .run();
Dev
  • 25
  • 3
  • 14