我试着将一个视频文件发送到HTML5
我发现了一个可以追溯到2010年的片段。
它在互联网上到处复制,并且仍然在传播,在代码风格、名称、使用的Node.js API版本或库上有一些细微的差异。
这是片段:
app.get('/video', function(req, res) {
const path = 'some_path/video.mp4'
const stat = fs.statSync(path)
const fileSize = stat.size
const range = req.headers.range
if( range ) {
const parts = range.replace(/bytes=/, "").split("-")
const start = parseInt(parts[0],10);
const end = parts[1] ? parseInt(parts[1],10) : fileSize-1
const chunksize = (end-start)+1
const file = fs.createReadStream(path, {start, end})
const head = {
'Content-Range' : `bytes ${start}-${end}/${fileSize}`,
'Accept-Ranges' : 'bytes',
'Content-Length': chunksize,
'Content-Type' : 'video/mp4',
}
res.writeHead(206, head)
file.pipe(res)
} else {
const head = {
'Content-Length': fileSize,
'Content-Type' : 'video/mp4',
}
res.writeHead(200, head)
fs.createReadStream(path).pipe(res)
}
})
很明显,此代码片段尚未准备就绪:
它使用同步
statSync()
它不解析
Range
头,并且没有错误处理,
它是硬编码的,
else
早午餐可能是多余的,
等。
我没意见。这是一个“入门级”代码。没关系。
它不按预期工作
... 但是
仍然有效
.
,浏览器发送对
-标记为
范围
Range: bytes=12345-
而且,在最初的请求中
Range: bytes=0-
const end = parts[1] ? parseInt(parts[1],10) : fileSize-1
与
const end = fileSize-1
而且,在最初的请求中,服务器将不发送视频的一小部分,而是发送整个文件。在视频回放的情况下-从请求的位置到结束有很大一块。
如果您通过Javascript请求一个文件,这肯定不会按预期工作。您将等待文件完全加载,或者需要以某种方式处理跟踪请求进度的问题,这将导致相当复杂的客户端代码。
但它的作用就像是
-标记,因为浏览器代表您处理这个问题。
end
这种方式:
const preferred_chunksize = 10000000 // arbitrary selected value
let end = parts[1] ? parseInt(parts[1],10) : start + preferred_chunksize
if( end > fileSize-1 ) end = fileSize-1
范围
-标签,即使这样:
const preferred_chunksize = 10000000 // arbitrary selected value
let end = start + preferred_chunksize
if( end > fileSize-1 ) end = fileSize-1
好的,现在它确实发送了预期大小的部分响应。
但是
这些线条比
我们需要选择
preferred_chunksize
明智地。E、 g小块大小,如
preferred_chunksize=1000
会发出很多请求,工作速度会明显减慢。
然而,至少在Chrome和Firefox上,原始版本的代码流视频文件非常好:我看不到过多的缓存或内存使用,或速度问题。我不必担心
首选块大小
所以我的问题是:我是否还需要发送大小正确的块(如果我只是需要发送一个视频到
-tag),是否有流行的浏览器/客户端js库无法播放原始片段提供的视频文件?或者这个片段的方法有没有隐藏的问题?