Ich habe ein Binärdokument (mp4-Videodatei) in einer Datenbank (MarkLogic). Ich verwende die Node.js API der Datenbank, um das Dokument in Chunks zu streamen. Das Setup sieht wie folgt aus:Node.js/Express-Video-Streaming (HTTP 206 Teilinhalt)
html-Datei
<video controls="controls" width="600">
<source src="/video/myvideo.mp4" type="video/mp4">
</video>
Expressgut dann habe ich Setup eine Route, die den/Video/Griffe: param Route (in der Datenbank das Video die eindeutige Kennung hat, die der String '/video/myvideo.mp4')
node.js
// I'm only showing the relevant things in here
const serveVideo = (req, res) => {
var stream = db.documents.read('/gopro/malta.mp4').stream('chunked');
var chunks = [];
var chunkBytes = 0;
var start = 0;
stream.on('data', (chunk) => {
var headers;
var range = req.headers.range;
var total = 214335483; //total length of vid in bytes
if (range) {
var chunkSize = chunk.length;
// (start === 0) ? start = 0 : start += chunkBytes;
if (chunkBytes === 0) {
start = 0
} else {
start = chunkBytes + 1
}
chunkBytes += chunkSize;
headers = {
'Content-Range': 'bytes ' + start + '-' + chunkBytes + '/' + total,
'Accept-Ranges': 'bytes',
'Content-Length': chunkSize,
'Content-Type': 'video/mp4'
};
res.writeHead(206, headers);
chunks.push(chunk);
}
});
stream.on('end',() => {
var allChunks = Buffer.concat(chunks);
res.end(allChunks);
});
});
router.route('/video/:uri').get(serveVideo);
Jetzt schlägt das obige natürlich fehl mit 'Fehler: Header können nach dem Senden nicht gesetzt werden.' Das ist alles fair und quadratisch. Aber ich kann mich nicht damit herumschlagen - der .stream ('chunked') Aufruf zwingt die Datenbank, das Dokument in Chunks abzufragen, und ich sehe diese Chunks ganz gut, aber wie kann ich eine 206 für den Browser zurückgeben? Ich kann es nicht in der .on ("Daten") tun, während Daten gestreamt werden, so dass die Kopfzeile mehrmals gesendet werden würde. Ich denke, welche Datenbank ich verwende ist nicht wirklich relevant - ich würde gerne das Konzept verstehen oder zumindest sehen, was ich falsch mache.
Jede Hilfe wird geschätzt. Alle Beispiele und andere Diskussionen, die ich gesehen habe, dass Video mit Node.js streamen, lesen die Videodatei von der Festplatte.
Update
eine Änderung des Codes zu machen erlaubt nun FF das Video aber nicht Chrome zu spielen:
let stream = db.documents.read({uris:'/gopro/malta.mp4'}).stream('chunked');
stream.pipe(res);
Es gibt keine Fehler in Chrome-Konsole. Hier sind die Kopfdetails - beachten Sie, dass es zwei Anfragen für die mp4-Datei:
1.
Response Headers
Connection:keep-alive
Date:Sat, 21 May 2016 17:05:30 GMT
Transfer-Encoding:chunked
X-Powered-By:Express
Request Headers
view source
Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8,hu;q=0.6,ro;q=0.4,it;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Cookie:__distillery=v20150227_a8e22306-65b3-4c2e-9a8a-159e308156ad; __smToken=7nYU8NYQY15mPowjjCZsS5D3
DNT:1
Host:localhost:8080
Pragma:no-cache
Range:bytes=0-
Referer:http://localhost:8080/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
2.
Response Headers
Connection:keep-alive
Date:Sat, 21 May 2016 17:05:31 GMT
Transfer-Encoding:chunked
X-Powered-By:Express
Request Headers
view source
Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8,hu;q=0.6,ro;q=0.4,it;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Cookie:__distillery=v20150227_a8e22306-65b3-4c2e-9a8a-159e308156ad; __smToken=7nYU8NYQY15mPowjjCZsS5D3
DNT:1
Host:localhost:8080
Pragma:no-cache
Range:bytes=28-
Referer:http://localhost:8080/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
Haben Sie bewiesen, dass Ihr Code oben funktioniert, indem Sie von der Festplatte lesen? Ich schlage das als ersten Schritt zur Fehlerbehebung vor. Sobald Sie die Rückseite brechen auf dem der allgemeine Code ist Sound, dann fügen Sie die DB-Schritte zurück in. –
Gute Frage! Ich würde sagen, dass Sie writeHead nicht anrufen sollten, aber dass Sie in Express eindringen müssen, um Kopfzeile direkt zu schreiben. Sie können auch einen Blick auf diesen [code] (https://github.com/feross/webtorrent/blob/c85dd3b83bdbd7fcbbb32c65a080b7011e4daeder/lib/server.js) werfen, von dem ich weiß, dass er ein Video mit 206 Antworten streamen kann, er wird in peerflix verwendet . siehe auch https://gist.github.com/paolorossi/1993068 –
Sie müssen wahrscheinlich nicht alle Chunk-Sachen. Setzen Sie die Header manuell: 'res.status (206);'. Dann pipe einfach die Antwort: 'let stream = db.yourChunkStuff(); stream.pipe (res); '. Auf einem Telefon hier kann man also nicht testen, also nur in einen Kommentar setzen. – Zlatko