Video recording with Edge using HTML5 - html

I am trying to record video using HTML5 API. I want this solution to be cross platform and it should atleast work on Chrome, Firefox and Edge browser. I tried with following code
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then((mediaStream) => {
const video = document.querySelector('video');
const url = window.URL.createObjectURL(mediaStream);
video.src = url;
});
Above code displays video in Chrome and Edge. When I try to capture bytes using MediaRecorder API, it only works in Chrome and not in Edge. Please suggest what can be done.
const recorder = new MediaRecorder(mediaStream);
recorder.ondataavailable = onDataAvailable
...
function onDataAvailable(d){
//d.data is populated in Chrome but not in Edge.
}
Please suggest, how can I capture bytes so that it can be saved on server.
I tried MediaStreamRecorder but that too didn't work with Edge.
Update : I found few approaches which indicate use of Canvas as an option to render frames and capture the bytes. Then use requestAnimationFrame to continue capturing video. While this might work, I am still open to any other better suggestions.

The MediaRecorder API seem to be only implemented in FireFox & Chrome
https://caniuse.com/#search=MediaRecorder
I'd always check caniuse.com for browser support for new APIs!

Related

MediaRecorder captured on Chrome not playable on Mobile or Safari

Goal: use MediaRecorder (or else) api to produce video files that are viewable cross platforms.
Fail: current api falls back to container/codec on google chrome which is only viewable on chrome and advanced desktop media players but not on Safari or mobile devices.
! Same code when running on safari generates a working video file on all platforms.
const mimeType = 'video/webm;codecs=H264'
rec = new MediaRecorder(stream.current, { mimeType })
rec.ondataavailable = e => blobs.push(e.data)
rec.onstop = async () => {
saveToFile(new Blob(blobs, { type: mimeType }))
}
Tried all different combinations of containers and codecs.
also tried to override the mimeType of the Blob with MP4 file container.
No success what so ever.
also tried:
https://github.com/streamproc/MediaStreamRecorder
https://github.com/muaz-khan/RecordRTC
Same issues. iI seems like chrome's container/codec combinations always fall back to a format that is only viewable out of the box on chrome or a powerful desktop video player like vlc.
The only cross platform working video for me is the one taken from safari browser and is the 5th from left in the picture above.
What is the correct container/codac to be used in MediaCapture api to make the output file playable cross platform.
Edit -
We ended up building a transcoding pipeline with AWS ElasticTranscoder, which takes the uploaded video and transcodes it with a general preset that is playable on all platforms thus creating a converted video file.
unfortunately the bounty I offered expired, but if someone answers the original question I would gladly reward him with the bounty again.
I think your problem may be in the first line:
const mimeType = 'video/webm;codecs=H264'
The container you are using is webm, which typically uses codecs VP8, VP9. H264 is a codec used in the mp4 container.
Chrome supports webm. Safari does not (and all iOS browsers are based on Safari - hence your mobile issue).
You say that run on Safari, this outputs a playable video. use ffprobe to see what codec/containers are outputted on Safari - I am guessing that there is a change in container/codec.
Since your video is h264, you must simply change the container to mp4, and it will play everywhere. This is a 'copy' from one container to the other, not a transcoding, but you'll still need ffmpeg :)
Here's a post that might help: Recording cross-platform (H.264?) videos using WebRTC MediaRecorder

MediaRecorder does not produce a valid WebM file

MediaRecorder.isTypeSupported() returns true for 'video/webm', 'video/webm;codecs=avc1', and 'video/webm;codecs=vp9'.
However, only mimeType='video/webm;codecs=vp9' results in a valid webm file ('video/webm;codecs=vp9,opus').
Setting mimeType to either 'video/webm' and 'video/webm;codecs=avc1' results in 'video/x-matroska;codecs=avc1,opus' file, which is not a valid webm video.
Is this a MediaRecorder bug, Chrome bug or am I missing something?\
Software: Chrome 85, MacOS 10.15. I have not tried this on Windows or Linux.
Reproduction:
const wantMimeType = 'video/webm;codecs=h264,opus';
if (MediaRecorder.isTypeSupported(wantMimeType)) {
let mediaRecorder = new MediaRecorder(stream, {
mimeType: wantMimeType,
});
// ...drive the recorder
mediaRecorder.onstop = (event) => {
try {
// returns 'video/x-matroska;codecs=avc1,opus' in Chrome,
// and the binary file content also says Matroska instead of WebM
let mimetype = mediaRecorder.mimeType;
if (!mimeType.startsWith('video/webm')) {
throw new Error(`We requested "${wantMimeType},
but the browser gave us "${mediaRecorder.mimeType}"`);
}
let blob = new Blob(chunks, { type: mimeType });
// ...convert to data: URL
// ...play it in <video src="data:..."> // won't work, if Matroska
} catch (ex) {
alert(ex);
}
};
}
Observations:
Chrome responds true to isTypeSupported('video/webm;codecs=h264,opus'), but Chrome actually does not support this combination, i.e. the response is factually incorrect and defeats the entire purpose of isTypeSupported().
Chrome ignores the mimetype that we pass in the MediaRecorder constructor, and instead returns video/x-matroska;codecs=avc1,opus. Which then doesn't work, because <video> won't play the Matroska mimetype.
2 solutions:
Hacky: After recording, just change the mimetype back to video/webm;codecs=h264,opus. The file content will still say "Matroska", but <video> on Chrome will play it. It's a bad solution, because we're passing in the wrong mimetype, it doesn't match the content. Other software - or Chrome in later versions - might break over it.
Proper: Don't use H.264, but VP9 or VP8. Chrome supports both, and Firefox supports VP8, and they work properly. As a bonus, they are open, while H.264 is riddled with software patents. Depending on the hardware encoder implementation, VP8/9 also may give better image quality results.
However, only mimeType='video/webm;codecs=vp9' results in a valid webm file.
Is this a MediaRecorder bug, Chrome bug or am I missing something?
WebM is the correct a/v media container for the VP8 and VP9 video codecs.
AVC1 video codec belongs into an MPEG container (.mp4, .m4v).
This video codec can also be contained inside an MKV media file (Matroska .mkv).

HTML5 record moderate video quality for upload to be playable by Safari

I am creating a web-based mobile app where it should be possible to upload video-recordings.
There are two ways to achieve this:
Use input:
<input type="file" name="video" accept="video/*" capture></input>
Use RTC MediaRecorder:
var recordedBlobs = [];
function handleDataAvailable(event) {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
var options = {
mimeType: 'video/webm',
audioBitsPerSecond : 128000,
videoBitsPerSecond : 2500000
}
mediaRecorder = new MediaRecorder(window.stream, options);
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10);
While the first option always works the main problem is that it uses the build-in mobile camera application leaving us no control over quality, which again leads to potentially very large files (especially on android)
Second version gives us full control over quality and lets os create moderate file sizes that are size-wise acceptable as content in the application. iOS/Safari does not support this feature yet, but this is ok since iPhones record small files by default when started from the browser. So I can activate option 1 when the user-agent is iOS.
Now the problems:
First option would be fine if I could:
Control the video recording quality of the mobile application
Post-elaborate the recording to change the resolution before upload
The problem with option 2 is that only the .webm container type is supported, and Safari does not support this type.
So I'm a little stuck - right now it seems like my only option is to post-convert the incoming .webm files to .mp4 on the server as they are uploaded. But it seems to be a very CPU costly process on the server.
Any good ideas?
You can record as H.264 into a webm container. This is supported by Chrome.
var options = {mimeType: 'video/webm;codecs=h264'};
media_recorder = new MediaRecorder(stream, options);
Although it is an usual combination of video format and container - it is valid.
Now you could change H.264/webm into H.264/mp4 without transcoding the video stream using ffmepg (-vcodec copy).
You could also try re-wrapping from webm to mp4 client side in JavaScript using ffmpeg.js.

Playing 360 videos in Chromium and Mozilla nightly WebVR versions

I'm trying to integrate 360 videos in WebGL, using the HTML5 video player and a flat video it does work, but when I use this video by example :
http://video.airpano.com/Video-Porto/portu_fin3_ir2048_5mbs.mp4
all I get is a black screen.
I use the chromium version 44.0.2383.0 for WebVR (http://blog.tojicode.com/2014/07/bringing-vr-to-chrome.html).
Does anyone experimented this problem before, or managed to play 360 videos ? thank you for your help !
EDIT
Here's the function I use to stream a videotexture :
that.loadVideoTexture = function(){
// create the video element
this.video = document.createElement("video");
this.video.src = "http://video.airpano.com/Video-Porto/portu_fin3_ir2048_5mbs.mp4";
this.video.crossOrigin = "anonymous";
this.video.crossorigin = "anonymous";
this.video.load(); // must call after setting/changing source
this.videoTexture = new THREE.VideoTexture(this.video);
this.videoTexture.minFilter = THREE.LinearFilter;
this.videoTexture.magFilter = THREE.LinearFilter;
this.mesh.material.materials[1] = new THREE.MeshPhongMaterial( { map: this.videoTexture, color:"white", side:THREE.DoubleSide } );
}
But apparently it would be coming from the non support of .mp4 by Chrome, so I guess the code isn't involved in this problem.
Since Chromium is an open-source distribution, it does not include support for proprietary, licensed formats like MP4 (H.264). You'll either need to convert the video to WebM or use WebVR in Firefox Nightly instead.

Read webm video from blob on firefox

I'm testing WebRTC API. More precisely the webcam part.
So I read the W3C draft and used it in firefox to record myself from a webpage. It works (not as good as expected, but it does). I mean that I can download a video formated as webm that is readable by my computer.
I want to previsualize my video before sending it to the server. So I madethis code:
var url = URL.createObjectURL(e.data);
video.innerHTML = '<source src="' + url + '" type="video/webm"></source>';
video.play();
This does'nt work at all. I got just a blank element on my webpage...
Any suggestion to make it work ?
The problem was an issue of Firefox. With e.data we get a blob but we have to redefine a new blob to make it work:
var new_blob = new Blob([e.data], { type: e.data.type });
Notice that for now (2014-09-30) firefox does not support officialy the video encoding and the specification is in draft that is not validated by the W3C.
the proble is I do not understand the what is the object you get in e.data, also you can check if the mime is correct console.log(e.data);;console.log(e.data.type); , what are the output of these,
also have you tried this, firefox webm capture, they show preview of the video.