我能够使用socket.io将流blob发送到节点js服务器。但是,在更新视频播放器中的blob数据时它会闪烁。我希望它顺利运行。如何在不闪烁视频播放器的情况下发送数据。这是我的服务器代码
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
var fs = require("fs")
app.use(express.static('public'))
app.get("/", function(req, res){
res.sendFile(__dirname+ "/public/index.html");
});
io.on("connection", function(socket) {
console.log("A user is connected");
socket.on("send", function(data){
console.log(data);
socket.emit("data", data);
});
socket.on("disconnect", function() {
console.log("A user is disconnected");
});
});
http.listen(3000, function(){
console.log("Server is started at port 3000\nTo close use Ctrl+C");
});
这是我的客户端代码,
<html>
<head><title>Testing</title>
<script src="socket.io/socket.io.js"></script>
<script type="text/javascript" src="MediaStreamRecorder.js"></script>
</head>
<body>
<video autoplay="true" id="video"></video>
<script type="text/javascript">
var socket = io();
window.URL.createObjectURL = window.URL.createObjectURL || window.URL.webkitCreateObjectURL || window.URL.mozCreateObjectURL || window.URL.msCreateObjectURL;
socket.on("data", function(data){
var binaryData = [];
binaryData.push(data);
videoElement = document.getElementById('video');
videoElement.src = window.URL.createObjectURL(new Blob(binaryData, {type: "video/webm"}));
});
var mediaConstraints = {
video: true
};
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var arrayOfStreams = [stream];
var medias = new MediaStreamRecorder(stream);
medias.ondataavailable = function(blob) {
socket.emit("send", blob);
};
medias.start();
}
function onMediaError(e) {
console.error('media error', e);
}
</script>
</body>
</html>
我将MediaStreamRecorder api中的timeslice值更改为500默认值。因此,在500毫秒后将数据发送到服务器。但是在网页上闪烁。我必须这样才能让它成为现实。任何帮助将不胜感激。
答案 0 :(得分:1)
但是,在更新视频播放器中的blob数据时它会闪烁。
您正在更改.src
元素的<video>
。
URL.createObjectURL()
和MediaStreamRecorder
不是必需的。
您可以传递.src
对象一次,并将<video>
元素MediaStream
设置为传递的<video>
,而不是更改.srcObject
元素的MediaStream
。 }。
videoElement = document.getElementById("video");
function onMediaSuccess(stream) {
if (videoElement.srcObject === null) {
videoElement.srcObject = stream
}
}
var videoElement = document.getElementById("video");
videoElement.oncanplay = function() {
videoElement.play();
}
var media = document.createElement("video");
media.src = "https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4";
media.oncanplay = function() {
media.play();
var stream = media.captureStream();
onMediaSuccess(stream);
}
function onMediaSuccess(stream) {
if (videoElement.srcObject === null) {
videoElement.srcObject = stream
}
}
<video id="video"></video>
如果要求发送Blob
,您可以使用MediaSource
,使用Blob
或ArrayBuffer
将FileReader
转换为fetch()
并附加ArrayBuffer
至SourceBuffer
,请参阅Unable to stream video over a websocket to Firefox。
答案 1 :(得分:0)
您正在使用使用TCP连接的socket.io。如果你想让你的应用程序实时像Skype一样,你必须使用UDP连接。
如果一帧滞后,那么您的应用程序应该忽略这一点,但在您的情况下,您将使用TCP连接,因此它将始终按顺序传递。防火墙也是TCP连接的问题。您说您尝试将超时设置为500毫秒,这对于实时应用来说太大了,这就是为什么您的视频会闪烁。
如果您愿意放弃TCP连接,我有一个小解决方案。我试过这个并且工作正常。
https://www.youtube.com/watch?v=ieBtXwHvoNk
只有一个问题是,在这种情况下,您无法直接在WAN上发送数据包,因为您可以轻松地在websockets中执行此操作。你必须在你的服务器上实现STUN / TURN或类似的东西。
如果您仍有疑问,请查看此github问题并阅读所有回复:https://github.com/socketio/socket.io/issues/1175
我希望这会有所帮助。