javascript - 浏览器发送已缓冲视频数据的请求

标签 javascript html html5-video

问题
正如标题所说,我看到了一个问题,即浏览器(在通过视频搜索时)不断地请求它应该已经拥有的字节范围。
enter image description here
代码
我提供了一个最小的代码示例;要复制该问题,请绕过视频上的当前时间控制并查看您的网络日志。

window.onload = function() {

  var myVideo = document.getElementById('my-video');

  myVideo.addEventListener('progress', function() {
    var bufferedEnd = myVideo.buffered.end(myVideo.buffered.length - 1);
    var duration = myVideo.duration;
    if (duration > 0) {
      document.getElementById('buffered-amount').style.width = ((bufferedEnd / duration) * 100) + "%";
    }
  });

  myVideo.addEventListener('timeupdate', function() {
    var duration = myVideo.duration;
    if (duration > 0) {
      document.getElementById('progress-amount').style.width = ((myVideo.currentTime / duration) * 100) + "%";
    }
  });
}
.buffered {
  height: 20px;
  position: relative;
  background: #555;
  width: 300px;
}

#buffered-amount {
  display: block;
  height: 100%;
  background-color: #777;
  width: 0;
}

.progress {
  margin-top: -20px;
  height: 20px;
  position: relative;
  width: 300px;
}

#progress-amount {
  display: block;
  height: 100%;
  background-color: #595;
  width: 0;
}
<video id="my-video" controls preload="auto"><source src="https://media-dev.ozone.tech/media/045728df-7431-4548-8353-318357cc2643/video_preview-1655322764.5499873.mp4?Expires=1656287999&Signature=3RnkLu03JreuUZk9bICqqC5IwGiq~tWpBCaUSfyGb9W9VLPfw6Na4zh~tDTxxDjIirhocj7es2T0ONm0L6XsuFxsCx2T9-CANok014Kt6ddHEaUmuOi5uztEWyXpLmI3ussq4dc5lW2Xw5WH6uV-5Z8fIlIQehMxQK-XQ6RpdHhWBQLsmfPBqSSPnDk6KH5fkK-xCwQmxUwAN1nRVH8H6p~43~E6MZa7gSS~i1717~FlHto3depk~AvREjm59T1rNBvaZeb6ZI-pnYAf52wwQs3pWXln7PCtiIOYQCxE10l4nkOvJ--KGmPA0jOeSuv0dCRUi3QLZD5JxsJgBVM4sA__&Key-Pair-Id=K16V0JZ9ZAOTC6" type="video/mp4"></video>
<div class="buffered">
  <span id="buffered-amount"></span>
</div>
<div class="progress">
  <span id="progress-amount"></span>
</div>

问题
有人可以解释为什么会发生这种情况以及如何防止它吗?似乎这可能是一个错误,但由于所有浏览器都在这样做,我想知道这是否是我的问题;也许我们编码视频的方式?

最佳答案

当我们引用 the specification on TimeRanges我们找到以下定义。

When a TimeRanges object is said to be a normalized TimeRanges object, the ranges it represents must obey the following criteria:

  • The start of a range must be greater than the end of all earlier ranges.
  • The start of a range must be less than or equal to the end of that same range.

In other words, the ranges in such an object are ordered, don't overlap, and don't touch (adjacent ranges are folded into one bigger range). A range can be empty (referencing just a single moment in time), e.g. to indicate that only one frame is currently buffered in the case that the user agent has discarded the entire media resource except for the current frame, when a media element is paused.

Ranges in a TimeRanges object must be inclusive.

Thus, the end of a range would be equal to the start of a following adjacent (touching but not overlapping) range. Similarly, a range covering a whole timeline anchored at zero would have a start equal to zero and an end equal to the duration of the timeline.


如果我要解释的话,我会想象只有当最小的 TimeRange(索引 0)的结尾等于持续时间时,才能实现 100% 的缓冲,即使在结尾处可能会保留多个范围,情况也并非如此。这与 the Mozilla documentation 相矛盾。 ,这么多的健全性检查。
基本上我们唯一需要推断的是缓冲的进度,安慰自己没有任何保证,甚至提到缓冲意味着已经下载、存储和随时可用的帧(不需要再次获取)。事实上,情况正好相反,存在“范围可以为空(仅引用单个时刻)”的可能性。
由于任何使用的唯一缓冲时间范围总是以当前时间为基础的 future 内容,这可能不一定是最小范围。
基于演绎推理,我们可以安全地假设:
  • 缓冲的总时间必须至少是当前时间
  • 仅添加与 future 范围结束的差异和
  • 包括任何后续范围的开始和结束之差的总和

  • 或者用其他更有说服力的话:
    function bufferedTotal(buffered, currentTime) {
        let total = currentTime;
        for (i = 0; i < buffered.length; i++)
            if (buffered.end(i) > currentTime)
                if (buffered.start(i) < currentTime)
                    total += buffered.end(i) - currentTime;
                else
                    total += buffered.end(i) - buffered.start(i);
        return total;
    }
    
    我们所有的鸭子都整齐地排成一排,这可能只是被认为完成了。

    window.onload = function() {
    
      function bufferedTotal(buffered, currentTime) {
         let total = currentTime;
         for (i = 0; i < buffered.length; i++)
              if (buffered.end(i) > currentTime)
                  if (buffered.start(i) < currentTime)
                      total += buffered.end(i) - currentTime;
                  else
                      total += buffered.end(i) - buffered.start(i);
          return total;
      }
    
      var myVideo = document.getElementById('my-video');
    
      myVideo.addEventListener('progress', function() {
        var bufferedEnd = bufferedTotal(myVideo.buffered, myVideo.currentTime);
        var duration = myVideo.duration;
        if (duration > 0) {
          document.getElementById('buffered-amount').style.width = ((bufferedEnd / duration) * 100) + "%";
        }
      });
    
      myVideo.addEventListener('timeupdate', function() {
        var duration = myVideo.duration;
        if (duration > 0) {
          document.getElementById('progress-amount').style.width = ((myVideo.currentTime / duration) * 100) + "%";
        }
      });
    }
    .buffered {
      height: 20px;
      position: relative;
      background: #555;
      width: 300px;
    }
    
    #buffered-amount {
      display: block;
      height: 100%;
      background-color: #777;
      width: 0;
    }
    
    .progress {
      margin-top: -20px;
      height: 20px;
      position: relative;
      width: 300px;
    }
    
    #progress-amount {
      display: block;
      height: 100%;
      background-color: #595;
      width: 0;
    }
    <video id="my-video" controls preload="auto"><source src="https://media-dev.ozone.tech/media/045728df-7431-4548-8353-318357cc2643/video_preview-1655322764.5499873.mp4?Expires=1656287999&Signature=3RnkLu03JreuUZk9bICqqC5IwGiq~tWpBCaUSfyGb9W9VLPfw6Na4zh~tDTxxDjIirhocj7es2T0ONm0L6XsuFxsCx2T9-CANok014Kt6ddHEaUmuOi5uztEWyXpLmI3ussq4dc5lW2Xw5WH6uV-5Z8fIlIQehMxQK-XQ6RpdHhWBQLsmfPBqSSPnDk6KH5fkK-xCwQmxUwAN1nRVH8H6p~43~E6MZa7gSS~i1717~FlHto3depk~AvREjm59T1rNBvaZeb6ZI-pnYAf52wwQs3pWXln7PCtiIOYQCxE10l4nkOvJ--KGmPA0jOeSuv0dCRUi3QLZD5JxsJgBVM4sA__&Key-Pair-Id=K16V0JZ9ZAOTC6" type="video/mp4"></video>
    <div class="buffered">
      <span id="buffered-amount"></span>
    </div>
    <div class="progress">
      <span id="progress-amount"></span>
    </div>

    关于javascript - 浏览器发送已缓冲视频数据的请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72624500/

    相关文章:

    video-streaming - 来自 mp4box 的 DASH .mpd 不在 Dash.js 播放器中播放

    javascript - 有状态 React 组件协同工作时遇到问题

    javascript - 添加一个使用 jquery 滚动时移动的动态 div

    html - 如何隐藏子菜单,直到它被鼠标悬停

    ios - HTML5 视频标签在 iOS 上不可靠

    javascript - 使用指向不同质量版本的源更改视频质量

    javascript - 保存 SVG 中图案图像的纵横比,如 css 背景图像封面

    javascript - React useState 钩子(Hook)不触发子组件的重新渲染

    html - 溢出时的假滚动条 : hidden

    jquery - 向上滑动页脚