Skip to content

Instantly share code, notes, and snippets.

@italodeandra
Created November 5, 2021 10:54
Show Gist options
  • Save italodeandra/144b7036318467a6c49591d7b4960abd to your computer and use it in GitHub Desktop.
Save italodeandra/144b7036318467a6c49591d7b4960abd to your computer and use it in GitHub Desktop.
Play simultaneously
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<video controls></video>
<script>
(async() => {
const fetching = Promise.all( [
// the video "only" file
fetchData( "video.webm" ),
// the audio "only" file
fetchData( "audio.webm" )
] );
const video_mime = "video/webm; codecs=vp09.00.50.08";
const audio_mime = "audio/webm; codecs=opus";
if(
!MediaSource.isTypeSupported( video_mime ) ||
!MediaSource.isTypeSupported( audio_mime )
) {
throw "unsupported codecs";
}
const source = new MediaSource();
document.querySelector( "video" ).src = URL.createObjectURL( source );
await waitForEvent( source, "sourceopen" );
const video_buffer = source.addSourceBuffer( video_mime );
const audio_buffer = source.addSourceBuffer( audio_mime );
video_buffer.mode = audio_buffer.mode = "sequence";
const [ video_data, audio_data ] = await fetching;
// There is a 'variable' limit as to how much
// data we can append in on go, 10MB seems quite safe
// const chunk_size = 10 * 1024 * 1024;
const chunk_size = 1024;
let i = 0;
while (
i < video_data.length &&
i < audio_data.length
) {
const next_i = i + chunk_size;
const events = Promise.all( [
waitForEvent( video_buffer, "updateend" ),
waitForEvent( audio_buffer, "updateend" )
] );
video_buffer.appendBuffer( video_data.subarray( i, next_i ) );
audio_buffer.appendBuffer( audio_data.subarray( i, next_i ) );
await events;
i = next_i;
}
if (source.readyState == 'open') {
source.endOfStream();
}
})().catch( console.error );
function fetchData( url ) {
return fetch( url, {} )
.then( (resp) => {
return resp.ok && resp.arrayBuffer();
})
// we return an Uint8 view to be able to do a zero-cost subarray()
.then( (buf) => new Uint8Array( buf ) );
}
function waitForEvent( target, event_name ) {
return new Promise( (res) => {
target.addEventListener( event_name, res, { once: true } );
} );
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment