【问题标题】:Playing HTML5 Video on IPad and seeking在 iPad 上播放 HTML5 视频并寻找
【发布时间】:2012-06-30 09:52:04
【问题描述】:

非常奇怪的错误,我似乎无法弄清楚。

当用户点击播放时,我试图让 HTML5 视频从某个位置播放。我试图让它在视频开始播放时正确搜索。

在我的游戏活动中,我做this.currentTime = X

在浏览器上它工作正常。但是在 iPad 上,当我播放视频时,视频不会找到正确的位置(它从零开始)。

更奇怪的是,如果我在 setTimeout 中调用 this.currentTime = X,比如说 1 秒,它可以在 iPad 上运行(有时)。

【问题讨论】:

    标签: javascript ios ipad html video


    【解决方案1】:

    在 iOS 上,视频加载 at play time(参见第 2 项),而不是在页面加载时加载。我的猜测是你运行this.currentTime = X时没有加载视频,所以没有效果。这也解释了为什么延迟操作有时可以解决问题:有时它会在一秒钟后加载,有时不会。

    我没有要测试的 iOS 设备,但我建议将 loadeddata 侦听器绑定到视频,以便您的 currentTime 操作仅在视频开始加载后发生:

    // within the play event handler...
    if(!isIOSDevice) {
         this.currentTime = X;
    } else {
        function trackTo(evt) {
            evt.target.currentTime = X;
            evt.target.removeEventListener("loadeddata", trackTo)
        });
        this.addEventListener("loadeddata", trackTo);
    }
    

    您需要根据当前访问是否来自 iOS 设备,在代码中的其他位置设置 isIOSDevice

    【讨论】:

    • 哇。它确实有效。最终使用了爆米花库(对于那些也使用爆米花 js 的人,请侦听 loaddata 事件)
    • @K2xL 太好了,很高兴你修复了它!我按照您的建议更新了我的答案以使用loadeddata。 (事实证明loadeddata 是一个标准的 HTML5 事件,而不仅仅是一个自定义的 Popcorn 事件。)
    • 好的,我真的很讨厌这么说@apsillers,但实际上它没有用。我认为确实如此(我实际上是在 trackTo 的第一行发出警报,以确保事件在 ipad 上触发。当我点击“OK”时,视频可能处于缓冲状态,所以它起作用了。我要去继续尝试您的解决方案的变体。会让您知道
    • 您可以尝试developer.mozilla.org/en/DOM/Media_events 上列出的其他一些活动。 canplaytimeupdate 似乎是可能的选择。
    【解决方案2】:

    虽然这个问题已经很老了,但问题仍然悬而未决。我发现了一个适用于 iOS 5 和 6(iOS3+4 未测试)的多个经过测试的 iPad (1+2+3) 的解决方案:

    基本上,您首先必须等待初始 playing 事件,然后为 canplaythrough 添加一次性活页夹,然后为 progress 添加 - 只有这样您才能真正更改 currentTime 值。在此之前的任何尝试都会失败!

    视频必须首先开始播放,这使得视频元素顶部的黑色层有点方便。不幸的是,视频中的声音无法通过 JavaScript 停用 --> 不是完美的用户体验

    // https://github.com/JoernBerkefeld/iOSvideoSeekOnLoad / MIT License 
    // requires jQuery 1.8+
    // seekToInitially (float) : video-time in seconds
    function loadingSeek(seekToInitially, callback) {
        if("undefined"==typeof callback) {
            callback = function() {};
        }
        var video = $("video"),
            video0 = video[0],
            isiOS = navigator.userAgent.match(/(iPad|iPhone|iPod)/) !== null,
            test;
        if(isiOS) { // get the iOS Version
            test =navigator.userAgent.match("OS ([0-9]{1})_([0-9]{1})");
            // you could add a loading spinner and a black layer onPlay HERE to hide the video as it starts at 0:00 before seeking
            // don't add it before or ppl will not click on the play button, thinking the player still needs to load
        }
        video.one("playing",function() { 
            if(seekToInitially > 0) {
                //log("seekToInitially: "+seekToInitially);
                if(isiOS) {
                    // iOS devices fire an error if currentTime is set before the video started playing
                    // this will only set the time on the first timeupdate after canplaythrough... everything else fails
                    video.one("canplaythrough",function() { 
                        video.one("progress",function() { 
                            video0.currentTime = seekToInitially;
                            video.one("seeked",function() {
                                // hide the loading spinner and the black layer HERE if you added one before
    
                                // optionally execute a callback function once seeking is done
                                callback();
                            });
                        });
                    });
                } else {
                    // seek directly after play was executed for all other devices
                    video0.currentTime = seekToInitially; 
    
                    // optionally execute a callback function once seeking is done
                    callback();
                }
            } else {
                // seek not necessary
    
                // optionally execute a callback function once seeking is done
                callback();
            }
        });
    }
    

    整个东西可以从my GitHub repo下载

    【讨论】:

      【解决方案3】:

      apsillers 是对的。一旦视频开始播放,Quicktime 播放器就会出现,并且在触发第一个“进度”事件之前,视频将无法搜索。如果您在此之前尝试搜索,您将收到无效状态错误。这是我的代码:

      cueVideo = function (video, pos) {
          try {
              video.currentTime = pos;
      
          // Mobile Safari's quicktime player will error if this doesn't work.
          } catch(error) {
              if (error.code === 11) { // Invalid State Error
      
                  // once 'progress' happens, the video will be seekable.
                  $(video).one('progress', cueVideo.bind(this, video, pos));
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        感谢您尝试以下答案。不幸的是,如果当前时间 > 0 且

        【讨论】:

          【解决方案5】:

          尝试将您的 X 限制为小数点后 1 位

          X.toFixed(1);
          

          正如您提到的,它有时会在 1 秒后起作用。您是否尝试在playing 事件触发后设置位置?甚至可能是canplaythrough 事件

          查看this page 的来源以查看可以使用的事件的完整列表(在 javascript 文件中)

          【讨论】:

            猜你喜欢
            • 2011-11-04
            • 1970-01-01
            • 2012-01-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-11
            • 1970-01-01
            • 2021-05-09
            相关资源
            最近更新 更多