4

I'm trying to stream mediafiles (.mkv) in Node.js using fs.createReadStream(). This works fine for files smaller than 2MB, they load correctly as the src of their respective HTML5 video elements.

For mediafiles larger than 2MB, this doesnt work. They don't load. In the Console's Network tab, the GET request shows the status '(canceled)' after ~30KB of transfered data. The strange part is that the video element seems to show the correct duration of the mediafile.

Request Method:GET
Status Code:206 Partial Content

Request Headers

Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2,el;q=0.2
Connection:keep-alive
Host:(...)
Range:bytes=0-
Referer:yaddayadda
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36

Response Headers

Accept-Ranges:bytes
Access-Control-Allow-Headers:origin, content-type
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:5716684
Content-Range:bytes 0-5716683/5716684
Content-Type:video/mp4
Date:Tue, 19 Nov 2013 16:29:51 GMT
X-Powered-By:Express

Serverside code

app.get('/getStream/:u/:f', function(req, res) {
    "use strict";
    var userId = req.params.u;
    var file = req.params.f;
    var path = "/tmp/" + userId + "/" + file;
    var stat = fs.statSync(path);
    var total = stat.size;
    if (req.headers['range']) {
        var range = req.headers.range;
        var parts = range.replace(/bytes=/, "").split("-");
        var partialstart = parts[0];
        var partialend = parts[1];

        var start = parseInt(partialstart, 10);
        var end = partialend ? parseInt(partialend, 10) : total - 1;
        var chunksize = (end - start) + 1;
        console.log('RANGE: ' + start + ' - ' + end + ' = ' + chunksize);

        var file = fs.createReadStream(path, {start: start, end: end});
        res.writeHead(206, {'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4'});
        file.pipe(res);
    } else {
        console.log('ALL: ' + total);
        res.writeHead(200, {'Content-Length': total, 'Content-Type': 'video/mp4'});
        fs.createReadStream(path).pipe(res);
    }
});

Serverside notes

I have tried with a simple stream.pipe(res) but the problem persists.

I hope I have included enough information.

Thanks in advance

Gnagy
  • 1,432
  • 16
  • 26
  • I have this same issue and haven't quite gotten to the bottom of it, but I suspect this is a Chrome Bug, as it seems to work fine for me in firefox. https://code.google.com/p/chromium/issues/detail?id=281710 – Matt Palmerlee Feb 02 '14 at 00:33
  • Sorry for the late response. This problem was a blocker and we used plan B, host mediafiles on AWS S3 without the interference of a node.js app. I'm still interested to find the cause of this problem. – Gnagy Feb 13 '14 at 09:14
  • See https://stackoverflow.com/questions/42590683/node-cant-seek-audio-stream for a snippet that worked for me. – centic Nov 30 '17 at 16:31
  • Possible duplicate of [Node - Can't seek audio stream](https://stackoverflow.com/questions/42590683/node-cant-seek-audio-stream) – centic Nov 30 '17 at 16:31
  • How can this be a duplicate when this question is asked 3 years earlier? – Gnagy Dec 05 '17 at 12:40

0 Answers0