我尝试使用 ytdl-core 模块获取纯音频的 youtube 视频,并使用 express node.js 进行流式传输,它适用于除 safari(iOS safari)之外的所有浏览器。我确实使用了字节范围响应,但仍然出错。
这里是服务器端代码:
app.get("/stream/:videoId", async (req, res) => {
const {videoId} = req.params;
const isValid = ytdl.validateID(videoId);
if (!isValid) {
throw new Error();
}
const videoInfo = await ytdl.getInfo(videoId);
let audioFormat = ytdl.chooseFormat(videoInfo.formats, {
filter: "audioonly",
quality: "highestaudio"
});
const {itag, container, contentLength} = audioFormat;
var start;
var end;
var total = 0;
var contentRange = false;
var content_length = 0;
var range = req.headers.range;
if (range) {
var positions = range.replace(/bytes=/, "").split("-");
start = parseInt(positions[0], 10);
total = contentLength;
end = positions[1] ? parseInt(positions[1], 10) : total - 1;
var chunksize = end - start + 1;
contentRange = true;
content_length = chunksize;
} else {
start = 0;
end = contentLength;
content_length = contentLength;
}
if (start <= end) {
var responseCode = 200;
var responseHeader = {
"Accept-Ranges": "bytes",
"Content-Length": content_length,
"Content-Type": `audio/${container}`
};
if (contentRange) {
responseCode = 206;
responseHeader["Content-Range"] = "bytes " + start + "-" + end + "/" + total;
}
res.writeHead(responseCode, responseHeader);
const range = {start: start, end: end};
var stream = ytdl(videoId, {filter: format => format.itag === itag, range})
.on("readable", function () {
var chunk;
while (null !== (chunk = stream.read(1024))) {
res.write(chunk);
}
})
.on("error", function (err) {
res.end(err);
})
.on("end", function (err) {
res.end();
});
} else {
return res.status(403).send();
}
});
并通过以下方式获取流音频:
<audio src="/stream/<youtube-video-ID>" controls></audio>
在标头 safari 字节范围请求中是 0-1 然后是 0-allbyte,这是一个错误吗?在 Firefox 浏览器中请求是 0- 然后是 xxxx-allbyte。我不知道这很重要我不太了解 HTTP 是如何工作的。请帮忙,谢谢