Chciałbym nagrać kamerę internetową i dźwięk użytkownika i zapisać do pliku na serwerze. Te pliki mogłyby być następnie udostępniane innym użytkownikom.
Nie mam problemów z odtwarzaniem, ale mam problemy z nagraniem zawartości.
Rozumiem, że .record()
funkcja getUserMedia nie została jeszcze napisana - do tej pory złożono tylko propozycję.
Chciałbym utworzyć połączenie równorzędne na moim serwerze za pomocą PeerConnectionAPI. Rozumiem, że to trochę hakerskie, ale myślę, że powinno być możliwe utworzenie peera na serwerze i zarejestrowanie tego, co wysyła klient-peer.
Jeśli jest to możliwe, powinienem być w stanie zapisać te dane do flv lub innego formatu wideo.
W rzeczywistości wolę nagrywać kamerę internetową + dźwięk po stronie klienta, aby umożliwić klientowi ponowne nagrywanie filmów, jeśli nie podobała mu się pierwsza próba przed przesłaniem. Pozwoliłoby to również na przerwy w połączeniach sieciowych. Widziałem kod, który umożliwia nagrywanie poszczególnych „obrazów” z kamery internetowej poprzez wysyłanie danych do kanwy - to fajne, ale potrzebuję też dźwięku.
Oto kod po stronie klienta, który mam do tej pory:
<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>
źródło
Odpowiedzi:
Zdecydowanie powinieneś rzucić okiem na Kurento . Zapewnia infrastrukturę serwera WebRTC, która umożliwia nagrywanie z kanału WebRTC i wiele więcej. Można również znaleźć kilka przykładów zastosowania planujesz tutaj . Naprawdę łatwo jest dodać możliwości nagrywania do tej demonstracji i przechowywać plik multimedialny w URI (dysk lokalny lub gdziekolwiek).
Projekt jest objęty licencją
LGPLApache 2.0EDYCJA 1
Od tego postu dodaliśmy nowy samouczek, który pokazuje, jak dodać rejestrator w kilku scenariuszach
Zastrzeżenie: jestem częścią zespołu, który rozwija Kurento.
źródło
Proszę sprawdzić RecordRTC
RecordRTC jest licencjonowane przez MIT na github .
źródło
Uważam za pomocą kurento lub innych mikrokontrolerów tylko do nagrywania filmów byłoby trochę przesadą, zwłaszcza biorąc pod uwagę fakt, że Chrome ma MediaRecorder API wsparcie od V47 i Firefox od V25. Więc na tym skrzyżowaniu możesz nawet nie potrzebować zewnętrznej biblioteki js do wykonania pracy, wypróbuj to demo, które zrobiłem, aby nagrywać wideo / audio za pomocą MediaRecorder:
Demo - działałoby w Chrome i Firefox (celowo pominięto wypychanie obiektu blob do kodu serwera)
Źródło kodu Github
Jeśli korzystasz z Firefoksa, możesz go przetestować w tym miejscu (Chrome potrzebuje
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>
źródło
tak, jak zrozumiałeś, MediaStreamRecorder nie jest obecnie zaimplementowany.
MediaStreamRecorder to API WebRTC do nagrywania strumieni getUserMedia (). Umożliwia aplikacjom internetowym tworzenie plików z sesji audio / wideo na żywo.
alternatywnie możesz to zrobić http://ericbidelman.tumblr.com/post/31486670538/creating-webm-video-from-getusermedia, ale brakuje dźwięku.
źródło
Możesz używać RecordRTC razem , który jest oparty na RecordRTC.
Obsługuje nagrywanie wideo i audio razem w osobnych plikach. Będziesz potrzebował narzędzia takiego jak
ffmpeg
połączenie dwóch plików w jeden na serwerze.źródło
Web Call Server 4 może nagrywać dźwięk i wideo WebRTC do kontenera WebM. Nagrywanie odbywa się za pomocą kodeka Vorbis dla audio i kodeka VP8 dla wideo. Pierwotne kodeki WebRTC to Opus lub G.711 i VP8. Zatem nagrywanie po stronie serwera wymaga transkodowania Opus / G.711 do Vorbis po stronie serwera lub transkodowania VP8-H.264, jeśli konieczne jest użycie innego kontenera, tj. AVI.
źródło
Dla porządku, też nie mam wystarczającej wiedzy na ten temat,
Ale znalazłem to w centrum 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>
W linii numer 89 w moim przypadku kod OnrecordComplete faktycznie dołącza link do pliku rejestratora, jeśli klikniesz ten link, rozpocznie się pobieranie, możesz zapisać tę ścieżkę na serwerze jako plik.
Kod nagrywania wygląda mniej więcej tak
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); };
BlobUrl przechowuje ścieżkę. Rozwiązałem swój problem z tym, mam nadzieję, że komuś to się przyda
źródło
Z technicznego punktu widzenia można użyć FFMPEG na zapleczu do miksowania wideo i audio
źródło