Created
November 5, 2021 10:54
-
-
Save italodeandra/144b7036318467a6c49591d7b4960abd to your computer and use it in GitHub Desktop.
Play simultaneously
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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