繁体   English   中英

如果没有 AVPlayer 在播放文件之前下载文件,我如何从 S3 stream MP4 视频?

[英]How can I stream MP4 videos from S3 without AVPlayer downloading the files before playing them?

我在公共 S3 存储桶中有很多长(45 分钟 - 90 分钟)的 MP4 视频,我想使用AVPlayer在我的 iOS 应用程序中播放它们。

我正在使用AVPlayerViewController来播放它们,但我需要等待几分钟才能开始播放,因为它会下载整个视频而不是流式传输。

我在本地缓存它,所以这只是第一次发生,但我很想 stream 视频,这样用户就不必等待整个视频下载。

有些人指出我需要 Cloudfront 到 stream 视频,但在文档中,我读到只有当许多人流式传输同一文件时才需要这样做。 我正在构建一个 MVP,所以我只需要一个简单的解决方案。

有什么方法可以从带有AVPlayerViewController的 S3 存储桶中获取 stream MP4 视频,而无需在向用户播放之前完全下载该文件?

TLDR

AVPlayer不支持您定义的“流式传输”(HTTP 范围请求),因此要么使用替代的视频播放器,要么使用AVPlayer支持的真实媒体流协议(如 HLS),并在下载所有视频之前启动视频.

CloudFront 通常非常适合交付,但并不是真正需要的 - 您可能已经看到由于 CloudFront RTMP发行版而提到它,但它们现在已停产


详细解答

S3 使用HTTP 范围请求支持称为字节范围提取的概念 - 您可以通过对视频文件执行 HEAD 请求并查看Accept-Ranges header 存在且值设置为字节(或不是“无”)来验证这一点。

在浏览器中加载您的 MP4 文件并注意它可以在您单击播放时立即启动。 您还可以移动到视频文件的末尾,但您还没有真正下载整个视频文件。 HTTP 范围请求是允许此机制工作的原因。 当用户到达视频的那部分时,可以下载小块视频。 这节省了文件服务器和用户带宽,同时提供比客户端下载整个文件更好的用户体验。

在客户端可以决定发出范围请求(或不发出)之前,服务器首先需要支持字节范围提取。 关键是,一旦服务器支持它,则由 HTTP 客户端决定是要以块的形式获取数据还是在一个 go 中获取数据。

正如您所知道的那样,这并不是真正的“流式传输”,并且在您的问题中指的是,它更多的是使用 HTTP 206 Partial Content 响应“从服务器中分块下载视频并播放”。

在视频中搜索时,您可以在浏览器的“网络”选项卡中将其视为一系列多个 206 响应。 不会下载整个视频,但视频是从您跳到的 position 流式传输的。

当在浏览器中加载视频并移动到视频中的随机点时,显示 Google Chrome 的网络选项卡中的多个 HTTP 206 部分内容响应的图像;突出显示 HTTP 范围请求


AVPlayer的问题

不幸的是, AVPlayer不支持使用 HTTP 范围请求和 HTTP 206 部分内容响应的“流式传输”。 我已经通过在 Xcode 中创建演示 iOS 应用程序手动验证了这一点。

这与 S3 无关- 如果您将这些文件存储在任何其他云提供商或文件服务器上,您会看到文件在播放之前仍然完全加载。


可能的解决方案

现在问题很清楚了,有2个解决方案。

使用其他视频播放器

最简单的解决方案是使用支持字节范围提取的替代视频播放器。 我不是 iOS 开发方面的专家,所以我很遗憾无法推荐替代方案,但我敢肯定会有一个流行的库,业界更喜欢内置的AVPlayer 这将为您提供“流媒体”的(非常常见的)定义。

使用视频流协议

但是,如果您必须使用AVPlayer ,解决方案是使用视频流协议实现真正的媒体流 - 真正的流还允许您利用自适应比特率切换、实时音频切换、许可等功能。

有很多这样的协议可用,例如DASH (HTTP 上的动态自适应流)、 SRT (安全可靠传输)和最后但并非最不重要的HLS (HTTP 实时流)。

今天,互联网上使用最广泛的流媒体协议是苹果自己创建的 HLS(嘿,也许不支持范围请求的原因是强迫你使用该协议)。 如果您有兴趣, Apple 自己的文档非常适合深入研究。

无需过多了解协议细节,HLS 将允许播放开始更快,快进可以更快,并在观看时提供视频,以获得真正的流媒体体验。

在 HLS 之前到 go:

  1. 使用AWS Elemental MediaConvert将您的 MP4 文件转换为 HLS 格式 - 生成的 output 将是 1 个(或更多) .M3U8清单文件以及.ts媒体段文件

  2. 将生成的 output 上传到 S3

  3. AVPlayer指向.M3U8文件

let asset = AVURLAsset(url: "https://ermiya.s3.eu-west-1.amazonaws.com/videos/video1playlist.m3u8")
let item = AVPlayerItem(asset: asset)
...
  1. 享受近乎即时的视频加载

CloudFront

关于Amazon CloudFront ,它本身并不是必需的,在这种情况下 S3 就足够了,但是快速的 Google 搜索会提到它提供的大量好处,尤其是缓存,它可以帮助您以后节省 S3 成本。


结论

如果可以的话,我会使用 go 转换为 HLS,因为它会产生更多的可能性,并且通常是更好的真正流媒体体验,但是由于 iOS AVPlayer限制,使用替代视频播放器也可以正常工作。

是否使用 CloudFront,将取决于您的用户群、S3 的使用情况和其他因素。

在创建 MVP 时,我建议您将 MP4 文件批量转换为 HLS 格式,而不使用 CloudFront,这会增加云配置的复杂性。

正如@ErmiyaEskandary 所说,您可以只使用 HLS 来解决您的问题,这可能是个好主意,但您不必等待整个 MP4 文件下载后再使用 AVPlayer 播放。 问题实际上根本不在于 AVPlayer 或字节范围请求,而在于 MP4 文件的格式。

您的 MP4 文件可能未正确配置为流式传输。 MP4 有一个称为 MOOV 原子的元数据部分。 默认情况下,许多编码器将其放在文件的后面。 在这种情况下,播放器必须先下载整个文件才能开始播放。

对于流式用例,这需要放在文件的前面。 然后播放器只需要缓冲 MOOV 原子,它就可以在加载数据时开始播放视频。

您可以使用启用了快速启动标志的 ffmpeg 将 MOOV 原子移动到文件的开头。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM