Node.js如何流式传输音频文件
Posted
技术标签:
【中文标题】Node.js如何流式传输音频文件【英文标题】:Node.js how to stream audio file 【发布时间】:2017-05-09 06:10:28 【问题描述】:我有一个 node.js,我想将音频文件流式传输到浏览器。这是我处理它的路线:
routes['/v1/tracks/:id/file'] =
get: async (ctx, next) =>
let tracks = await File.find(
trackId: ctx.params.id,
sort: 'bitrate',
direction: 'desc',
limit: 3
);
let stat = fs.statSync(tracks[0].data.path);
let mimeType = 'audio/mpeg';
let opts = , res = 200;
let resHeaders =
'Content-Type': mimeType,
'Content-Length': stat.size,
'Accept-Ranges': 'bytes'
;
if (ctx.headers.accept !== '*/*')
ctx.res.writeHead(200, resHeaders);
return;
if (ctx.headers['range'])
let [b, range] = ctx.headers['range'].split('=');
console.log(b, range);
if (b === 'bytes')
let [start, end] = range.split('-');
if (!end || end === '' || end < start)
end = stat.size;
opts =
start: start - 0,
end: end - 0
;
res = 206;
resHeaders['Content-Range'] = `bytes $start-$end/$stat.size`;
ctx.res.writeHead(res, resHeaders);
ctx.body = fs.createReadStream(tracks[0].data.path, opts);
然后,当我尝试访问 chrome 中的 URL 时,它会发送两个请求。
第一个:
Request Headers:
GET /v1/tracks/ghHxLPNt8Fayfx1d/file HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/55.0.2883.95 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Response Headers:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: audio/mpeg
Content-Length: 5986643
Accept-Ranges: bytes
Date: Fri, 23 Dec 2016 14:09:27 GMT
Connection: keep-alive
第二个:
Request headers:
GET /v1/tracks/ghHxLPNt8Fayfx1d/file HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Accept-Encoding: identity;q=1, *;q=0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
Accept: */*
Referer: http://localhost:3000/v1/tracks/ghHxLPNt8Fayfx1d/file
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Range: bytes=0-
Response headers:
HTTP/1.1 206 Partial Content
X-Powered-By: Express
Content-Type: audio/mpeg
Content-Length: 5986643
Accept-Ranges: bytes
Content-Range: bytes 0-5986643/5986643
Date: Fri, 23 Dec 2016 14:09:28 GMT
Connection: keep-alive
但是它不起作用。 Chrome 只显示带有播放按钮的空白曲目,但没有显示曲目长度,我无法与之交互。 Safari 只是显示加载。
编辑:
如果我删除一堆代码(关于部分内容的所有内容),我可以让它工作,但它不会让我进入一个位置,只能从头到尾播放它。我也可以用我在这里写的代码(Ctrl + S)下载它,然后播放它就好了
【问题讨论】:
【参考方案1】:在挖了很多之后终于确定了,单个字节是问题的原因。
新代码:
if (ctx.headers['range'])
let [b, range] = ctx.headers['range'].split('=');
console.log(b, range);
if (b === 'bytes')
let [start, end] = range.split('-');
if (!end || end === '' || end < start)
end = stat.size - 1;
opts =
start: start - 0,
end: end - 0
;
res = 206;
resHeaders['Content-Range'] = `bytes $start-$end/$stat.size`;
resHeaders['Content-Length'] = end - start + 1;
另见Streaming a video file to an html5 video player with Node.js so that the video controls continue to work?
【讨论】:
以上是关于Node.js如何流式传输音频文件的主要内容,如果未能解决你的问题,请参考以下文章
将音频从浏览器流式传输到具有特定 MIME 类型的 node.js 服务器
将音频从 Node.js 服务器流式传输到 HTML5 <audio> 标签
将文件解压缩到内存中,调整文件,压缩并流式传输到客户端(Node.js)