转码和流音频 - 如何发送内容范围头 [英] Transcoding and streaming audio - how to send content-range headers
问题描述
快速版本:如何发送正确的内容范围
头时,不知道身体长度
Quick version: how to send correct Content-Range
headers when don't know the body length?
我有一个FLAC文件。我想跨code它的MP3并立即传输到用户。
我有这样的事情至今:
I have a FLAC file. I want to transcode it to MP3 and stream it to the user immediately. I have something like this so far:
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)
})
这如预期运作,但它的流媒体,所以我不能跳过左右。
显然,我需要做的内容范围
的东西。
使用: https://github.com/visionmedia/node-range-parser
This works as intended, but it's "streaming", so I can't skip around.
Apparently I need to do Content-Range
stuff.
Using: 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)
})
这就是我卡住了。
由于我不是等到整个首歌是连接codeD,
我不知道这首歌的大小。
由于我刚刚得到在Chrome中,取消
我假设的内容范围
头是没有大小的格式不正确。
This is where I'm stuck.
Since I'm not waiting until the entire song is encoded,
I don't know the size of the song.
Since I just get a "canceled" in Chrome,
I'm assuming that the Content-Range
header is malformed without the size.
此外,我目前刚刚开放的歌曲在我的浏览器,所以我想它使用了&LT;音频方式&gt;
元素
Also, I'm current just opening the song in my browser, so I assume it uses the <audio>
element.
建议?
推荐答案
是的,你的内容范围
头是没有大小的格式不正确。然而,你的可能的尝试发送电流的大小你的服务器已经转codeD。虽然我怀疑,铬会优雅地处理不断变化的大小...
Yes, your Content-Range
header is malformed without the size. However, you could attempt to send the current size your server had already transcoded. Although I'm doubtful that Chrome would handle the changing size gracefully…
- 您似乎没有被发送
206部分内容
状态(也许这是由库处理,不知道)。 - 它看起来并不像你连检查范围请求的最后一部分。 Chrome不正常发送任何东西,但
0 -
,但其他浏览器会。事实上,有些人可能会(在屁股皇家疼痛支持)在单个请求发送多个范围。 - 您不是在发送正确的
内容范围
响应头,你也不能包括你发送的内容结束索引。它应该是这样的:结果内容范围:字节0-2048 / 3980841
- 最后,如果客户端发出请求的范围是出界,也就是说,没有值范围重叠的资源的服务范围应与的
416请求范围无法满足
状态。
- You don't appear to be sending the
206 Partial Content
status (maybe this is handled by the library, not sure). - It doesn't look like you're even checking the end part of the range request. Chrome doesn't normally send anything but
0-
, but other browsers will. In fact, some might send multiple ranges in a single request (royal pain in the ass to support). - You're not sending a proper
Content-Range
response header as you are also failing to include the end index of the content you're sending. It should look like this:
Content-Range: bytes 0-2048/3980841
- Finally if the client makes a range request that is out of bounds—that is, none of the range values overlap the extent of the resource—the service should respond with a
416 Requested Range Not Satisfiable
status.
编辑:我没有测试过这种特殊情况下,但如果你是从FLAC转码到192kbps的MP3 CBR,我会想象有只限制设置的,将发生的,如果你准备(小于1000位关闭)进行发送的略的不准确的内容长度:
I haven't tested this particular case, but if you were transcoding from FLAC to a 192kbps CBR MP3, I would imagine there are only a limit set of possibilities that would occur if you were sending a slightly inaccurate content-length (off by less than a 1000 bits):
- 音频的最后会得到在由玩家最终剪去。 〜1000位将剪辑约 5毫秒音频(不是显而易见的人)的。
- 浏览器会忽略的结束索引或内容长度,只是不断接受和/或请求以外的范围内的
内容范围
您最初,直至关闭回应连接或发送416状态。 - 音频的丢失/错误的结束可能导致
&LT;音频&GT;
抛出一个MEDIA_ERR_NETWORK
或MEDIA_ERR_DE code
错误你只需优雅地处理。 (音频仍然在这种情况下被裁剪。)
- The very end of the audio would get clipped off at the end by the player. ~1000 bits would clip approximately 5ms of audio (not obvious to a human).
- The browser would ignore the end index or content-length and simply keep accepting and/or requesting ranges outside of the
Content-Range
you responded with originally until you close the connection or send the 416 status. - The missing/erroneous end of the audio may cause the
<audio>
to throw aMEDIA_ERR_NETWORK
or aMEDIA_ERR_DECODE
error that you'd simply have to handle gracefully. (The audio would still be clipped in this case.)
这篇关于转码和流音频 - 如何发送内容范围头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!