【发布时间】:2021-09-29 14:52:50
【问题描述】:
我想做一个低延迟的视频流服务并开源(以改善我的网络开发)。 我去年二月开始了这个项目,但我没有太多时间继续它。项目项目名为twitch-with-nodejs。反正。 我不清楚 MediaSources 是如何工作的(我认为)。
我的代码在一个客户端中使用 MediaRecorded 并停止它以每 2 秒发送一次视频通量。然后,服务器将其放入内存中 30 秒,然后准备好将其作为流返回。
另一个客户端想要观看视频流,因此他每 2 秒向服务器发出一次请求以获取视频流。然后,它适用于第一次调用,但不适用于以下。
这是我的代码示例: 第一个客户(流媒体):
this.media = await navigator.mediaDevices[what]({
audio: this.config.audio,
video: this.config.video ? {
width: this.config.width,
height: this.config.height,
frameRate: this.config.fps,
facingMode: (this.config.front ? "user" : "environment")
} : false
}).catch(e => {
console.log(e.name + ": " + e.message);
this.can = false;
});
let chunks = [];
const video = document.querySelector('video');
video.srcObject = this.media;
video.onloadedmetadata = () => {
video.play()
}
let mediaRecorder = new MediaRecorder(this.media, {"mimeType": "video/webm;"});
mediaRecorder.ondataavailable = function(ev) {
chunks.push(ev.data);
}
setInterval(() => {
mediaRecorder.stop();
mediaRecorder.start();
}, 2000);
mediaRecorder.onstop = () => {
let blob = new Blob(chunks, {'type': 'video/webm;'});
chunks = [];
const data = new FormData();
data.append('file', blob);
fetch("/postStream", {
"method": "post",
"body": data
});
}
服务器端:
app.post("/postStream", async (req, res) => {
const fileProperty = req?.files?.file;
if(!fileProperty?.data || fileProperty.mimetype !== 'video/webm') return res.json(false);
this.chunks.push({ data: fileProperty?.data, id: i++, date: Date.now() });
return res.json(true);
});
app.get("/playVideo", (req, res) => {
if(this?.chunks?.length < 1) return res.json(false);
const buffer = new Buffer.from(this.chunks?.reverse()?.[0]?.data, 'base64')
const stream = this.bufferToStream(buffer);
res.setHeader("content-type", "video/webm");
stream.pipe(res);
});
还有我的第二个客户,他想看视频:
const mediaSource = new MediaSource();
videoPlaying.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
var sourceBuffer;
const mime = "video/webm; codecs=\"vp8, vorbis\"";
function fetchSegment(){
return fetch("/playVideo").then(res => res.arrayBuffer());
}
async function sourceOpen(){
let data = await fetchSegment();
sourceBuffer = mediaSource.addSourceBuffer(mime);
sourceBuffer.appendBuffer(data);
sourceBuffer.addEventListener('updateend', onUpdateEnd);
videoPlaying.play();
}
function onUpdateEnd(){
//mediaSource.endOfStream();
//clearInterval(intervalSegment);
}
var intervalSegment = setInterval(async () => {
/* Here I catch the following error :
An attempt was made to use an object that is not, or is no longer, usable
*/
console.log(mediaSource.readyState, mediaSource.duration); // => Open, Infinit
let data = await fetchSegment();
sourceBuffer.appendBuffer(data)
console.log("Clearing memory...")
sourceBuffer.remove(0, 2);
}, 2000)
那么,为什么我会捕捉到错误“尝试使用不可用或不再可用的对象”?如何正确读取流?
【问题讨论】:
标签: node.js arrays arraybuffer media-source