3

I am trying to compress/transcode a video file that is saved in my MongoDB database, but I am not sure how I can add it as an input stream into the ffmpeg transcoding process.

Any ideas?

async function transcodeVideo(_id) {
  gfs.collection("originalVideos");

  const video = await gfs.files.findOne({ _id: ObjectId(_id) }); //this is used for other things not shown in this example.

  const gridfsBucket = new mongoose.mongo.GridFSBucket(connection.db, {
    bucketName: "originalVideos",
  });

  const downloadStream = gridfsBucket.openDownloadStream(video._id);

  return new Promise((resolve, reject) => {
    const command = ffmpeg()
      .input(downloadStream)
      .inputFormat("mp4")
      .setFfprobePath(pathToFfprobe.path)
      .setFfmpegPath(pathToFfmpeg)
      .videoCodec("libx264")
      .audioCodec("libmp3lame")
      .size("720x?")
      .on("error", (err) => {
        console.log(err);
      })
      .on("progress", (progress) => {
      })
      .on("end", () => {
      })
      .save("./video.mp4");
  });

enter image description here

twominds
  • 1,084
  • 5
  • 20
  • I'm thinking its because I need to specify the encoding or something because it is currently streaming in as a buffer. – twominds Mar 23 '22 at 12:50
  • 1
    I think ffmpeg should get the encoding from the data within the buffer. Just a hunch though. This is a good original question BTW! – mikemaccana Mar 23 '22 at 13:19
  • 2
    It [doesn't look like `openDownloadStream`](https://mongodb.github.io/node-mongodb-native/3.1/api/GridFSBucket.html#openDownloadStream) returns a proper Node ReadableStream, [which seems to be required by fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#specifying-inputs). – AKX Mar 23 '22 at 13:19
  • @AKX Yeah, I've been looking through that same documentation but didn't find anything also. Is it possible to convert the buffer while being streamed as input? – twominds Mar 23 '22 at 13:24
  • Sure, you could probably write your own ReadableStream that reads from the MongoDB stream. – AKX Mar 23 '22 at 13:29
  • Alright, I just learned that ffmpeg has a limitation for streaming input. You must use seekable file formats like webm, but im still looking for a workaround. I just tried the same code above except with a webm file, and it worked fine. – twominds Apr 04 '22 at 18:16
  • By using `multer.memoryStorage()`, it will store the video file in server memory as a `req.file.buffer`. Use npm `stream` to create a `new stream.PassThrough()`. Pass the multer `req.file.buffer` to `bufferStream.end(Buffer.from(req.file.buffer))` which will create a passthrough. The passthrough can be inputted into the npm ffmpeg `stream-transcoder` constructor. Chain a `.stream().pipe(writeStream)` to `gridfsbucket.openUploadStream` the transcoded video. It doesnt work with m4v, mov, DRM and non seekable formats. I dont recommend this for video, but it may work well with photos. – twominds Apr 07 '22 at 15:22
  • I am sort of forced to go back to how I was doing it before by just saving the requestors full video file on the server, then transcoding/compressing it from an input string, then outputting it as a file back to the server, and then finally stream writing that output video file to MongoDB. – twominds Apr 07 '22 at 15:26

0 Answers0