Pregunta Cómo grabar cámara web y audio usando webRTC y una conexión de Peer basada en servidor


Me gustaría grabar la cámara web y el audio de los usuarios y guardarlo en un archivo en el servidor. Estos archivos podrían luego ser servidos a otros usuarios.

No tengo problemas con la reproducción, sin embargo, tengo problemas para grabar el contenido.

Mi entendimiento es que getUserMedia .record() la función todavía no se ha escrito, solo se ha hecho una propuesta para ella hasta el momento.

Me gustaría crear una conexión de igual en mi servidor utilizando la PeerConnectionAPI. Entiendo que esto es un poco raro, pero creo que debería ser posible crear un par en el servidor y registrar lo que envía el cliente-par.

Si esto es posible, debería poder guardar esta información en flv o en cualquier otro formato de video.

Mi preferencia es grabar la cámara + audio del lado del cliente, para permitir que el cliente vuelva a grabar videos si no le gustó su primer intento antes de subirlo. Esto también permitiría interrupciones en las conexiones de red. He visto un código que permite grabar "imágenes" individuales desde la cámara web al enviar los datos al lienzo, eso es genial, pero también necesito el audio.

Aquí está el código del lado del cliente que tengo hasta ahora:

  <video autoplay></video>

<script language="javascript" type="text/javascript">
function onVideoFail(e) {
    console.log('webcam fail!', e);
  };

function hasGetUserMedia() {
  // Note: Opera is unprefixed.
  return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia || navigator.msGetUserMedia);
}

if (hasGetUserMedia()) {
  // Good to go!
} else {
  alert('getUserMedia() is not supported in your browser');
}

window.URL = window.URL || window.webkitURL;
navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia || navigator.msGetUserMedia;

var video = document.querySelector('video');
var streamRecorder;
var webcamstream;

if (navigator.getUserMedia) {
  navigator.getUserMedia({audio: true, video: true}, function(stream) {
    video.src = window.URL.createObjectURL(stream);
    webcamstream = stream;
//  streamrecorder = webcamstream.record();
  }, onVideoFail);
} else {
    alert ('failed');
}

function startRecording() {
    streamRecorder = webcamstream.record();
    setTimeout(stopRecording, 10000);
}
function stopRecording() {
    streamRecorder.getRecordedData(postVideoToServer);
}
function postVideoToServer(videoblob) {
/*  var x = new XMLHttpRequest();
    x.open('POST', 'uploadMessage');
    x.send(videoblob);
*/
    var data = {};
    data.video = videoblob;
    data.metadata = 'test metadata';
    data.action = "upload_video";
    jQuery.post("http://www.foundthru.co.uk/uploadvideo.php", data, onUploadSuccess);
}
function onUploadSuccess() {
    alert ('video uploaded');
}

</script>

<div id="webcamcontrols">
    <a class="recordbutton" href="javascript:startRecording();">RECORD</a>
</div>

75
2018-05-15 17:06


origen


Respuestas:


Definitivamente deberías echarle un vistazo a Kurento. Proporciona una infraestructura de servidor WebRTC que le permite grabar desde un alimentador WebRTC y mucho más. También puede encontrar algunos ejemplos para la aplicación que está planeando aquí. Es realmente fácil agregar capacidades de grabación a esa demostración, y almacenar el archivo multimedia en un URI (disco local o donde sea).

El proyecto tiene licencia bajo LGPL Apache 2.0


EDIT 1

Desde esta publicación, hemos agregado un nuevo tutorial que muestra cómo agregar la grabadora en un par de escenarios

Descargo de responsabilidad: soy parte del equipo que desarrolla Kurento.


42
2017-07-25 16:18



Por favor, checa el RecordRTC

RecordRTC tiene licencia de MIT en github.


14
2018-06-30 12:22



Creo que usar kurento u otras MCU solo para grabar videos sería un poco exagerado, especialmente teniendo en cuenta el hecho de que Chrome tiene MediaRecorder Soporte API desde v47 y Firefox desde v25. Entonces, en este cruce, puede que ni siquiera necesite una biblioteca js externa para hacer el trabajo, pruebe esta demostración que hice para grabar video / audio usando MediaRecorder:

Manifestación - Funcionaría en Chrome y Firefox (se omitió intencionalmente empujando blob al código del servidor)

Fuente de código Github

Si ejecuta Firefox, puede probarlo aquí mismo (Chrome necesita https)

'use strict'

let log = console.log.bind(console),
  id = val => document.getElementById(val),
  ul = id('ul'),
  gUMbtn = id('gUMbtn'),
  start = id('start'),
  stop = id('stop'),
  stream,
  recorder,
  counter = 1,
  chunks,
  media;


gUMbtn.onclick = e => {
  let mv = id('mediaVideo'),
    mediaOptions = {
      video: {
        tag: 'video',
        type: 'video/webm',
        ext: '.mp4',
        gUM: {
          video: true,
          audio: true
        }
      },
      audio: {
        tag: 'audio',
        type: 'audio/ogg',
        ext: '.ogg',
        gUM: {
          audio: true
        }
      }
    };
  media = mv.checked ? mediaOptions.video : mediaOptions.audio;
  navigator.mediaDevices.getUserMedia(media.gUM).then(_stream => {
    stream = _stream;
    id('gUMArea').style.display = 'none';
    id('btns').style.display = 'inherit';
    start.removeAttribute('disabled');
    recorder = new MediaRecorder(stream);
    recorder.ondataavailable = e => {
      chunks.push(e.data);
      if (recorder.state == 'inactive') makeLink();
    };
    log('got media successfully');
  }).catch(log);
}

start.onclick = e => {
  start.disabled = true;
  stop.removeAttribute('disabled');
  chunks = [];
  recorder.start();
}


stop.onclick = e => {
  stop.disabled = true;
  recorder.stop();
  start.removeAttribute('disabled');
}



function makeLink() {
  let blob = new Blob(chunks, {
      type: media.type
    }),
    url = URL.createObjectURL(blob),
    li = document.createElement('li'),
    mt = document.createElement(media.tag),
    hf = document.createElement('a');
  mt.controls = true;
  mt.src = url;
  hf.href = url;
  hf.download = `${counter++}${media.ext}`;
  hf.innerHTML = `donwload ${hf.download}`;
  li.appendChild(mt);
  li.appendChild(hf);
  ul.appendChild(li);
}
      button {
        margin: 10px 5px;
      }
      li {
        margin: 10px;
      }
      body {
        width: 90%;
        max-width: 960px;
        margin: 0px auto;
      }
      #btns {
        display: none;
      }
      h1 {
        margin-bottom: 100px;
      }
<link type="text/css" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<h1> MediaRecorder API example</h1>

<p>For now it is supported only in Firefox(v25+) and Chrome(v47+)</p>
<div id='gUMArea'>
  <div>
    Record:
    <input type="radio" name="media" value="video" checked id='mediaVideo'>Video
    <input type="radio" name="media" value="audio">audio
  </div>
  <button class="btn btn-default" id='gUMbtn'>Request Stream</button>
</div>
<div id='btns'>
  <button class="btn btn-default" id='start'>Start</button>
  <button class="btn btn-default" id='stop'>Stop</button>
</div>
<div>
  <ul class="list-unstyled" id='ul'></ul>
</div>
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>


8
2018-04-22 02:29



sí, como usted entendió, MediaStreamRecorder no está implementado actualmente.

MediaStreamRecorder es una API de WebRTC para grabar streams de getUserMedia (). Permite a las aplicaciones web crear un archivo a partir de una sesión de audio / video en vivo.

alternativamente, puede hacer esto http://ericbidelman.tumblr.com/post/31486670538/creating-webm-video-from-getusermedia pero el audio le falta parte.


7
2018-05-21 11:20



Puedes usar RecordRTC-juntos, que se basa en RecordRTC.

Es compatible con la grabación de video y audio juntos en archivos separados. Necesitarás una herramienta como ffmpeg fusionar dos archivos en uno en el servidor.


4
2017-11-10 16:26



Servidor de llamadas web 4 puede grabar audio y video de WebRTC en el contenedor de WebM. La grabación se realiza utilizando el códec Vorbis para audio y el códec VP8 para video. Los codecs WebRTC iniciales son Opus o G.711 y VP8. Por lo tanto, la grabación en el lado del servidor requiere Opus / G.711 a la transcodificación del lado del servidor de Vorbis o la transcodificación VP8-H.264 si es necesario utilizar otro contenedor, es decir, AVI.


0
2017-09-10 20:14



Para el registro, tampoco tengo suficiente conocimiento sobre esto,

Pero encontré esto en el centro de Git-

<!DOCTYPE html>
 <html>
<head>
  <title>XSockets.WebRTC Client example</title>
  <meta charset="utf-8" />


<style>
body {

  }
.localvideo {
position: absolute;
right: 10px;
top: 10px;
}

.localvideo video {
max-width: 240px;
width:100%;
margin-right:auto;
margin-left:auto;
border: 2px solid #333;

 }
 .remotevideos {
height:120px;
background:#dadada;
padding:10px; 
}

.remotevideos video{
max-height:120px;
float:left;
 }
</style>
</head>
<body>
<h1>XSockets.WebRTC Client example </h1>
<div class="localvideo">
    <video autoplay></video>
</div>

<h2>Remote videos</h2>
<div class="remotevideos">

</div>
<h2>Recordings  ( Click on your camera stream to start record)</h2>
<ul></ul>


<h2>Trace</h2>
<div id="immediate"></div>
<script src="XSockets.latest.js"></script>
<script src="adapter.js"></script>
<script src="bobBinder.js"></script>
<script src="xsocketWebRTC.js"></script>
<script>
    var $ = function (selector, el) {
        if (!el) el = document;
        return el.querySelector(selector);
    }
    var trace = function (what, obj) {
        var pre = document.createElement("pre");
        pre.textContent = JSON.stringify(what) + " - " + JSON.stringify(obj || "");
        $("#immediate").appendChild(pre);
    };
    var main = (function () {
        var broker;
        var rtc;
        trace("Ready");
        trace("Try connect the connectionBroker");
        var ws = new XSockets.WebSocket("wss://rtcplaygrouund.azurewebsites.net:443", ["connectionbroker"], {
            ctx: '23fbc61c-541a-4c0d-b46e-1a1f6473720a'
        });
        var onError = function (err) {
            trace("error", arguments);
        };
        var recordMediaStream = function (stream) {
            if ("MediaRecorder" in window === false) {
                trace("Recorder not started MediaRecorder not available in this browser. ");
                return;
            }
            var recorder = new XSockets.MediaRecorder(stream);
            recorder.start();
            trace("Recorder started.. ");
            recorder.oncompleted = function (blob, blobUrl) {
                trace("Recorder completed.. ");
                var li = document.createElement("li");
                var download = document.createElement("a");
                download.textContent = new Date();
                download.setAttribute("download", XSockets.Utils.randomString(8) + ".webm");
                download.setAttribute("href", blobUrl);
                li.appendChild(download);
                $("ul").appendChild(li);
            };
        };
        var addRemoteVideo = function (peerId, mediaStream) {
            var remoteVideo = document.createElement("video");
            remoteVideo.setAttribute("autoplay", "autoplay");
            remoteVideo.setAttribute("rel", peerId);
            attachMediaStream(remoteVideo, mediaStream);
            $(".remotevideos").appendChild(remoteVideo);
        };
        var onConnectionLost = function (remotePeer) {
            trace("onconnectionlost", arguments);
            var peerId = remotePeer.PeerId;
            var videoToRemove = $("video[rel='" + peerId + "']");
            $(".remotevideos").removeChild(videoToRemove);
        };
        var oncConnectionCreated = function () {
            console.log(arguments, rtc);
            trace("oncconnectioncreated", arguments);
        };
        var onGetUerMedia = function (stream) {
            trace("Successfully got some userMedia , hopefully a goat will appear..");
            rtc.connectToContext(); // connect to the current context?
        };
        var onRemoteStream = function (remotePeer) {
            addRemoteVideo(remotePeer.PeerId, remotePeer.stream);
            trace("Opps, we got a remote stream. lets see if its a goat..");
        };
        var onLocalStream = function (mediaStream) {
            trace("Got a localStream", mediaStream.id);
            attachMediaStream($(".localvideo video "), mediaStream);
            // if user click, video , call the recorder
            $(".localvideo video ").addEventListener("click", function () {
                recordMediaStream(rtc.getLocalStreams()[0]);
            });
        };
        var onContextCreated = function (ctx) {
            trace("RTC object created, and a context is created - ", ctx);
            rtc.getUserMedia(rtc.userMediaConstraints.hd(false), onGetUerMedia, onError);
        };
        var onOpen = function () {
            trace("Connected to the brokerController - 'connectionBroker'");
            rtc = new XSockets.WebRTC(this);
            rtc.onlocalstream = onLocalStream;
            rtc.oncontextcreated = onContextCreated;
            rtc.onconnectioncreated = oncConnectionCreated;
            rtc.onconnectionlost = onConnectionLost;
            rtc.onremotestream = onRemoteStream;
            rtc.onanswer = function (event) {
            };
            rtc.onoffer = function (event) {
            };
        };
        var onConnected = function () {
            trace("connection to the 'broker' server is established");
            trace("Try get the broker controller form server..");
            broker = ws.controller("connectionbroker");
            broker.onopen = onOpen;
        };
        ws.onconnected = onConnected;
    });
    document.addEventListener("DOMContentLoaded", main);
</script>

En la línea número 89, en mi caso, el código OnrecordComplete anexa un enlace del archivo de la grabadora. Si hace clic en ese enlace, comenzará la descarga, puede guardar esa ruta en su servidor como un archivo.

El código de grabación se ve algo como esto

recorder.oncompleted = function (blob, blobUrl) {
                trace("Recorder completed.. ");
                var li = document.createElement("li");
                var download = document.createElement("a");
                download.textContent = new Date();
                download.setAttribute("download", XSockets.Utils.randomString(8) + ".webm");
                download.setAttribute("href", blobUrl);
                li.appendChild(download);
                $("ul").appendChild(li);
            };

El blobUrl contiene el camino. Resolví mi problema con esto, espero que alguien lo encuentre útil


0
2018-04-24 05:11



Echa un vistazo a Janus. Aquí hay una demostración de grabación:

https://janus.conf.meetecho.com/recordplaytest.html

A diferencia de Kurento, cuyo desarrollo se ha ralentizado severamente después de la adquisición de Twilio, Janus continúa siendo activamente desarrollado y respaldado.


0
2018-01-03 10:36



Técnicamente puedes usar FFMPEG en back-end para mezclar video y audio


-4
2017-11-11 16:45