11

I'm building a nodejs app that streams a video from the disk to the user. Thanks to this question, i have a working video feed for a "static" video file that is stored on disk, so far so good.

My problem is that i need to transcode the video on the fly, to do this i used fluent-ffmpeg and i was successful at implementing the transcoding, but the HTML5 player only shows the first 3-4s of the video, and then stops. I'm guessing the problem is the filesize, but even when i harcode it nothing changes.

Any idea ? Thanks a lot :)

var file = 'Big_Buck_Bunny_1080p_surround_FrostWire.com.mp4';
    fs.stat(file, function(err, stats) {
        var range = req.headers.range
        if (!range) { // 416 Wrong range
            return res.sendStatus(416)
        }
        var positions = range.replace(/bytes=/, "").split("-");
        var start = parseInt(positions[0], 10);
        var total = stats.size;
        var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
        var chunksize = (end - start) + 1;

        res.writeHead(206, {
            "Content-Range": "bytes " + start + "-" + end + "/" + total,
            "Accept-Ranges": "bytes",
            "Content-Length": chunksize,
            "Content-Type": "video/mp4"
        })

        var stream = fs.createReadStream(file, { start: start, end: end, autoclose: true })
        .on("open", function() {
            const ffmpegCommand = ffmpeg()
                .input(stream)
                .outputFormat('mp4')
                .outputOptions([ '-movflags faststart', '-frag_size 4096', '-cpu-used 2', '-deadline realtime', '-threads 4' ])
                .videoBitrate(640, true)
                .audioBitrate(128)
                .audioCodec('aac')
                .videoCodec('libx264')
                .output(res)
                .run()
        }).on("error", function(err) {
            res.end(err)
        })
    })
Rogue
  • 751
  • 1
  • 17
  • 36
  • 1
    I don't believe you can use `output` here, you need to use a `pipe`. See this SO thread https://stackoverflow.com/questions/49483191/stream-overlapping-audio-files-to-chromecast-audio/50016463#50016463 – Tarun Lalwani Jun 05 '18 at 19:09
  • Also, the http response contains `Content-Range`, `Content-Length` headers which include information about the size of the **original** video, not the transcoded one, which might be significantly different. When transcoding on the fly you should probably not set these at all if you cannot reliably determine them in advance. – Robert Rossmann Jun 12 '18 at 07:59

2 Answers2

0

Eventually, the best solution i found was to use a more "streaming-friendly" format, so i switched to HLS and now everything is simpler and works just fine :)

Rogue
  • 751
  • 1
  • 17
  • 36
0

I think you should drop .output(res) .run()

and use .stream().pipe(res, { end: true}) instead

C-lio Garcia
  • 652
  • 8
  • 17