Nodejs socket.io 传递对象
Nodejs socket.io 传递对象
这段代码能调用摄像头 显示在video1上,下面是客户端代码:
var hosline=io.connect(null);
function startVideo(){
var video = document.getElementById("video1"),
videoObj = {"video" : true },
if (navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function (stream) {
var src = window.webkitURL.createObjectURL(stream);
video.src = src;
video.play();
hosline.emit('priveateMessage', stream,toWho);//toWho 是 socket.id
});
我想把这个 stream 对象(typeof(stream)为 MediaStream )经服务端转发给另一个客户端,下面是服务段代码:
clisocket.on('priveateMessage',function(stream,toWho){
UserLists[towho].emit('priveateMessage',stream, clisocket.id});
});
另一个客户端接收到这个 stream 然后应该就可以视频对话了,但是另一个客户端接收到的 stream(typeof(stream) 是 object)报错。下面是客户端的代码:
hosline.on('priveateMessage',function(stream,fromid){
var src = window.webkitURL.createObjectURL(stream);//这行报一个 类型错误。
var video = document.getElementById('video2');
video.src = src;
video.play();
}
哪位大侠能帮忙解决下呀,在这先谢谢谢谢谢了!!!
在使用 Node.js 和 Socket.IO 传递 MediaStream
对象时,直接传递该对象可能会导致问题,因为 MediaStream
对象通常不能被序列化并通过 WebSocket 发送。相反,你可以考虑将流数据转换为另一种形式(如 Blob 或 Base64 编码的数据 URL),然后发送这个数据。
以下是一个改进的示例,展示了如何将媒体流转换为 Blob,并通过 Socket.IO 发送:
客户端代码
var hosline = io.connect(null);
function startVideo() {
var video = document.getElementById("video1");
var videoObj = { "video": true };
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(videoObj).then(function (stream) {
video.srcObject = stream;
video.play();
// 将流转换为 Blob 并发送
const mediaRecorder = new MediaRecorder(stream);
let chunks = [];
mediaRecorder.ondataavailable = function (event) {
chunks.push(event.data);
};
mediaRecorder.onstop = function () {
const blob = new Blob(chunks, { type: 'video/webm' });
chunks = [];
hosline.emit('priveateMessage', blob, toWho); // toWho 是 socket.id
};
mediaRecorder.start(500); // 每500毫秒录制一次
setTimeout(() => {
mediaRecorder.stop();
}, 5000); // 录制5秒后停止
});
}
}
// 接收并播放视频
hosline.on('priveateMessage', function (blob, fromid) {
var video = document.getElementById('video2');
var url = URL.createObjectURL(blob);
video.src = url;
video.play();
});
服务端代码
服务端不需要对流进行特殊处理,只需将其从一个客户端转发到另一个客户端即可:
const io = require('socket.io')(server);
io.on('connection', function (socket) {
socket.on('priveateMessage', function (blob, toWho) {
socket.broadcast.to(toWho).emit('priveateMessage', blob, socket.id);
});
});
解释
-
客户端:
- 使用
navigator.mediaDevices.getUserMedia
获取媒体流。 - 使用
MediaRecorder
对流进行录制,并将录制的数据转换为 Blob。 - 通过 Socket.IO 发送 Blob 数据。
- 使用
-
服务端:
- 收到 Blob 数据后,广播给指定的客户端。
-
接收端:
- 接收到 Blob 后,创建一个 URL 并将其设置为视频元素的
src
属性。
- 接收到 Blob 后,创建一个 URL 并将其设置为视频元素的
这种方法避免了直接传递复杂的 MediaStream
对象,而是通过 Blob 进行传递,从而解决了类型错误的问题。
传递 MediaStream
对象通过 Socket.IO 并不是直接可行的,因为 MediaStream
对象包含大量复杂的数据,并且它与浏览器上下文紧密相关,无法通过网络传输。通常的做法是传递媒体流的相关信息(例如媒体流的 URL 或媒体源 ID),然后在接收方重新获取或生成相应的媒体流。
示例
客户端代码
首先,你需要将媒体流的 URL 发送到服务器,而不是发送整个媒体流对象。
var hosline = io.connect();
function startVideo() {
var video = document.getElementById("video1");
var videoObj = {"video": true};
if (navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function (stream) {
var src = window.URL.createObjectURL(stream);
video.src = src;
video.play();
// 发送媒体流的 URL 到服务器
hosline.emit('priveateMessage', { streamUrl: src, toWho: "socketIdHere" });
}, function (err) {
console.log("Error: ", err);
});
}
}
服务端代码
服务器接收到媒体流的 URL 后,可以将其转发给目标客户端。
const io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.on('priveateMessage', function(data) {
const { streamUrl, toWho } = data;
io.sockets.connected[toWho].emit('priveateMessage', { streamUrl: streamUrl });
});
});
接收方客户端代码
接收方客户端接收到媒体流的 URL 后,可以创建一个新的视频元素并设置其 src
属性来播放视频。
hosline.on('priveateMessage', function(data) {
var src = data.streamUrl;
var video = document.createElement('video');
video.src = src;
document.body.appendChild(video); // 或者插入到任何其他 DOM 元素中
video.play();
});
解释
- 客户端:使用
window.URL.createObjectURL
创建媒体流的 URL,并将其发送到服务器。 - 服务器:接收 URL 并转发给目标客户端。
- 接收方客户端:接收到 URL 后,使用
window.URL.createObjectURL
再次创建媒体流对象,并在新的视频元素上播放。
这种方法确保了数据的有效传输,并且避免了直接传递复杂的媒体流对象带来的问题。