Skip to content Skip to sidebar Skip to footer

Playing One Of Multiple Audio Tracks In Sync With A Video

I'm trying to play a video in a web browser, the original video comes with two or more audio streams, each in a different language. I want to give the user the option to switch whi

Solution 1:

The best in your case is probably to use the Media Source Extension (MSE) API. This will allow you to switch only the audio source while keeping playing the original video. Since we will replace the whole audio SourceBuffer's content with the other audio source, we won't have sync issues, for the player, it will be just as if there was a single audio source.

(async() => {
  const vid = document.querySelector( "video" );
  const check = document.querySelector( "input" );
  // video track as ArrayBufferconst bufvid = awaitgetFileBuffer( "525d5ltprednwh1/test.webm" );
  // audio track oneconst buf300 = awaitgetFileBuffer( "p56kvhwku7pdzd9/beep300hz.webm" );
  // audio track twoconst buf800 = awaitgetFileBuffer( "me3y69ekxyxabhi/beep800hz.webm" );
  
  const source = newMediaSource();
  // load our MediaSource into the video
  vid.src = URL.createObjectURL( source );
  // when the MediaSource becomes openawaitwaitForEvent( source, "sourceopen" );

  // append video trackconst vid_buffer = source.addSourceBuffer( "video/webm;codecs=vp8" );
  vid_buffer.appendBuffer( bufvid );

  // append one of the audio tracksconst aud_buffer =  source.addSourceBuffer( "audio/webm;codecs=opus" );
  aud_buffer.appendBuffer( check.checked ? buf300 : buf800 );
  // wait for both SourceBuffers to be readyawaitPromise.all( [
    waitForEvent( aud_buffer, "updateend" ),
    waitForEvent( vid_buffer, "updateend" )
  ] );
  // Tell the UI the stream is ended (so that 'ended' can fire)
  source.endOfStream();
  
  check.onchange = async (evt) => {
    // remove all the data we had in the Audio track's buffer
    aud_buffer.remove( 0, source.duration );
    // it is async, so we need to wait it's doneawaitwaitForEvent( aud_buffer, "updateend" );
    // no we append the data of the other track
    aud_buffer.appendBuffer( check.checked ? buf300 : buf800 );
    // also asyncawaitwaitForEvent( aud_buffer, "updateend" );
    // for ended to fire
    source.endOfStream();
  };

})();

// helpersfunctiongetFileBuffer( filename ) {
  returnfetch( "https://dl.dropboxusercontent.com/s/" + filename )
    .then( (resp) => resp.arrayBuffer() );
}
functionwaitForEvent( target, event ) {
  returnnewPromise( res => {
    target.addEventListener( event, res, { once: true } );
  } );
}
video { max-width: 100%; max-height: 100% }
<label>Use 300Hz audio track instead of 800Hz <inputtype="checkbox"></label><br><videocontrols></video>

Post a Comment for "Playing One Of Multiple Audio Tracks In Sync With A Video"