実現したいこと
ローカルフォルダに保存されている復数の動画ファイルから1つを選択し、フロントエンドで動画を再生したいと考えています。
作成したコード
下記のようなコードを作成しました。
実際にNode.js、EJSを使用して、動画のパス部分を可変にして、フロントエンドから選択できるようにコード作成しました。
javascript
1var fs = require('fs'); 2var glob = require("glob") 3var express = require("express"); 4 5const port = 3000; 6var app = express(); 7var videoPath = ""; 8 9app.set("view engine", "ejs"); 10app.get('/', function (req, res) { 11 res.render('./sample.ejs', { 12 //ファイルのリストを渡す 13 files: mp4files = glob.sync("video/*.mp4"), 14 path: videoPath, 15 }); 16}); 17 18app.get('/renderVideo', function (req, res) { 19 const path = videoPath 20 const stat = fs.statSync(path) 21 const fileSize = stat.size 22 const range = req.headers.range 23 if (range) { 24 const parts = range.replace(/bytes=/, "").split("-") 25 const start = parseInt(parts[0], 10) 26 const end = parts[1] 27 ? parseInt(parts[1], 10) 28 : fileSize - 1 29 const chunksize = (end - start) + 1 30 const file = fs.createReadStream(path, { start, end }) 31 const head = { 32 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 33 'Accept-Ranges': 'bytes', 34 'Content-Length': chunksize, 35 'Content-Type': 'video/mp4', 36 } 37 res.writeHead(206, head); 38 file.pipe(res); 39 40 } else { 41 const head = { 42 'Content-Length': fileSize, 43 'Content-Type': 'video/mp4', 44 } 45 res.writeHead(200, head) 46 fs.createReadStream(path).pipe(res) 47 } 48}); 49 50var bodyParser = require('body-parser'); 51app.use(bodyParser.urlencoded({ extended: false })); 52app.post('/getMp4Name', function (req, res) { 53 videoPath = req.body.mp4 54 res.redirect("/") 55 console.log("videoPath : ", videoPath) 56}); 57 58app.listen(port, () => console.log('app listening on port 3000!'))
HTML
1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="utf-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> 7 <title>Test Application</title> 8</head> 9 10<body> 11 <!-- 保存されている動画のファイル名を取得 --> 12 <div> 13 <form method="POST" id="tableForm" action="/getMp4Name"> 14 <select class="mp4" name="mp4"> 15 <% for (var i=0; i<files.length; i++){ %> 16 <option value=<%=files[i] %> ><%=files[i] %> 17 </option> 18 <%} %> 19 </select> 20 <input type="submit"> 21 </form> 22 </div> 23 <!-- 動画表示 --> 24 <figure> 25 <video id="displayVideo" controls style="max-width: 500px;"> 26 <source src="http://localhost:3000/renderVideo/" type="video/mp4" /> 27 </video> 28 </figure> 29</body> 30 31</html>
参考にしたこと
上記のコードは下記のリンクにある説明を参考にしました。
Video Stream With Node.js and HTML5
こちらではNode.jsのStreamをつかい、パスは決め打ちで単体の動画を再生する方法について説明されています。
/videoでGETされたときに下記が呼び出され、HTMLで表示されます。
javascript
1//Node.js 2app.get('/video', function(req, res) { 3 //ここのパスを可変にした。 4 const path = 'assets/sample.mp4' 5 const stat = fs.statSync(path) 6 const fileSize = stat.size 7 const range = req.headers.range 8 if (range) { 9 const parts = range.replace(/bytes=/, "").split("-") 10 const start = parseInt(parts[0], 10) 11 const end = parts[1] 12 ? parseInt(parts[1], 10) 13 : fileSize-1 14 const chunksize = (end-start)+1 15 const file = fs.createReadStream(path, {start, end}) 16 const head = { 17 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 18 'Accept-Ranges': 'bytes', 19 'Content-Length': chunksize, 20 'Content-Type': 'video/mp4', 21 } 22 res.writeHead(206, head); 23 file.pipe(res); 24 } else { 25 const head = { 26 'Content-Length': fileSize, 27 'Content-Type': 'video/mp4', 28 } 29 res.writeHead(200, head) 30 fs.createReadStream(path).pipe(res) 31 } 32});
HTML
1<video id="videoPlayer" controls> 2 <source src="http://localhost:3000/video" type="video/mp4"> 3</video>
試したこと、考えていること
先程のリンクを参考に、path部分を可変にして(フロントエンドから選択できるようにして)改良してみました。しかし動画を切り替えることができませんでした。
パスが変更されたあと、下記のようなエラーコードがでました。
RangeError [ERR_OUT_OF_RANGE]: The value of "start" is out of range. It must be <= "end"
推測ですが先ほど紹介したコードで、パスを変更する前にapp.get内でpipe()してレスポンスを返している部分をunpipe()する必要があると考えました。
javascript
1file.pipe(res);
質問したいこと
上記のやり方で、動画のパスを切り替えてStreamするためにはどのような処理が必要でしょうか?

回答1件
あなたの回答
tips
プレビュー