【问题标题】:Another: Force Chrome to fully buffer mp4 video另:强制 Chrome 完全缓冲 mp4 视频
【发布时间】:2013-08-15 11:19:10
【问题描述】:

我已经看到了一些关于这个的帖子,但没有答案,所以我想我应该在被污染的 youtube 相关页面的坟墓场添加另一个。

我有一个 100MB 的 mp4 视频,需要通过浏览器完全下载,

但是,当它完全下载时没有触发事件,并且 Chrome 似乎停止缓冲任何视频,直到当前视频时间几乎达到缓冲区的末尾,然后它会请求更多。

如何让浏览器完全下载视频并 100% 缓冲?

谢谢

【问题讨论】:

    标签: html google-chrome video buffer mp4


    【解决方案1】:

    可悲的是,Chrome - 与其他 HTML5 浏览器一样 - 试图对其下载的内容保持智能并避免不必要的带宽使用......这意味着有时我们会获得次优体验(讽刺的是,YouTube 遭受了如此多的痛苦,以至于有一些扩展可以强制进行更多的预缓冲!)

    也就是说,我发现这对于良好的服务器和良好的连接并不经常需要 - 但如果您需要某些东西,我发现的唯一解决方案是有点大锤......使用 Ajax 下载您要播放的文件,然后将其加载到视频元素的源中。

    以下示例假设您的浏览器支持 m4v/mp4 - 如果您不能保证(例如)Chrome,您可能希望使用 canPlayType 测试为您的用户选择最合适的视频格式。您还需要测试一下它处理您想要大小的视频的能力(我尝试了一些相当大的视频,但不确定它可以可靠地处理什么上限)

    该示例也非常简单...它启动请求并且在加载时不向用户传达任何信息 - 对于您大小的视频,您可能希望显示一个进度条以保留它们有兴趣...

    此过程的另一个缺点是,在您完全下载文件之前它不会开始播放 - 如果您想更深入地从缓冲区动态显示视频,那么您需要开始深入研究MediaSource 的前沿(目前)世界,如 http://francisshanahan.com/index.php/2013/build-an-mpeg-dash-player-from-scratch/ 之类的帖子中所述

    <!DOCTYPE html>
    <html>
    <head>
    <title>Preload video via AJAX</title>
    </head>
    <body>
    <script>
    console.log("Downloading video...hellip;Please wait...")
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'BigBuck.m4v', true);
    xhr.responseType = 'blob';
    xhr.onload = function(e) {
      if (this.status == 200) {
        console.log("got it");
        var myBlob = this.response;
        var vid = (window.webkitURL || window.URL).createObjectURL(myBlob);
        // myBlob is now the blob that the object URL pointed to.
        var video = document.getElementById("video");
        console.log("Loading video into element");
        video.src = vid;
        // not needed if autoplay is set for the video element
        // video.play()
       }
      }
    
    xhr.send();
    </script>
    
    <video id="video" controls autoplay></video>
    
    </body>
    </html>
    

    【讨论】:

    • Blob 无法在三星互联网(三星默认浏览器)8.2 版本中运行
    • 请问,作为最终用户视频查看器而不是网站开发人员,我该如何做?
    【解决方案2】:

    我的解决方案是针对比所描述的 OP 小得多的视频,但是所需的行为是相同的:阻止视频开始播放,直到视频完全缓冲。如果视频已被缓存,则应为返回用户播放视频。

    以下答案深受answer 的影响,并已在 Chrome、Safari 和 Firefox 上进行了测试。

    Javascript 文件:

        $(document).ready(function(){
          // The video_length_round variable is video specific.
          // In this example the video is 10.88 seconds long, rounded up to 11.
          var video_length_round = 11;
    
          var video = document.getElementById('home_video_element');
          var mp4Source = document.getElementById('mp4Source');
    
          // Ensure home_video_element present on page
          if(typeof video !== 'undefined'){
    
            // Ensure video element has an mp4Source, if so then update video src
            if(typeof mp4Source !== 'undefined'){
              $(mp4Source).attr('src', '/assets/homepage_video.mp4');
            }
    
            video.load();
    
            // Ensure video is fully buffered before playing
            video.addEventListener("canplay", function() {
              this.removeEventListener("canplay", arguments.callee, false);
    
              if(Math.round(video.buffered.end(0)) >= video_length_round){
                // Video is already loaded
                this.play();
    
              } else {
                // Monitor video buffer progress before playing
                video.addEventListener("progress", function() {
                  if(Math.round(video.buffered.end(0)) == video_length_round){
                    this.removeEventListener("progress", arguments.callee, false);
                    video.play();
                  }
                }, false);
              }
            }, false);
          }
        });
    

    上面的 javascript 更新了视频元素的来源,例如这个:

        <video id="home_video_element" loop="" poster="/assets/home/video_poster_name.jpg" preload="auto">
          <source id="mp4Source" type="video/mp4">
        </video>
    

    【讨论】:

      【解决方案3】:

      我遇到了一个类似的问题,我想在哪里解决,我希望 chrome 能够更积极地在未计量连接的桌面上为用户加载视频。我尝试按照上面建议的答案之一查看MediaSource,但使用它会涉及我必须将我的 mp4 编码为碎片化的 mp4,这似乎工作量太大。

      最终我决定采取这种行为:

      <!DOCTYPE html>
      <html>
      <head>
        <title>Test</title>
      </head>
      
      <script>
        function load(){
          const url = document.getElementById('url').value
          const vid = document.getElementById('video')
          vid.src = url;
          const progressElem = document.getElementById('progress')
      
          const xhr = new XMLHttpRequest();
          xhr.onload = function() {
              const wasPaused = vid.paused
              const time =  vid.currentTime;
              vid.src = URL.createObjectURL(xhr.response);
              vid.currentTime = time;
              if(!wasPaused)
                vid.play();
          };
          xhr.onprogress = onprogress = function (event) {
            progressElem.innerText = 'Download Progress: ' + (event.loaded / event.total);
          };
      
          xhr.responseType = "blob";
          xhr.open("GET", url)
          xhr.send();
        }
      </script>
      
      
      <body style="padding-left: 30px">
          <h1>Testing video loading</h1>
          <input type="text" id="url" value="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" size="200">
          <br>
          <button onclick="load()">Load Video</button>
          <br>
          <h3 id="progress"></h3>
          <br>
          <video id="video" style="max-width:min(800px, 100vw)" controls></video>
      </body>
      </html>

      基本上,我会先让用户从他们的浏览器本地流式传输视频,但我也会开始下载整个文件,一旦完成,我只需将下载的数据交换到 vid.src 并确保玩家处于正确的状态。请注意,这确实会在视频中产生轻微的卡顿/缓冲效果。

      此解决方案绝对不是最节省带宽的解决方案,但对于台式机上的 1-2GB 视频文件来说,它似乎工作得相当好。

      我还应该提到,我认为您应该只在 Chrome 中执行此操作,因为其他浏览器可能有更好的解决方案。例如,在 Firefox 中,settings 用户可以访问哪些控制视频的缓冲量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 1970-01-01
        • 2017-06-06
        • 1970-01-01
        • 2021-05-09
        • 2012-12-12
        • 2014-09-01
        相关资源
        最近更新 更多