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);
            }
andrew
  • 9,313
  • 7
  • 30
  • 61
  • 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. – chrismauck Apr 26 '14 at 21:17
  • 2
    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 down – andrew Apr 26 '14 at 22:07

2 Answers2

29

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.

drowzy
  • 657
  • 6
  • 9
  • 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! – Anibal Itriago Mar 14 '18 at 18:55
  • 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 help – cars Apr 17 '18 at 23:20
  • 1
    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 ? – Sukhwinder Sodhi Aug 09 '19 at 13:06
  • 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? – Austin Burk Jan 05 '20 at 08:45
  • 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 : https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API/Transcoding_assets_for_MSE – thomas Jan 10 '20 at 13:04
-2

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

  • 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... – VC.One Jun 23 '22 at 12:59