将HTML5 <video>与<audio>播放同步

24

我有来自一个源的音轨,且已经将其静音,现在我想使用 <audio> 元素在其上播放背景音乐。这些音轨包含一些时间关键元素。

在HTML5/Javascript中,如何同步这两个不同的媒体播放器?如果音频播放非常敏感于时间 - 偶尔失去视频帧并不重要,会有哪些选项可供选择,可以提供主时钟呢?


2
目前我是通过设置视频.currentTime来实现的,该值是从音轨时钟获取的。https://github.com/miohtama/slideshow9000/blob/master/slideshow/static/video.js#L48 - Mikko Ohtamaa
6个回答

21

Mikko Ohtamaa在评论中提供了一个解决方案,我认为这是最好的选项-它不需要框架,也不需要您编辑视频文件。

基本上,在“取消静音”时从视频元素中获取当前时间,并将该时间应用于音频元素。一些代码可能看起来像这样:

function unmute() {
  var vid = document.getElementById("video");
  var aud = document.getElementById("audio");

  aud.currentTime = vid.currentTime;
  aud.play();

}

谢谢 - 我没有注意到这个问题还没有被我关闭 :) - Mikko Ohtamaa
这里唯一的问题是视频可能尚未播放,此时 vid.currentTime 将为 null。 - clayRay

5
这是一个使用Popcorn.js实现的简单解决方案,与此文章灵感来源一样。请点击这里查看。

$(function(){
var medias = {
    audio: Popcorn("#narration"),
    video: Popcorn("#video")
  },
  loadCount = 0,
  events = "play pause timeupdate seeking volumechange".split(/\s+/g); 


// iterate both media sources
Popcorn.forEach(medias, function(media, type) {

  // when each is ready... 
  media.on("canplayall", function() {

    // trigger a custom "sync" event
    this.emit("sync");

    // Listen for the custom sync event...    
  }).on("sync", function() {

    // Once both items are loaded, sync events
    if (++loadCount == 2) {
      // Uncomment this line to silence the video
      //medias.video.mute();

      // Iterate all events and trigger them on the video 
      // whenever they occur on the audio
      events.forEach(function(event) {

        medias.video.on(event, function() {

          // Avoid overkill events, trigger timeupdate manually
          if (event === "timeupdate") {

            if (!this.media.paused) {
              return;
            }
            medias.audio.emit("timeupdate");

            return;
          }

          if (event === "seeking") {
              medias.audio.currentTime(this.currentTime());
          }
          
          if (event === "volumechange") {  
           if(this.muted()) { 
            medias.audio.mute(); 
           } else {
            medias.audio.unmute(); 
           } 
           
           medias.audio.volume(this.volume());
          }

          if (event === "play" || event === "pause") {
            medias.audio[event]();
          }
        });
      });
    }
  });
});
});
   <script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
   <script type="text/javascript" src="https://static.bocoup.com/js/popcorn.min.js"></script>
     
<audio id="narration">
 <source src="https://videos.cdn.mozilla.net/uploads/webmademovies/popcorn101/popcorn101.ogg">
</audio>
<video id="video" controls="controls">  
 <source src="https://videos.cdn.mozilla.net/uploads/webmademovies/popcorntest.mp4">
</video>


有没有可能双向同步,我的意思是音频的更改反映在视频中,视频的更改反映在音频中? - shrestha2lt8
当视频因加载数据而暂停时,音频不会停止。 - Vahid

1
用一个非常简单的技巧就能轻松解决;)
<video id="myvideo" controls muted loop>
    <source src="sample_video_no_sound.mp4" type="video/mp4"/>
    <audio id="myaudio">
        <source src="sound.mp3" type="audio/mpeg"/>
    </audio>
</video>

<script>
    var myvideo = document.getElementById("myvideo");
    var myaudio = document.getElementById("myaudio");

    var change_time_state = true;

    myvideo.onplay = function(){
        myaudio.play();
        if(change_time_state){
            myaudio.currentTime = myvideo.currentTime;
            change_time_state = false;
        }
    }

    myvideo.onpause = function(){
        myaudio.pause();
        change_time_state = true;
    }
</script>

如果有人决定跳过视频的一分钟,会怎么样呢? - undefined

0
尝试使用VideoJS。在页面加载并准备好时,当视频播放开始时,您可以触发一个函数,该函数将单独播放页面中包含的音乐。

http://videojs.com/


0

通过将音乐包含在视频文件中,也可以实现相同的效果。HTML5视频播放器控件将具有静音功能。


正如我所说,我需要特别避免这种情况:音乐是动态生成的。 - Mikko Ohtamaa

0

目前没有可靠的解决方案。唯一支持多个流同步的HTML5功能是mediaGroup,但它已被Chrome取消支持并被W3C弃用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接