快速版本:如何发送正确的Content-Range
标题时不知道身长?转码和流音频 - 如何发送内容范围标头
我有一个FLAC文件。我想将其转码为MP3并立即将其流式传输给用户。 我有这样的事情至今:
function transcode(file) {
var spawn = require('child_process').spawn
var decode = spawn('flac', [
'--decode',
'--stdout',
file
])
var encode = spawn('lame', [
'-V0',
'-',
'-'
])
decode.stdout.pipe(encode.stdin)
return encode
}
var express = require('express')
var app = express()
app.get('/somefile.mp3', function (req, res) {
res.setHeader('Accept-Ranges', 'bytes')
res.setHeader('Content-Range', 'bytes')
res.setHeader('Content-Type', 'audio/mpeg')
transcode(file).stdout.pipe(res)
})
这按预期工作,但它的“流媒体”,所以我不能跳过左右。 显然我需要做Content-Range
的东西。 使用:https://github.com/visionmedia/node-range-parser
function sliceStream(start, writeStream, readStream) {
var length = 0
var passed = false
readStream.on('data', function (buf) {
if (passed) return writeStream.write(buf);
length += buf.length
if (length < start) return;
passed = true
writeStream.write(buf.slice(length - start))
})
readStream.on('end', function() {
writeStream.end()
})
}
var parseRange = require('range-parser')
app.get('/somefile.mp3', function (req, res) {
var ranges = parseRange(Infinity, req.headers['range'])
if (ranges === -1 || ranges === -2) return res.send(400);
var start = ranges[0].start
res.setHeader('Accept-Ranges', 'bytes')
res.setHeader('Content-Type', 'audio/mpeg')
if (!start) {
res.setHeader('Content-Range', 'bytes')
transcode(file).stdout.pipe(res)
return
}
res.setHeader('Content-Range', 'bytes ' + start + '-')
sliceStream(start, transcode(file).stdout, res)
})
这是我坚持。 因为我并没有等到整首歌被编码,我不知道这首歌的大小。 由于我刚刚在Chrome中取消了“取消”,因此我假设Content-Range
标头的格式不正确,但没有大小。
此外,我目前只是在浏览器中打开歌曲,所以我认为它使用了<audio>
元素。
对此提出建议?
所以基本上这意味着我必须事先知道长度? –
基本上是。但是,如果您进行了CBR编码,则可以轻松估计长度。你会知道代码转换后文件的长度(以毫秒为单位)和恒定比特率。 – idbehold
如果不是确切的,该怎么办?有关系吗? –