javascript 動画 再生 - Node.jsを使用してビデオファイルをhtml5ビデオプレーヤーにストリーミングして、ビデオコントロールが動作し続けるようにしますか?
この質問への受け入れられた答えはすばらしく、受け入れられた答えのままにすべきです。 しかし、私は、読んだストリームがいつも終了/閉じられていないというコードで問題が発生しました。 ソリューションの一部は、 start:start, end:end
と一緒にautoClose: true
2番目のcreateReadStream
argに送信することautoClose: true
。
ソリューションのもう1つの部分は、応答で送信される最大chunksize
を制限することでした。 もう一方の答えは次のようにend
ます:
var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
...どのくらいの数のバイトがあっても、残りのファイルを要求された開始位置から最後のバイトまで送るという効果があります。 しかし、クライアントブラウザには、そのストリームの一部だけを読み込むオプションがあります。まだバイトのすべてを必要としない場合は、そうします。 これにより、ブラウザがより多くのデータを取得するとき(例えば、シーク/スクラブのようなユーザアクションやストリームを再生することなど)まで、ストリームの読み込みがブロックされるようになります。
ユーザーがビデオファイルを削除できるページに<video>
要素を表示していたため、このストリームを閉じる必要がありました。 しかし、クライアント(またはサーバ)が接続を終了するまでファイルはファイルシステムから削除されていませんでした。なぜなら、それがストリームが終了/終了する唯一の方法だからです。
私の解決策は、 maxChunk
設定変数を1MBに設定し、一度に1MB以上のストリームを応答にパイプしないことでした。
// same code as accepted answer
var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
var chunksize = (end - start) + 1;
// poor hack to send smaller chunks to the browser
var maxChunk = 1024 * 1024; // 1MB at a time
if (chunksize > maxChunk) {
end = start + maxChunk - 1;
chunksize = (end - start) + 1;
}
これは、各リクエストの後に読み込みストリームが終了/閉じられ、ブラウザによって保持されていないことを確認する効果があります。
私はまた、この問題をカバーする別のStackOverflowのquestionとanswerを書いた。
Tl; Dr - 質問:
Node.jsを使用してビデオファイルをhtml5ビデオプレーヤーにストリーミングするのに適切な方法は何ですか?ビデオコントロールは引き続き使用できますか?
私はヘッダーが処理される方法と関係していると思います 。 とにかく、ここに背景情報があります。 コードは少し長めですが、かなり簡単です。
小さなビデオファイルをノードでHTML5ビデオにストリーミングするのは簡単です
私は小さなビデオファイルをHTML5ビデオプレーヤーに簡単に流す方法を学びました。 この設定では、コントロールは自分の部分では何もせずに動作し、ビデオストリームは完璧に流れます。 サンプルビデオを含む完全に機能するコードの作業コピーが、 Google Docsでダウンロードできます 。
クライアント:
<html>
<title>Welcome</title>
<body>
<video controls>
<source src="movie.mp4" type="video/mp4"/>
<source src="movie.webm" type="video/webm"/>
<source src="movie.ogg" type="video/ogg"/>
<!-- fallback -->
Your browser does not support the <code>video</code> element.
</video>
</body>
</html>
サーバ:
// Declare Vars & Read Files
var fs = require('fs'),
http = require('http'),
url = require('url'),
path = require('path');
var movie_webm, movie_mp4, movie_ogg;
// ... [snip] ... (Read index page)
fs.readFile(path.resolve(__dirname,"movie.mp4"), function (err, data) {
if (err) {
throw err;
}
movie_mp4 = data;
});
// ... [snip] ... (Read two other formats for the video)
// Serve & Stream Video
http.createServer(function (req, res) {
// ... [snip] ... (Serve client files)
var total;
if (reqResource == "/movie.mp4") {
total = movie_mp4.length;
}
// ... [snip] ... handle two other formats for the video
var range = req.headers.range;
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0], 10);
var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
var chunksize = (end - start) + 1;
if (reqResource == "/movie.mp4") {
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
res.end(movie_mp4.slice(start, end + 1), "binary");
}
// ... [snip] ... handle two other formats for the video
}).listen(8888);
しかし、この方法は1GB未満のファイルに限られています。
fs.createReadStream
ビデオファイルをストリーミング(任意のサイズ)
fs.createReadStream()
利用することにより、サーバはストリームを一度にすべて読み出すのではなく、ストリーム内のファイルを読み込むことができます。 これは物事を行う正しい方法のように聞こえ、構文は非常に単純です:
サーバースニペット:
movieStream = fs.createReadStream(pathToFile);
movieStream.on('open', function () {
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
// This just pipes the read stream to the response object (which goes
//to the client)
movieStream.pipe(res);
});
movieStream.on('error', function (err) {
res.end(err);
});
これはビデオをうまくストリームします! しかし、ビデオコントロールはもはや機能しません。