admin管理员组文章数量:1356925
<video id="video1" width="320" height="176" controls="controls">
<source src="mov_bbb.mp4" type="video/mp4">
<source src="mov_bbb.m4a" type="video/m4a">
</video>
<video id="video1" width="320" height="176" controls="controls">
<source src="mov_bbb.mp4" type="video/mp4">
<source src="mov_bbb.m4a" type="video/m4a">
</video>
I have a silent video and want to add his audio file in the video playback
Share Improve this question asked Apr 28, 2019 at 9:09 user11308036user11308036 4- 1 Possible duplicate of Get audio from HTML5 video – Yannick K Commented Apr 28, 2019 at 9:13
-
1
not in a single element, you would need to bine the audio and video. You might be able to have a
<video>
and an<audio>
element and try to keep then in sync, but probably not going to be a great experience – Offbeatmammal Commented Apr 28, 2019 at 9:34 - You should be able to use MediaSource Extensions to get what you need. – Brad Commented Apr 29, 2019 at 1:38
- There's an answer in another stackoverflow post. – Bei Commented Jun 25, 2020 at 12:54
2 Answers
Reset to default 6 +25The MediaSource API allows us to do exactly this.
Note though that for this to work you need to prepare your media assets in a way it's patible with that API. Have a thorough read of this MDN article which explains pretty well how to do so.
Once you have your assets, the remaining is quite straight-forward:
(async() => {
const fetching = Promise.all( [
// the video "only" file
fetchData( "https://dl.dropboxusercontent./s/u9ycdfwy8fig4dl/bbb_video.mp4" ),
// the audio "only" file
fetchData( "https://dl.dropboxusercontent./s/rj4dh32vxwi1iv5/bbb_audio.mp4" )
] );
const video_mime = "video/mp4; codecs=avc1.64000c";
const audio_mime = "audio/mp4; codecs=mp4a.40.2";
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;
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;
}
source.endOfStream();
})().catch( console.error );
function fetchData( url ) {
return fetch( url )
.then( (resp) => 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 } );
} );
}
<video controls></video>
This works for me:
<meta charset="utf-8">
<video controls id="v" height="480" src="file.webm"></video>
<audio id="a" src="file.weba"></audio>
<script>
let v = document.getElementById('v');
let a = document.getElementById('a');
v.onpause = () => a.pause();
v.onplay = () => a.play();
v.onseeked = () => a.currentTime = v.currentTime;
</script>
Controls are on the video element, and audio element will respond to video play, pause and seek. The volume control doesn't work in this example, so you can either add that code, or just use the system volume control.
版权声明:本文标题:javascript - Is there a way to play audio and video separate from each other in the same video - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744027828a2578361.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论