如何对媒体片段的任何部分进行范围请求?

Posted

技术标签:

【中文标题】如何对媒体片段的任何部分进行范围请求?【英文标题】:How to make range request for any portion of a media fragment? 【发布时间】:2017-12-14 22:44:34 【问题描述】:

如果我们想发出HTTP/1.0HTTP/1.1 请求,例如给定媒体资源的字节20000 到100000 或20 到35 秒,例如.webm.ogg 音频或.mp4视频,其中响应将是一个离散的媒体片段,能够在没有媒体资源的其他部分的情况下播放,我们将如何实现这一点?

例如

let headers = new Headers();
let range = 1024 * 1024;
headers.append("Range", "bytes=0-" + range); 
let request = new Request(url, headers:headers);
fetch(request)
.then(response => response.blob())
.then(data => audio.src = URL.createObjectURL(data));

加载和媒体播放

let headers = new Headers();
let range = 1024 * 1024;
headers.append("Range", "bytes=" + range + "-" + range * 2);
let request = new Request(url, headers:headers);
fetch(request)
.then(response => response.blob())
.then(data => audio.src = URL.createObjectURL(data));

记录成功的200206 响应状态,但不会在<audio> 元素处呈现媒体播放。

如何为给定媒体创建一个范围请求,它只返回请求的资源范围作为能够在没有媒体的其他部分的情况下播放的离散资源,其中请求的媒体片段可以是媒体资源的任何离散部分?

【问题讨论】:

@charlietfl 是的plnkr.co/edit/h1MOoIPwgEf0WiHMdm6z?p=preview 刚刚发现 206 可能意味着它必须返回该标题 @charlietfl 编写了一个有问题的解决方法。有兴趣查看其他开发人员如何处理此案例。 @charlietfl HTTP/1.1 Range Requests @charlietfl fwiw,这是在尝试将媒体片段作为独立文件实现获取媒体片段时遵循问题代码的解决方法***.com/questions/45123057/… 【参考方案1】:

你根本做不到。

您绝对需要媒体文件(元数据)的标头,以便您的浏览器能够解码其中包含的数据。

不同的媒体格式会有不同的解析规则,数据块的顺序不同,并且只获取原始数据的一部分会破坏数据的整体结构。因此,对于某些文件格式,您可能可以通过仅提供文件开头来播放媒体的开头,但所有媒体格式都不允许这样做,甚至不期望从开头到结尾读取。

不过可以使用 MediaElement 的src 的timerange parameter:

#t=[starttime][,endtime]

const url = 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg';

btn.onclick = e => 
  // fast input check for the demo
  if (max.value > aud.duration)
    max.value = aud.duration;
  if (min.value > max.value)
    min.value = max.value - 1;
  // construct our timerange parameter
  let range = '#t=' + min.value + ',' + max.value;
  // append it to our original url
  aud.src = url + range;

btn.onclick();
<audio id="aud" aud controls></audio><br>
<label>start: <input id="min" type="number" value="10" min="0" max="119"></label>
<label>end: <input id="max" type="number" value="20" min="1" max="120"></label>
<button id="btn">re-load</button>

【讨论】:

结束标签应该是“结束”?是的,熟悉媒体片段 URI。是否可以创建可以单独播放的媒体片段的每个时间片段的记录并将片段合并到可以无缝播放的单个文件中?我们如何提取、创建或重用每种媒体类型的媒体头?为什么可以播放从0 开始的范围,而不是不以0 开始的范围? @guest271314,是的,您显然可以使用此方法为每个切片创建一个新的 MediaElement,然后使用其 captureStream 方法和 MediaRecorders 来导出这些片段。如果要连接它们,则必须控制一个流,在其中更新原始源的 currentTime,因为您无法以比 x1 更快的速度记录。 对于 为什么它不适用于除 0 以外的起始范围请求,这只是因为您很幸运所有 您的文件所需的元数据 b> 包含在此范围内。如果它位于文件的末尾,您将无法播放其中的任何内容。 如何提取必要的元数据并在需要它们的范围内复制和包含元数据***.com/questions/44976805/…? webmproject.org/docs/container 用于 webm,这可能是最好的开始,因为它有一个很好的类似 xml 的数据结构。但请注意,chrome 本身 isn't even able to generate correct metadata 用于记录文件。因此,如果您碰巧有足够的时间来做这件事,请不要犹豫,让我们知道。 (您可以找到 nodejs 的 EBML 解析器示例,这可能会对您的任务有所帮助)

以上是关于如何对媒体片段的任何部分进行范围请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 中实现部分 GET 请求?

给定一个文档,选择一个相关的片段

MPEG DASH 部分片段

当浏览器请求部分内容范围请求时,如何检测何时在 iframe 中加载 pdf?

软件测试之如何编写单元测试用例

带有多部分请求的 Spring Boot 不受支持的媒体类型