But works fine in Firefox.
Google Chrome version:61.0.3163.100 (Official Build) (64-bit)
Mozilla Firefox version: 56.0.2 (64-bit)
My video is fragmented MP4 streamed over WebSocket to a client html page,where it's being fetched into MSE. The video codec is H264 Main Profile. The video info has been check both in FFPROBE and other inspectors to make sure the data integrity is ok. The following flags are used when muxing the FMP4:
"empty_moov+default_base_moof+frag_keyframe"
I also double checked that the first fragmented is the so called " initializing segment" with size of 24 bytes. As I said, Firefox playback is fine.
Here is the client code (mostly borrowed from here):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MSE Demo</title>
</head>
<body>
<h1>MSE Demo</h1>
<div>
<video id="video1" controls width="80%" autoplay="true"> </video>
</div>
<script type="text/javascript">
(function () {
var mime = 'video/mp4; codecs="avc1.4D401E"';
if (!MediaSource.isTypeSupported(mime)) {
document.querySelector('h1').append(' - Unsuported mime type :(');
return;
}
var buffer;
var websocket;
var buffer_size = 4 * 1024 * 1024;
var buffer_index = 0;
var frag_mp4_buffer = new Uint8Array(buffer_size);
var video = document.querySelector('video');
var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceended', function (e) { console.log('sourceended: ' + mediaSource.readyState); });
mediaSource.addEventListener('sourceclose', function (e) { console.log('sourceclose: ' + mediaSource.readyState); });
mediaSource.addEventListener('error', function (e) { console.log('error: ' + mediaSource.readyState); });
video.src = window.URL.createObjectURL(mediaSource);
video.crossOrigin = 'anonymous';
mediaSource.addEventListener('sourceopen', function (e) {
console.log('sourceopen: ' + mediaSource.readyState);
//doesn't help:
// var playPromise = video.play();
// In browsers that don’t yet support this functionality,
// playPromise won’t be defined.
/*
if (playPromise !== undefined) {
playPromise.then(function () {
// Automatic playback started!
}).catch(function (error) {
// Automatic playback failed.
// Show a UI element to let the user manually start playback.
});
}
*/
buffer = mediaSource.addSourceBuffer(mime);
buffer.addEventListener('updateend', function (e) {
if (video.duration && !video.currentTime) {
video.currentTime = video.duration;
}
});
var websocket = new WebSocket('ws://' + document.location.hostname + ':8080');
websocket.binaryType = 'arraybuffer';
websocket.addEventListener('message', function (e) {
var data = new Uint8Array(e.data);
console.log("got packet! size:" + data.length);
if (data.length) {
if ((buffer_index + data.length) <= buffer_size) {
frag_mp4_buffer.set(data, buffer_index);
buffer_index = buffer_index + data.length;
if (!buffer.updating && mediaSource.readyState == 'open')
{
var appended = frag_mp4_buffer.slice(0, buffer_index);
buffer.appendBuffer(appended);
frag_mp4_buffer.fill(0);
buffer_index = 0;
}
}
}
}, false);
}, false);
})();
</script>
</body>
Another important info,you can see I commented out the video.play()
call. That's actually the only place which throws an error when the app start:
Uncaught (in promise) DOMException: Failed to load because no supported source was found
I tried the following solution from here :
var playPromise = video.play();
if (playPromise !== undefined) {
playPromise.then(function () {
// Automatic playback started!
}).catch(function (error) {
// Automatic playback failed.
$(document).on('click', '#video1', function (e) {
var video = $(this).get(0);
if (video.paused === false) {
video.pause();
} else {
video.play();
}
return false;
});
});
}
But it changed nothing. The video area is white always.