Как отправить записанный поток getusermedia на сервер nodejs в реальном времени

Я могу отправить потоковый BLOB-объект с помощью socket.io на сервер node 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> 

Я изменил значение временного интервала в API MediaStreamRecorder на 500 по умолчанию. Итак, отправка данных на сервер через 500 миллисекунд. Но мигает на веб-странице. Я должен сделать это в реальном времени. Любая помощь будет оценена.


person Shawon    schedule 30.07.2017    source источник


Ответы (2)


Вы используете socket.io, который использует TCP-соединение. Если вы хотите, чтобы ваше приложение работало в режиме реального времени наподобие скайпа, вы должны использовать UDP-соединение.

Если один кадр отстает, ваше приложение должно игнорировать это, но в вашем случае вы используете TCP-соединение, поэтому оно всегда будет доставляться по порядку. Брандмауэр также является проблемой для TCP-соединения. Вы сказали, что пытались установить тайм-аут на 500 мс, что слишком много для приложения реального времени, поэтому ваше видео мигает.

Если вы готовы отказаться от TCP-соединения, у меня есть для этого небольшое решение. Я пробовал это, и это работает нормально.

https://www.youtube.com/watch?v=ieBtXwHvoNk

Единственная проблема заключается в том, что в этом случае вы не можете отправлять свои пакеты по глобальной сети напрямую, как это легко можно сделать в веб-сокетах. Вы должны реализовать STUN/TURN или что-то подобное на своем сервере.

Если у вас все еще есть какие-то сомнения, посмотрите эту проблему на github и прочитайте все ответы: https://github.com/socketio/socket.io/issues/1175

Надеюсь, это поможет.

person Apal Shah    schedule 30.08.2017

Но он мигает при обновлении данных 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, см. Невозможно передать потоковое видео через веб-сокет в Firefox.

person guest271314    schedule 30.07.2017