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

Der*_*ard 8 html javascript html5-video

问题

正如标题所说,我看到一个问题,浏览器(在通过视频进行搜索时)不断地请求它应该已经拥有的字节范围。

在此输入图像描述

代码

我提供了一个最小的代码示例;要重现该问题,请调整视频的当前时间控制并查看网络日志。

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) + "%";
    }
  });
}
Run Code Online (Sandbox Code Playgroud)
.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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

问题

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

nic*_*kl- 2

当我们引用TimeRanges 的规范时,我们发现以下定义。

当 TimeRanges 对象被称为规范化 TimeRanges 对象时,它表示的范围必须遵守以下标准:

  • 范围的开头必须大于所有较早范围的结尾。
  • 范围的开头必须小于或等于同一范围的结尾。

换句话说,此类对象中的范围是有序的,不重叠,也不接触(相邻范围被折叠成一个更大的范围)。范围可以为空(仅引用单个时刻),例如,当媒体元素暂停时,指示在用户代理已丢弃除当前帧之外的整个媒体资源的情况下当前仅缓冲一帧。

TimeRanges 对象中的范围必须包含在内。

因此,范围的结尾将等于后续相邻(接触但不重叠)范围的开头。类似地,覆盖锚定于零的整个时间线的范围将具有等于零的开始和等于时间线的持续时间的结束。

如果我要解释的话,我会想象只有最小 TimeRange 的末尾(索引 0)等于持续时间才能实现 100% 缓冲,即使在末尾可能保留多个范围,情况也并非如此。这与Mozilla 文档相矛盾,因此需要进行健全性检查。

基本上我们唯一需要推断的是缓冲的进度,安慰自己没有任何保证,甚至没有提到缓冲意味着已经下载、存储和随时可用的帧(永远不需要再次获取)。事实上,事实恰恰相反,存在“范围可以为空(仅引用单个时刻)”的可能性。

由于考虑当前时间作为我们的基础,任何使用的唯一缓冲时间范围将始终是未来内容,这不一定是最小范围。

基于演绎推理,我们可以安全地假设:

  • 缓冲总量必须至少是当前时间
  • 仅添加与未来范围末端的差异,并且
  • 包括任何后续范围的开始和结束之间的差值之和

或者用其他更雄辩的话来说:

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;
}
Run Code Online (Sandbox Code Playgroud)

当我们所有的鸭子整齐地排成一排时,这可能就被认为是完成了。

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) + "%";
    }
  });
}
Run Code Online (Sandbox Code Playgroud)
.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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)