126

请注意,对于以下问题:所有资产在设备上都是本地的——没有发生网络流式传输。视频包含音轨。

我正在开发一个 iOS 应用程序,该应用程序需要以最小延迟播放视频文件才能启动相关视频剪辑。不幸的是,在我们真正需要启动它之前,我们不知道接下来是什么特定的视频剪辑。具体来说:当播放一个视频剪辑时,我们将知道下一组(大约)10 个视频剪辑是什么,但我们不知道具体是哪一个,直到“立即”播放下一个剪辑。

我查看实际开始延迟所做的是调用addBoundaryTimeObserverForTimes视频播放器,以一毫秒的时间段查看视频实际开始播放的时间,我将时间戳与第一个位置的差异指示要开始播放哪个资产的代码。

从到目前为止我所看到的情况来看,我发现使用AVAsset加载的组合,然后在它准备好后从中创建一个AVPlayerItem,然后在我调用播放之前等待AVPlayerStatusReadyToPlay,往往需要 1 到 3 秒来启动夹子。

从那以后,我转向了我认为大致相同的方式:打电话[AVPlayerItem playerItemWithURL:]和等待AVPlayerItemStatusReadyToPlay比赛。性能大致相同。

我观察到的一件事是第一个 AVPlayer 项目加载比其他项目慢。似乎一个想法是在尝试播放第一个视频之前使用短/空资产预飞行 AVPlayer 可能是一个很好的一般做法。[第一次播放声音时 AVAudioPlayer 启动缓慢

我很想尽可能缩短视频的开始时间,并有一些可以尝试的想法,但希望任何可以提供帮助的人提供一些指导。

更新:下面的想法 7 实现的切换时间约为 500 毫秒。这是一个改进,但如果能更快地实现这一点会很好。

想法1:使用N个AVPlayers(不起作用)

使用〜10个AVPPlayer对象并开始和暂停所有〜10个剪辑,一旦我们知道我们真正需要哪个,切换到并取消暂停正确的AVPlayer,然后重新开始下一个周期。

我认为这行不通,因为我读过AVPlayer'siOS 中大约有 4 个活动的限制。有人在 StackOverflow 上询问这个问题,发现了 4 AVPlayer 限制:fast-switching-between-videos-using-avfoundation

想法 2:使用 AVQueuePlayer(不起作用)

我不相信将 10 推AVPlayerItems入一个AVQueuePlayer会预先加载它们以实现无缝启动。 AVQueuePlayer是一个队列,我认为它实际上只会使队列中的下一个视频准备好立即播放。我不知道我们想要播放大约 10 个视频中的哪一个,直到该开始播放那个了。ios-avplayer-视频预加载

想法 3:在后台加载、播放和保留AVPlayerItems(还不是 100% 确定——但看起来不太好)

我正在研究在后台加载和播放每个视频剪辑的第一秒是否有任何好处(抑制视频和音频输出),并保持对每个的引用AVPlayerItem,以及当我们知道需要播放哪个项目时真实的,交换那个,并将背景 AVPlayer 与活动的交换。冲洗并重复。

理论上,最近播放AVPlayer/AVPlayerItem的 's 可能仍保留一些准备好的资源,这将使后续播放更快。到目前为止,我还没有看到这样做的好处,但我可能没有AVPlayerLayer正确设置背景。我怀疑这真的会改善我所看到的情况。

想法 4:使用不同的文件格式——也许加载速度更快?

我目前正在使用 .m4v 的 (video-MPEG4) H.264 格式。H.264 有很多不同的编解码器选项,因此某些选项可能比其他选项搜索得更快。我发现使用更高级的设置使文件更小会增加查找时间,但没有找到任何相反的选项。

思路五:无损视频格式+AVQueuePlayer的组合

如果有一种视频格式可以快速加载,但文件大小可能很疯狂,一个想法可能是预先准备每个视频剪辑的前 10 秒,使用一个臃肿但加载速度更快但又回来的版本加上以 H.264 编码的资产。使用 AVQueuePlayer,并以未压缩文件格式添加前 10 秒,然后使用 H.264 格式的文件,其准备/预加载时间长达 10 秒。所以我会得到两全其美的“最好的”:快速启动时间,但也受益于更紧凑的格式。

想法 6:使用非标准的 AVPlayer / 自己编写 / 使用别人的

鉴于我的需要,也许我不能使用 AVPlayer,但必须求助于 AVAssetReader,并在前几秒钟解码(可能将原始文件写入磁盘),并且在播放时,使用原始格式播放它快回来。对我来说似乎是一个巨大的项目,如果我以一种天真的方式去做,那就不清楚/不太可能做得更好。每个解码和未压缩的视频帧为 2.25 MB。天真地说——如果我们以大约 30 fps 的速度播放视频,我最终会得到大约 60 MB/s 的磁盘读取要求,这可能是不可能的/推动它。显然,我们必须进行某种程度的图像压缩(也许是通过 PVRTC 的原生 openGL/es 压缩格式)......但这有点疯狂。也许那里有一个我可以使用的图书馆?

想法 7:将所有内容组合成一个电影资产,并 seekToTime

一个可能比上述一些更容易的想法是将所有内容组合成一个电影,并使用 seekToTime。问题是我们会到处乱跳。基本上是随机访问电影。我认为这实际上可以正常工作:avplayer-movie-playing-lag-in-ios5

您认为哪种方法最好?到目前为止,我在减少延迟方面没有取得太大进展。

4

6 回答 6

6

对于 iOS 10.x 及更高版本,以减少我设置的 AVPlayer 启动延迟: avplayer.automaticallyWaitsToMinimizeStalling = false; 这似乎为我解决了这个问题。这可能会产生其他后果,但我还没有达到这些后果。

我的想法来自: https ://stackoverflow.com/a/50598525/9620547

于 2019-04-30T19:37:05.480 回答
1

一旦您创建了资产,它可能还没有准备好,它可能会计算电影的持续时间,请确保在文件中包含电影的所有元数据。

于 2012-10-31T12:17:42.433 回答
1

您应该首先尝试选项#7,看看您是否可以使其正常工作。我怀疑它实际上无法满足您的需求,因为搜索时间可能不够快,无法让您在剪辑之间无缝切换。如果您尝试这样做但失败了,那么我建议您执行选项 4/6 并查看我专门为此目的设计的 iOS 库,只需在 AVAnimator 上进行快速谷歌搜索以了解更多信息。我的库可以实现无缝循环并从一个剪辑切换到另一个剪辑,它非常快,因为必须事先将视频解码为文件。在您的情况下,所有 10 个视频剪辑都会在您开始之前被解码为文件,但是在它们之间切换会很快。

于 2013-06-10T21:04:47.967 回答
0

过去没有做过类似的事情,根据您的想法和经验,我会尝试 7 和 1 的组合:在 10 个后续视频的前几秒预加载一个 AVPlayer。然后,由于数据较少,跳过很可能会更快、更可靠。在播放所选片段时,您有足够的时间在后台为所选后续视频的其余部分准备 AVPlayer。开始完成后,切换到准备好的 AVPlayer。因此,总的来说,您在任何给定时间最多加载 2 个 AVPlayer。

当然不知道切换能不能流畅到不打扰播放。

(如果可以的话,会添加这个作为评论。)

最好的,彼得

于 2012-09-07T19:44:31.813 回答
0

如果我正确理解了您的问题,您似乎有一个连续的视频,您需要立即加载音轨。

如果是这种情况,我建议研究BASS。BASS 是一个类似于 AVPlayer 的音频库,它让您(相对)轻松地访问 iOS 中 AudioUnits 框架的低级 API。对你来说意味着什么?这意味着通过一点点缓冲区操作(您甚至可能不需要它,取决于您想要的延迟有多小),您可以立即开始播放音乐。

然而,限制扩展到视频,正如我所说,它是一个音频库,因此任何视频操作仍然必须使用 AVPlayer 完成。但是,-seekToTime:toleranfeBefore:toleranceAfter:只要您预先设置所有必要的选项,您就应该能够在视频中实现快速搜索。

如果您要跨多个设备同步(您的应用程序可能会建议),只需发表评论,我很乐意编辑我的答案。

PS:BASS 乍一看可能会让人望而生畏,因为它是类似 C 的格式,但实际上它真的很容易使用。

于 2017-06-20T13:31:15.453 回答
-2

以下是 AVAsset 类提供的几个可能有帮助的属性和方法:

- (void)_pu_setCachedDuration:(id)arg1;
- (id)pu_cachedDuration; 
- (struct
 { 
   long long x1; 
   int x2;
   unsigned int x3; 
   long long x4; 
})pu_duration;
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1;
于 2016-08-06T03:30:18.713 回答