Howto stream webcam data to a server? - javascript

I'm looking for a way to stream the webcam data from a browser to a webserver. The webcam data is acquired by using getUserMedia. One common option seems to be to use a canvas and a timer in order to send screenshots to a server, but I want a proper video stream. WEBRTC seems to be another option, but that might be a bit over the top, plus there is not too much software that runs on a server (i.e. non-browser), speaks WEBRTC, and has bindings for Python.
Maybe I'm missing sompling simpler. For example, could the video stream be streamed using Websockets?
'use strict';
var errorCallback = function(e) {
console.log('Rejected!', e);
};
var successCallback = function(stream) {
console.log('Got Video.');
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(stream);
// ???
// Stream data to server
video.play();
};
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
var hdConstraints = {
video: {
mandatory: {
minWidth: 1280,
minHeight: 720,
}
},
audio: false,
};
if (navigator.getUserMedia) {
navigator.getUserMedia(hdConstraints, successCallback, errorCallback);
}
else {
console.log('No getUserMedia available.');
}

Looks like the current best solution is indeed to use a canvas, create an image from the webcam in regular intervals and send it via websockets.

Related

Javascript | MediaRecorder API - Recorded video file on Desktop does not play in Mobile

I am trying to develop a canva-like Insta story creator using Canvas and MediaRecorder
The app is working perfectly on a desktop browser - I am able to download the file, and play it on desktop. However, when I send that file to my mobile, it doesn't play(even on Insta). I figure this is an issue with codecs - but don't know how to solve the same.
This is the function that handles the mediaRecorderAPI
Is there any mime type that I can use, that is universal and can play for any device?
initRecorder () {
var dl = document.querySelector("#dl")
let videoStream = this.canvas.captureStream(60);
if(this.isAudioPresent) {
videoStream.addTrack(this.audioStream.getAudioTracks()[0])
}
let mediaRecorder = new MediaRecorder(videoStream, {
videoBitsPerSecond : 2500000,
mime: 'video/webm'
});
let chunks = [];
mediaRecorder.onstop = function(e) {
var blob = new Blob(chunks, { 'type' : 'video/webm' });
chunks = [];
var videoURL = URL.createObjectURL(blob);
dl.href = videoURL;
};
mediaRecorder.ondataavailable = function(e) {
e.data.size && chunks.push(e.data);
};
mediaRecorder.start();
setTimeout(function (){ mediaRecorder.stop(); },this.storytime);
}
```
Figured this out: Different browsers use different transcoding. Insta only accepts MP4 transcoding. Hence, you need to use either a transcoder on the frontend(ffmpeg.js or wasm version of ffmpeg) or send your data to backend and handle there(which I ended up doing)

How to send video stream to node.js server

My goal: send some video stream from one client to another throught node.js server. But I can`t even send video from first cleint to server.
Cleint
var socket = io(":9966");
socket.on('message', function (data) {
console.log(data)
})
function onVideoFail(e) {
console.log('webcam fail!', e);
};
window.URL = window.URL || window.webkitURL;
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
var video = document.querySelector('video');
navigator.getUserMedia({video: true}, function(stream) {
console.log(stream);
video.src = window.URL.createObjectURL(stream);
var arrayOfStreams = [stream];
var medias = new MediaStreamRecorder(stream);
medias.ondataavailable = function(blob) {
socket.emit("streaming", blob);
};
medias.start();
socket.emit("streaming", stream);
socket.emit('test', 'mess from 1');
}, onVideoFail);
Server
io.on('connection', function (socket) {
log.info('new con!', socket.id);
socket.send("you connected to server");
socket.on('test', function (data) {
console.log(data);
socket.broadcast.send(data);
});
socket.on('streaming', function (stream) {
log.info("i`m in stream", socket.id);
log.info(stream);
socket.broadcast.emit('streaming', stream);
});
});
I can send text and everything great, but when I send stream to server I get empty value.
What I see on server side
I looked for some tips and found, but still not working. Maybe I missed something.
Can anyone help me?
PS I getting video from video tag
convert your media to base64, this way the server reads it as a string of texts and returns it back
Question is closed. As I red its hard to make live stream. If somebody reading this, check this link https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder . What you must understand: record little part of video and send it to server. Hope it`s will help.

Audio recording plays back at inconsistent rate

I am using the code below to record audio in the browser, then use socket.io to send the resulting blob to a node.js server. The data is then saved to a mysql database or as an .ogg file.
The playback from either is strangely garbled at times - in different moments the sound will suddenly accelerate then return to normal. I've not been able to find anything online about this issue.
UPDATE: Further testing leads me to believe it is a hardware/software/compatibility with the Asus D1 soundcard I'm using. recording off of other devices does not result in the same behavior.
var mediaRecorder;
var startRecord = function(recordData){
if (!navigator.getUserMedia)
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({audio:true}, success, function(stream) {
alert('Error capturing audio.');
});
} else alert('getUserMedia not supported in this browser.');
function success(stream) {
var chunks = [];
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
mediaRecorder.onstop = function(e) {
stream.getAudioTracks()[0].stop()
var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' })
var audioURL = URL.createObjectURL(blob);
if (recordData.id) {
socket.emit('audio', {
'id':recordData.id,
'audio':blob,
'option':recordData.type
});
}
mediaRecorder.ondataavailable = function(e) {
chunks.push(e.data);
}
}
};
var stopRecord = function(recordData){
mediaRecorder.stop();
mediaRecorder.state = 'recording'
};

Using MediaSource for video with MediaRecord

I'm trying to broadcast a video from my webcam in javascript. I'm using MediaStream to get the video from my webcam, MediaRecorder to record such video in chunks (which would be transmitted to the server), and MediaSource to assemble these chunks and play them seamlessly in a video container called watchVideo on the source below.
It all works perfectly when i'm capturing only video, i.e. constraints = { video: true } ; but if I add audio, the watchVideo doesn't display anything, and the console shows me the following error:
Uncaught DOMException: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source.
This is the relevant part of the code:
var mime = 'video/webm; codecs=vp8';
if (navigator.mediaDevices) {
constraints = { video: true, audio: true };
navigator.mediaDevices.getUserMedia(constraints)
.then(handleUserMedia)
.catch( err => {
console.log("ERROR: " + err);
})
}
function handleUserMedia(stream) {
source = new MediaSource();
watchVideo.src = window.URL.createObjectURL(source);
source.onsourceopen = () => {
buffer = source.addSourceBuffer(mime);
};
var options = { mimeType: mime };
mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.ondataavailable = handleDataAvailable;
}
function handleDataAvailable(evt) {
var filereader = new FileReader();
filereader.onload = () => {
buffer.appendBuffer(filereader.result );
};
filereader.readAsArrayBuffer(evt.data);
}
I came across the question and it actually helped me more than many answers related to this topic. I don't know if you are still interested in the answer but I have tried
mime="video/webm; codecs="vp9,opus"
and it worked fine with audio and video, I hope this answer will help you

MediaRecorder Alternatives

Ive been playing about with MediaRecorder to save a MediaStream that has been created by getUserMedia. I'm really happy with the results, however I need something similar that has better cross browser support.
Here is some sample code for how I'm using MediaRecorder (just to give you some context):
var mediaRec;
navigator.getUserMedia({
audio:true
},function(stream){
mediaRec=new MediaRecorder(stream);
mediaRec.start(10000);
mediaRec.ondataavailable=function(e){
};
},function(err){});
It seems that MediaRecorder only works in the Firefox browser and the Firefox OS.
However MediaRecorder is part of the W3C Specification, and Google Chrome has stated it intends to support it in a future release, but what options do I have in the meantime?
I know that plug ins such as Flash and Silverlight can achieve the same thing that MediaRecorder performs, but what I need is a javascript solution.
Can anyone help?
All the other options that are available will be utilizing high-level APIs and implemented at the Browser/JavaScript level. Thus, none will really be comparable to the MediaRecorder API provided by Firefox as it is integrated into the browser and has the benefit of being "lower level" in the browser's implementation.
One option I know that works for sure(though utilizes the Web Audio API) is Matt Diamond's Recorderjs.
And Example using Recorderjs taken from Matt's github.
var audio_context;
var recorder;
function startUserMedia(stream) {
var input = audio_context.createMediaStreamSource(stream);
input.connect(audio_context.destination);
recorder = new Recorder(input);
}
function startRecording() {
recorder.record();
}
function stopRecording(button) {
recorder.stop();
createDownloadLink();
recorder.clear();
}
function createDownloadLink() {
recorder.exportWAV(function(blob) {
var url = URL.createObjectURL(blob);
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
au.controls = true;
au.src = url;
hf.href = url;
hf.download = new Date().toISOString() + '.wav';
hf.innerHTML = hf.download;
li.appendChild(au);
li.appendChild(hf);
recordingslist.appendChild(li);
});
}
window.onload = function init() {
try {
// webkit shim
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
window.URL = window.URL || window.webkitURL;
audio_context = new AudioContext;
navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
console.log('No live audio input: ' + e);
});

Categories

Resources