检测移动Safari何时因为第二个视频开始而停止播放视频

Detect when mobile Safari stops playing a video because a second video starts

本文关键字:视频 开始 播放 第二个 移动 Safari 何时 因为 检测      更新时间:2023-09-26

Mobile Safari一次只能播放一个音频或视频流。

多个同步音频或视频流

目前,所有运行iOS的设备都仅限于播放单个音频或视频流在任何时候。同时播放多个视频侧面,部分重叠,或完全重叠-不是当前

如果播放第二个视频,第一个停止。我需要检测这种情况何时发生,这样我就可以在视频旁边的播放按钮中退色,我还想将其重置为第一帧,因为在动画中留下它看起来很糟糕。

不幸的是,当视频像这样被迫停止时,<video>元素似乎不会触发'ended'或'paused'事件。

 $('video').off('ended pause').on('ended paused', function ()
 {
     alert('ended');   // don't get here except when the video naturally ends
 }

我似乎找不到任何其他与'强制停止'相对应的事件。(参见Apple events的HTMLMediaElement)

我必须自己这样做,并添加一个.playing类到我的视频,并检查它播放第二个视频时?如果我控制页面上的每个视频,这是可行的,但是一旦我在那里粘贴一个YouTube视频,它就变得复杂得多。有更好的解决方案吗

这个解决方案感觉有点粗糙,但如果Safari移动浏览器在视频停止时不抛出事件,那么就没有多少选择了-

要检测视频是否已经停止,我们可以首先确保脚本知道视频何时正在播放,所以:

var isPlaying1 = false,
    isPlaying2 = false, // if more videos an array is better to use, or reuse
    lastTime1 = 0,
    lastTime2 = 0;      // etc.
$('video1').on('playing', function() {
    isPlaying1 = true;
});
$('video1').on('ended', function() {
    isPlaying1 = false;
});

设置视频开始时的播放标志。使用ended事件也,设置它为假,以防它播放到结束或手动停止。

下一步是轮询视频播放的当前时间,看看它是否改变。如果没有更改,则表示视频未播放(并且未被结束事件捕获):

function check() {
    if (isPlaying1) {
        var video = $('video1')[0];
        if (video.currentTime === lastTime1) {
            // video has stopped
            isPlaying1 = false;
            video.currentTime = lastTime1 = 0; //reset time
        }
        else {
            lastTime1 = video.currentTime;
        }
    }
}
var timerID = setInterval(check, 1000/15);  // start check

检查速率不能超过30fps。这是因为时间戳不会从对应于从一个帧到另一个帧的时间改变。为了安全起见,使用例子中已知最高帧率的一半速率(在美国视频很少超过30fps,在欧洲视频很少超过25fps)。如果您知道视频将以较低的速率播放,则最低速率应该是这里的值。一般情况下也可降低,以减少负荷。

停止检查只需调用:

clearInterval(timerID); // timerID is in global scope

您可能会在结束事件和检查之间遇到竞争条件(因为两者都创建异步行为)。是否重要取决于你如何处理这两种情况。

如前所述,它感觉有点"黑客",我还没有测试过(只是理论上的,因为我目前无法为它设置一个完整的测试环境),但希望它能帮助你绕过Safari移动浏览器的这个限制。

如果事件不触发只有当另一个视频播放,也许当我们播放一个视频,我们可以简单地触发所有其他视频正在播放的ended事件。为了跟踪播放视频,我们可以使用附加到video对象的javascript属性。就像

$("video").on("ended",function(){
    this.playing=false
    this.currentTime=0
    console.log(this.src+" has ended")
})

$("video").on("play",function(){
    var that=this
    this.playing=true //video that is playing is "playing"
    $("video").each(function(i,o){
        if(o.playing && !$(o).is($(that)) ){ //for all the other "playing" video
          o.pause()
          $(o).trigger("ended")
        }
    })
})

示例(在iPad mini上测试)

另一方面,这也将适用于桌面浏览器,这可能是不可取的。至于嵌入同一页面的youtube视频,我们或许可以使用youtube的api。api使用postMessage相互通信,所以我使用下面的代码来停止视频标签,当一个youtube视频正在播放。

window.addEventListener('message',function(event) {
    //probably should check origin
    var data=JSON.parse(event.data)
    if(data.info && 
     ( data.info.playerState == 1   //buffering
       || data.info.playerState == 3 )){ //or playing
        $("video").each(function (i, o) {
            if(o.playing){
              o.pause()
              $(o).trigger("ended")
            }
        })
    }
},false);
示例