Reputation: 3233
I tried to work with MediaSource
, but it works only with the video file from the MDN example.
Although MediaSource.isTypeSupported(mimeCodec)
returns true
for videos which I tested, the videos are not showed anyway.
Here is the videos I used list with comments:
// Only with this video it works
var assetURL = 'https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4';
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; // ./mp4info frag_bunny.mp4 | grep Codec
// It does not work
var assetURL = 'https://giant.gfycat.com/HandmadeMajesticIndianjackal.mp4';
var mimeCodec = 'video/mp4; codecs="avc1.64002A, mp4a.40.2"';
// The previous video, but encoded by Youtube. The same codecs, but reduced size. (it does not work too)
var assetURL = 'https://giant.gfycat.com/NaturalBraveHoneycreeper.mp4';
var mimeCodec = 'video/mp4; codecs="avc1.64002A, mp4a.40.2"';
// Another random not working examples:
// var assetURL = 'https://giant.gfycat.com/DigitalPolishedDassie.mp4';
// var mimeCodec = 'video/mp4; codecs="avc1.640033"';
// var assetURL = 'https://giant.gfycat.com/AncientAllAmericanavocet.mp4';
// var mimeCodec = 'video/mp4; codecs="avc1.42C01F"';
The short example. It works fine only with the first video.
(Check the full demo below.)
let video = document.querySelector("video");
let mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener("sourceopen", sourceOpen);
async function sourceOpen(_) {
const mediaSource = this;
const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
const resp = await fetch(assetURL);
const reader = resp.body.getReader();
let updated = Promise.resolve();
while (true) {
const {done, value} = await reader.read();
await updated;
if (done) {
break;
}
sourceBuffer.appendBuffer(value);
updated = sourceBufferUpdated(sourceBuffer);
}
reader.releaseLock();
mediaSource.endOfStream();
await video.play();
};
function sourceBufferUpdated(sourceBuffer) {
return new Promise(resolve => {
if (sourceBuffer.updating) {
sourceBuffer.onupdate = resolve;
} else {
resolve();
}
});
}
The full "working" demo. Click the "next" button.
const entries = [
{
url: 'https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4',
// ./mp4info frag_bunny.mp4 | grep Codec
mimeCodec: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
}, {
url: 'https://giant.gfycat.com/HandmadeMajesticIndianjackal.mp4',
mimeCodec: 'video/mp4; codecs="avc1.64002A, mp4a.40.2"'
}, {
url: 'https://giant.gfycat.com/NaturalBraveHoneycreeper.mp4',
mimeCodec: 'video/mp4; codecs="avc1.64002A, mp4a.40.2"'
}, {
url: 'https://giant.gfycat.com/DigitalPolishedDassie.mp4',
mimeCodec: 'video/mp4; codecs="avc1.640033"'
}, {
url: 'https://giant.gfycat.com/AncientAllAmericanavocet.mp4',
mimeCodec: 'video/mp4; codecs="avc1.42C01F"'
}
];
let index = 0;
main(entries[index]);
function main({url, mimeCodec}) {
document.querySelector("#url").textContent = url;
document.querySelector("#mimeCodec").textContent = mimeCodec;
if (!MediaSource.isTypeSupported(mimeCodec)) {
document.querySelector("#mimeCodec").textContent += " (mimeCodec is not supported)";
return;
}
const video = document.querySelector("video");
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener("sourceopen", sourceOpenHandler);
async function sourceOpenHandler() {
const mediaSource = this;
const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
const resp = await fetch(url);
const reader = resp.body.getReader();
let updated = Promise.resolve();
while (true) {
const {done, value} = await reader.read();
await updated;
if (done) {
break;
}
sourceBuffer.appendBuffer(value);
updated = sourceBufferUpdated(sourceBuffer);
}
reader.releaseLock();
mediaSource.endOfStream();
await video.play();
};
}
function sourceBufferUpdated(sourceBuffer) {
return new Promise(resolve => {
if (sourceBuffer.updating) {
sourceBuffer.onupdate = resolve;
} else {
resolve();
}
});
}
document.querySelector("body").addEventListener("click", event => {
if (event.target.id === "next") {
++index;
} else if (event.target.id === "pre") {
--index;
} else {
return;
}
const {length} = entries;
const possition = (length + (index % length)) % length;
main(entries[possition]);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>MediaSourse Demo</title>
</head>
<body>
<button id="pre">pre</button>
<button id="next">next</button>
<div id="mimeCodec"></div>
<div id="url"></div>
<video controls="" src="" crossorigin="anonymous" muted></video>
<script src="script.js"></script>
</body>
</html>
Upvotes: 1
Views: 1339