Unable to get MediaSource working with mp4 format in chrome
Asked Answered
E

2

13

Based on the example here

I downloaded the webm file and encoded as an mp4 file which will play locally but I'm unable to use it as a media source.

MP4Box reports the codec to be avc1.64000d,mp4a.40.2 but adding it to the source buffer did not help.

Here is a demo of the problem (I don't expect it to work in firefox as Media Source Extensions are not supported yet)

and here is the code I'm testing with:

 var FILE,CODEC,mediaSource;
            var NUM_CHUNKS = 5;
            var video = document.querySelector('video');
            window.MediaSource = window.MediaSource || window.WebKitMediaSource;
            if (!!!window.MediaSource) {
                alert('MediaSource API is not available');
            }
            function callback() {
                var sourceBuffer = mediaSource.addSourceBuffer(CODEC);
                GET(FILE, function(uInt8Array) {
                    var file = new Blob([uInt8Array], {type: 'video/mp4'});
                    var chunkSize = Math.ceil(file.size / NUM_CHUNKS);
                    var i = 0;
                    (function readChunk_(i) {
                        var reader = new FileReader();
                        reader.onload = function(e) {
                            sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
                            if (i == NUM_CHUNKS - 1) {
                                mediaSource.endOfStream();
                            } else {
                                if (video.paused) {
                                    video.play();
                                }
                                readChunk_(++i);
                            }
                        };
                        var startByte = chunkSize * i;
                        var chunk = file.slice(startByte, startByte + chunkSize);
                        reader.readAsArrayBuffer(chunk);
                    })(i);
                });
            }
            function GET(url, callback) {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', url, true);
                xhr.responseType = 'arraybuffer';
                xhr.send();
                xhr.onload = function(e) {
                    if (xhr.status != 200) {
                        alert("Unexpected status code " + xhr.status + " for " + url);
                        return false;
                    }
                    callback(new Uint8Array(xhr.response));
                };
            }
            function start(type) {
                if (type == 'webm') {
                    FILE = 'test.webm';
                    CODEC = 'video/webm; codecs="vorbis,vp8"';
                }
                if (type == 'mp4') {
                    FILE = 'test.mp4';
                    CODEC = 'video/mp4; codecs="avc1.64000d,mp4a.40.2"';
                }
                mediaSource = new MediaSource();
                video.src = window.URL.createObjectURL(mediaSource);
                mediaSource.addEventListener('sourceopen', callback, false);
                mediaSource.addEventListener('webkitsourceopen', callback, false);
                mediaSource.addEventListener('webkitsourceended', function(e) {
                }, false);
            }
Engelhardt answered 10/4, 2014 at 18:56 Comment(2)
Looking into this now. Is there a reason you need this to work with MP4 since it already works with webm? Is it to make it cross browser compatible? Sorry, just want to better understand the need.Presentday
Its because I want to stream from Ipcameras that produce h.264, I could transcode to webm but it would be really nice to keep the cpu time downEngelhardt
U
30

The problem is your file. Media source extensions requires fragmented MP4 with the moov(movie header box) at the beginning of the file, in your case it is placed last.

Also there need to be a moof (Movie fragment box) preceding the mdat (media data box). MP4Box is capable of generating DASH compliant fragmented mp4, but I would recommend that you use their latest nightly releases.

MP4Box -dash 1000 -rap -frag-rap test.mp4

This will generate the a correctly structured fragmented mp4 file with the moov placed in the beginning of the file. Each fragment will be 1 second, starting with a key frame.

Undershirt answered 29/4, 2014 at 8:24 Comment(5)
You rock!!!!! Spent a lot of time trying to get it working and with your answers you helped me not to trash all the project and leave programming life back! Thanks!Triangular
I have a .mp4 video file which contains video and audio only. And I want the video and the audio separated, and both of them created into fragmented mp4 to be played through Media Source Extensions. How will I describe this is MP4Box. Please helpTerryl
I recorded a video from iphone and ran same command on it but i am still getting error Failed to execute 'endOfStream' on 'MediaSource': The MediaSource's readyState is not 'open Can anyone help ?Automatize
MP4Box is extremely inflexible for automated purposes and doesn't do basic things like reading/writing from/to stdin/stdout. Any way to get ffmpeg to generate the dashinit file like this?Euplastic
The ffmpeg command to fix both moov and moof issues is the following : ffmpeg -i file.mp4 -c copy -movflags frag_keyframe+empty_moov+default_base_moof output.mp4 This is better documented in the mozilla MSE documentation here : developer.mozilla.org/en-US/docs/Web/API/…Ambala
L
-2

Your codec is wrong too, would be 'video/mp4; codecs="avc1.4D4001,mp4a.40.2"'

Ludewig answered 20/10, 2020 at 12:41 Comment(1)
I think you got down-vote because (1) This reads like a comment about problem, not as solution to the problem... The answer box is for solutions only. (2) You did not prove the codec is avc1.4D4001. Did you check the bytes of the MP4 file for 0x4D4001 at the avcConfig section? Otherwise it seems you are giving wrong information as Answer...Fuhrman

© 2022 - 2024 — McMap. All rights reserved.