admin管理员组文章数量:1394159
Mobile Safari only lets you play one audio or video stream at a time.
Multiple Simultaneous Audio or Video Streams
Currently, all devices running iOS are limited to playback of a single audio or video stream at any time. Playing more than one video—side by side, partly overlapping, or pletely overlaid—is not currently supported on iOS devices.
If you play a second video the first stops. I need to detect when this occurs so that I can fade back in a play button that appears next to the video, and I'd also like to reset it to the first frame too because leaving it mid animation looks terrible.
Unfortunately the <video>
element doesn't seem to trigger either the 'ended' or 'paused' event when the video is forced to stop like this.
$('video').off('ended pause').on('ended paused', function ()
{
alert('ended'); // don't get here except when the video naturally ends
}
I can't seem to find any other events that correspond to 'forced stop'. (See Apple events for HTMLMediaElement)
Do I have to do this by myself and add a .playing
class to my video and check for it when playing a second video? This is workable if I control every video on the page, but as soon as I stick a YouTube video in there too it bees a lot more plicated. Any better solutions
Mobile Safari only lets you play one audio or video stream at a time.
Multiple Simultaneous Audio or Video Streams
Currently, all devices running iOS are limited to playback of a single audio or video stream at any time. Playing more than one video—side by side, partly overlapping, or pletely overlaid—is not currently supported on iOS devices.
If you play a second video the first stops. I need to detect when this occurs so that I can fade back in a play button that appears next to the video, and I'd also like to reset it to the first frame too because leaving it mid animation looks terrible.
Unfortunately the <video>
element doesn't seem to trigger either the 'ended' or 'paused' event when the video is forced to stop like this.
$('video').off('ended pause').on('ended paused', function ()
{
alert('ended'); // don't get here except when the video naturally ends
}
I can't seem to find any other events that correspond to 'forced stop'. (See Apple events for HTMLMediaElement)
Do I have to do this by myself and add a .playing
class to my video and check for it when playing a second video? This is workable if I control every video on the page, but as soon as I stick a YouTube video in there too it bees a lot more plicated. Any better solutions
-
Have you tried listening to the
webkitbeginfullscreen
andwebkitendfullscreen
events? – nils Commented May 13, 2014 at 22:09 -
webkitendfullscreen
is only called if the video has actually played in full screen, which for me applies for the iPhone. it's on an iPad where the video is playing in-page that I have issues when another video starts.webkitendfullscreen
isn't raised in this case. there just don't seem to be any events on the list that apply – Simon_Weaver Commented May 14, 2014 at 0:53 - to be fair though this seems like a problem even YouTube hasn't fixed. in fact for YouTube it's even worse. the second video never even starts playing and just buffers forever while the first video continues to play (you can see this behavior on any website that hosts two youtube videos - such as failblog.). i just got really frustrated because I couldn't even seem to find discussion of this issue anywhere else – Simon_Weaver Commented May 14, 2014 at 0:55
2 Answers
Reset to default 2 +25This solution feels a bit hackish but if the Safari mobile browser does not throw an event when the video stopped then there are not many options left -
To detect if a video has stopped we can first make sure the script knows when a video is playing, so:
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;
});
This sets a playing flag when video started. Use the ended
event too, to set it to false in case it played to the end or was manually stopped.
Next step is to poll the current time of the video playing to see if it changes. If no change it will indicate the video is not playing (and not caught by the ended event):
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
The check rate should not be higher than 30 fps. This is because the time-stamp would not be changed from what would correspond to the time from one frame to another. To be safe use half the rate as in the example for the highest known frame rate (videos are very rarely above 30 fps in US or 25 fps in Europe). If you know the videos will play at a lower rate the lowest rate should be the value here. It can also be lowered to reduce load in general.
To stop the checking simply call:
clearInterval(timerID); // timerID is in global scope
You may run into a race condition between ended event and the checking (as both creates asynchronous behavior). If it matters depends on how you handle the two situations.
As said, it feels "hackish", it's untested on my part (only theorized as I am unable to set up an entire test environment for it at the moment) but hopefully it will help you get around this limitation of the Safari mobile browser.
If the event doesn't fire only when another video plays, perhaps when we play a video we can simply trigger the ended
event of all the other videos that was playing. To keep track of playing videos we could use a javascript property attached to the video
object. Something like
$("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")
}
})
})
Example (Tested on iPad mini)
The flip side to this is that, this will also apply to desktop browsers which may not be desirable. As for youtube videos embedded in the same page, we might be able to use Youtube's APIs. The APIs use postMessage to municate with each other, so I used the code below to stop the video tags, when a youtube video is playing.
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);
Example
版权声明:本文标题:javascript - Detect when mobile Safari stops playing a video because a second video starts - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744710683a2621110.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论