Export HTML5 blob video to MP4 - html

I am trying to use Chrome's screen sharing feature to make a screen recorder and save the video in MP4 format. However, I have no idea how I do this. The demo is at https://figgycity50.kd.io/screencap.html (include https!) and the code is:
<video autoplay></video>
<button>start</button>
<script>
navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.getUserMedia;
var stream = null;
button = document.querySelector("button");
function start(e) {
// Seems to only work over SSL.
navigator.getUserMedia({
video: {
mandatory: {
chromeMediaSource: 'screen',
maxWidth: 1280,
maxHeight: 720
}
}
}, function(s) {
stream = s;
button.textContent = 'Stop';
button.removeEventListener('click', start);
button.addEventListener('click', stop);
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(stream);
video.autoplay = true;
stream.onended = function(e) {
//The save code should go here.
};
//document.body.appendChild(video);
}, function(e) {
});
}
function stop() {
stream.stop();
button.addEventListener('click', start);
button.textContent = 'Capture your screen';
}
button.addEventListener('click', start);
</script>
How do I do this?

You cannot save directly to MP4 format with the way the current state of getUserMedia API is working, you can however save in webm format and convert it afterwards.
Several attempts have been made, webRTC experiment project has several versions of recording in the browser implemented:
https://www.webrtc-experiment.com/RecordRTC/
You can however save directly in MP4 format using HTML Media Capture.
This works by extending the <input type="file"/> and adding new values for the accept parameter with options for audio, video and photo/snapshot. This however works only for mobile browsers, as the desktop browser will only interpret it as a simple file upload.
HDFVR has a demo of this, if you access their demo from a mobile device.
More details can be read in the following article:
http://hdfvr.com/html5-video-recording

Related

WebAudio streaming with fetch : DOMException: Unable to decode audio data

I'm trying to play an infinite stream coming from the fetch API using Chrome 51. (a webcam audio stream as Microsoft PCM, 16 bit, mono 11025 Hz)
The code works almost OK with mp3s files, except some glitches, but it does not work at all with wav files for some reason i get "DOMException: Unable to decode audio data"
The code is adapted from this answer Choppy/inaudible playback with chunked audio through Web Audio API
Any idea if its possible to make it work with WAV streams ?
function play(url) {
var context = new (window.AudioContext || window.webkitAudioContext)();
var audioStack = [];
var nextTime = 0;
fetch(url).then(function(response) {
var reader = response.body.getReader();
function read() {
return reader.read().then(({ value, done })=> {
context.decodeAudioData(value.buffer, function(buffer) {
audioStack.push(buffer);
if (audioStack.length) {
scheduleBuffers();
}
}, function(err) {
console.log("err(decodeAudioData): "+err);
});
if (done) {
console.log('done');
return;
}
read()
});
}
read();
})
function scheduleBuffers() {
while ( audioStack.length) {
var buffer = audioStack.shift();
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
if (nextTime == 0)
nextTime = context.currentTime + 0.01; /// add 50ms latency to work well across systems - tune this if you like
source.start(nextTime);
nextTime += source.buffer.duration; // Make the next buffer wait the length of the last buffer before being played
};
}
}
Just use play('/path/to/mp3') to test the code. (the server needs to have CORS enabled, or be on the same domain your run script from)
AudioContext.decodeAudioData just isn't designed to decode partial files; it's intended for "short" (but complete) files. Due to the chunking design of MP3, it sometimes works on MP3 streams, but wouldn't on WAV files. You'll need to implement your own decoder in this case.
Making the wav stream sound correctly implies to add WAV headers to the chunks as Raymond suggested, plus some webaudio magic and paquet ordering checks;
Some cool guys helped me to setup that module to handle just that and it works beautifully on Chrome : https://github.com/revolunet/webaudio-wav-stream-player
Now works on Firefox 57+ with some config flags on : https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader#Browser_compatibility

Embed camera frame in web app html5

I want to beuild web app that the user will upload a image from device camera.
I know that I can use <input type="file" accept="image/*" capture="camera">.
My question is that if there is a way to "embed" the camera screen in the page itself. In other words, I want that the screen will look like this:
I suggest you can read the article Capturing Audio & Video in HTML5.
Here is the code to access your camera:
<video autoplay></video>
<script>
var errorCallback = function(e) {
console.log('Reeeejected!', e);
};
// Not showing vendor prefixes.
navigator.getUserMedia({video: true, audio: true}, function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.
// See crbug.com/110938.
video.onloadedmetadata = function(e) {
// Ready to go. Do some stuff.
};
}, errorCallback);
</script>
Taking screenshots:
<video autoplay></video>
<img src="">
<canvas style="display:none;"></canvas>
<script>
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var localMediaStream = null;
function snapshot() {
if (localMediaStream) {
ctx.drawImage(video, 0, 0);
// "image/webp" works in Chrome.
// Other browsers will fall back to image/png.
document.querySelector('img').src = canvas.toDataURL('image/webp');
}
}
video.addEventListener('click', snapshot, false);
// Not showing vendor prefixes or code that works cross-browser.
navigator.getUserMedia({video: true}, function(stream) {
video.src = window.URL.createObjectURL(stream);
localMediaStream = stream;
}, errorCallback);
</script>
Video tag is there HTML5 to handle this. and you need to use getUserMedia api to handle the streaming. most of the modern browsers supports it. To validate whether it is supported, use javascript to check that. You can try this:
if(navigator.getUserMedia()) ....
Here's a good tutorial on how to use a web cam to capture images. The same person also has a tutorial on capturing video to GIFs.
http://davidwalsh.name/browser-camera
HTML 5 Image capture tutorial & demo

Live audio via socket.io 1.0

As from socket.io website
Binary streaming
Starting in 1.0, it's possible to send any blob back and forth: image, audio, video.
I'm now wondering, if this couldn't be the solution for something I'm trying to achieve recently.
I'm actually looking for a way how to broadcast live audio stream from (A - ie, mic input..) to all clients connected to a website of mine. Is something like this possible? I've been messing with WebRTC (https://www.webrtc-experiment.com/) examples but I haven't been able to manage the goal for more than few connected clients.
My idea is about something like getUserMedia or any other audio source (PCM, whatever..) on side A being chopped to chunks and provided to client and played for example by html5 audio element or anything.. I need to make that stream as much realtime as possible, no shout/ice cast services werent fast enough (indeed, they arent solution to my problem, they're meant to be used this way) and I don't really care about the audio quality. Crossplatform compatibility would be awesome.
Is something like that possible? By using socket.io as way how to provide those data to clients?
I would be very grateful for any reference, hint or source that could help me achieve this.
Thanks a lot.
This example shows you how to use the MediaRecorder to upload audio and then forward it using socket.io. This code will only broadcast after you're called mediaRecorder.stop(). You can choose to broadcast inside of ondataavailable. If you do that, you might want to pass a timeslice to mediaRecorder.start(), so that it doesn't trigger ondataavailable so often.
This solution isn't truly live, but I think it will help people who come back and find this question.
Client Code
var constraints = { audio: true };
navigator.mediaDevices.getUserMedia(constraints).then(function(mediaStream) {
var mediaRecorder = new MediaRecorder(mediaStream);
mediaRecorder.onstart = function(e) {
this.chunks = [];
};
mediaRecorder.ondataavailable = function(e) {
this.chunks.push(e.data);
};
mediaRecorder.onstop = function(e) {
var blob = new Blob(this.chunks, { 'type' : 'audio/ogg; codecs=opus' });
socket.emit('radio', blob);
};
// Start recording
mediaRecorder.start();
// Stop recording after 5 seconds and broadcast it to server
setTimeout(function() {
mediaRecorder.stop()
}, 5000);
});
// When the client receives a voice message it will play the sound
socket.on('voice', function(arrayBuffer) {
var blob = new Blob([arrayBuffer], { 'type' : 'audio/ogg; codecs=opus' });
var audio = document.createElement('audio');
audio.src = window.URL.createObjectURL(blob);
audio.play();
});
Server Code
socket.on('radio', function(blob) {
// can choose to broadcast it to whoever you want
socket.broadcast.emit('voice', blob);
});
In the Client Code you can write setInterval() instead of setTimeout() and then recursively call mediaRecorder.start() so that every 5 seconds the blob will be emitted continuously.
setInterval(function() {
mediaRecorder.stop()
mediaRecorder.start()
}, 5000);
Client Code
var constraints = { audio: true };
navigator.mediaDevices.getUserMedia(constraints).then(function(mediaStream) {
var mediaRecorder = new MediaRecorder(mediaStream);
mediaRecorder.onstart = function(e) {
this.chunks = [];
};
mediaRecorder.ondataavailable = function(e) {
this.chunks.push(e.data);
};
mediaRecorder.onstop = function(e) {
var blob = new Blob(this.chunks, { 'type' : 'audio/ogg; codecs=opus' });
socket.emit('radio', blob);
};
// Start recording
mediaRecorder.start();
// Stop recording after 5 seconds and broadcast it to server
setInterval(function() {
mediaRecorder.stop()
mediaRecorder.start()
}, 5000);
});
// When the client receives a voice message it will play the sound
socket.on('voice', function(arrayBuffer) {
var blob = new Blob([arrayBuffer], { 'type' : 'audio/ogg; codecs=opus' });
var audio = document.createElement('audio');
audio.src = window.URL.createObjectURL(blob);
audio.play();
});
Server Code
socket.on('voice', function(blob) {
// can choose to broadcast it to whoever you want
socket.broadcast.emit('voice', blob);
});

Capturing video from web browser in HTML5

I'm trying to follow this guide on capturing video from webcam in HTML5
http://www.html5rocks.com/en/tutorials/getusermedia/intro/
I have copied and pasted the following code but Chrome does not ask for permission to use my camera
<video autoplay></video>
<script>
var onFailSoHard = function(e) {
console.log('Reeeejected!', e);
};
// Not showing vendor prefixes.
navigator.getUserMedia({video: true, audio: true}, function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.
// See crbug.com/110938.
video.onloadedmetadata = function(e) {
// Ready to go. Do some stuff.
};
}, onFailSoHard);
</script>
Whereas when I click "capture video" in the guide it works, my webcam shows...
Another website has similar code but yet again it's not working for me
http://dev.opera.com/articles/view/playing-with-html5-video-and-getusermedia-support/
<!-- HTML code -->
<video id="sourcevid" autoplay>Put your fallback message here.</video>
/* JavaScript code */
window.addEventListener('DOMContentLoaded', function() {
// Assign the <video> element to a variable
var video = document.getElementById('sourcevid');
// Replace the source of the video element with the stream from the camera
if (navigator.getUserMedia) {
navigator.getUserMedia('video', successCallback, errorCallback);
// Below is the latest syntax. Using the old syntax for the time being for backwards compatibility.
// navigator.getUserMedia({video: true}, successCallback, errorCallback);
function successCallback(stream) {
video.src = stream;
}
function errorCallback(error) {
console.error('An error occurred: [CODE ' + error.code + ']');
return;
}
} else {
console.log('Native web camera streaming (getUserMedia) is not supported in this browser.');
return;
}
}, false);
I was wondering if I'm missing something or has something changed, because none of the sample code has worked for me so far.
Found out what was happening. For anyone wondering, on Chrome you only have access to the webcam if running from a server. It won't work on just a file.

enable autoplay in ipad

I am working on a project which is in html5. I am testing it in ipad. I have one background audio which play when page load. I made all code to play it, but it not play when it page load. If i click on play button then it play nicely.
Now what i want is to play audio automatically (autoplay). Below is my code,
$(document).ready(function() {
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', 'S6.mp3');
audioElement.controls = true;
audioElement.load();
audioElement.play();
audioElement.play();
$('.play').live('click',function() {
//alert('play'); // alert('asdsad');
audioElement.play();
$("#play").removeClass("play").addClass("pause");
});
$('.pause').live('click',function() {
// alert('pause'); // alert('4545');
audioElement.pause();
//$("#play").html('<a href="#" title="Play" class="play" id="play">');
$("#play").removeClass("pause").addClass("play");
});
$('.soundhover').live('click',function() {
audioElement.volume=0;
$("#off").removeClass("soundhover").addClass("soundoff");
});
$('.soundoff').live('click',function() {
audioElement.volume=1;
$("#off").removeClass("soundoff").addClass("soundhover");
});
});
autoplay doesn't work on iOS:
https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW1