使用两个AVPlayer加载同一个视频

3

我有两个不同的视图,都是用来播放同一个视频的。我正在创建一个应用程序,在视频播放期间会多次在这两个视图之间切换。

我目前是按以下方式加载带有视频的第一个视图:

NSURL *url = [NSURL URLWithString:@"http://[URL TO VIDEO HERE]"];
AVURLAsset *avasset = [[AVURLAsset alloc] initWithURL:url options:nil];

AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:avasset];
player = [[AVPlayer alloc] initWithPlayerItem:item];

playerLayer = [[AVPlayerLayer playerLayerWithPlayer:player] retain];
CGSize size = self.bounds.size;
float x = size.width/2.0-202.0;
float y = size.height/2.0 - 100;

//[player play];
playerLayer.frame = CGRectMake(x, y, 404, 200);
playerLayer.backgroundColor = [UIColor blackColor].CGColor;

[self.layer addSublayer:playerLayer];
NSString *tracksKey = @"tracks";

[avasset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
 ^{
     dispatch_async(dispatch_get_main_queue(),
                    ^{
                        NSError *error = nil;
                        AVKeyValueStatus status = [avasset statusOfValueForKey:tracksKey error:&error];

                        if (status == AVKeyValueStatusLoaded) {

                            //videoInitialized = YES;
                            [player play];
                        }
                        else {
                            // You should deal with the error appropriately.
                            NSLog(@"The asset's tracks were not loaded:\n%@", [error localizedDescription]);
                        }
                    });
 }];

在我的第二个视图中,我想从dispatch_get_main_queue加载视频,以便两个视图中的视频同步。
我希望有人可以帮助我将第一个视图中的视频数据加载到第二个视图中。

请审核我的答案是否正确,谢谢。 - Nikita
3个回答

5

这很简单:

初始化第一个玩家:

AVAsset *asset = [AVAsset assetWithURL:URL];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];

第二个玩家同样,但是使用第一个玩家的相同资产。我已经验证过,它有效。

您需要的所有信息都在苹果页面上: https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html

这种抽象意味着您可以同时使用不同的播放器播放给定的资产

这句话来自于这个页面。


0

我认为你无法让这种方法起作用。视频是在硬件中解码,然后将图形缓冲区发送到图形卡。你似乎想要做的是在一个视图中解码视频,然后捕获第一个视图的内容并在第二个视图中显示它。这样不会保持同步,因为需要时间将第一个窗口的内容捕获回主存储器,然后这些内容需要再次发送到视频卡。基本上,这是行不通的。你也不能解码两个h.264视频流并期望它们保持同步。

你可以完全采用另一种方法来实现这个。如果你将h.264视频解码为磁盘上的帧(将每个帧保存为PNG),然后编写自己的循环,该循环将解码一系列PNG中的第N个PNG,然后在两个不同的窗口中显示结果。这将足够快地在新的iPhone 4和5以及iPad 2和3上实现有效的实现。如果你想利用更高级的实现,请查看我的AVAnimator库,你可以使用现有代码在20分钟内让这种方法起作用。


谢谢您的建议!这个库也可以用于远程视频文件吗? - Ronny vdb
我假设你是在谈论流式视频,但这不支持流媒体(网络流媒体完全不同)。但是,如果一个H.264视频只是以普通文件的形式存在于远程服务器上,那么你可以下载它,等下载完成后再打开它。参见AVAssetReaderConvertMaxvid类的代码逻辑,该逻辑将从磁盘上读取H.264视频文件并将其解压缩到包含未压缩的RGB像素的文件中。示例项目AVDecodeEncode展示了解压缩和重新压缩所需的代码,但你只需要使用解压缩部分。 - MoDJ
首先,你的库做得非常好!在 iOS 上处理视频的实现很不错。不过,我需要一个能够处理视频流的解决方案。 - Ronny vdb

0

对于这个只有十年历史的问题,且其回答皆已过时了的问题,现在是最新回答。

var leadPlayer: AVPlayer ... the lead player you want to dupe

这个不起作用:

let leadPlayerItem: AVPlayerItem = leadPlayer.currentItem!
yourPlayer = AVPlayer(playerItem: leadPlayerItem)
yourPlayer.play()

苹果不允许那样做(尝试一下,会看到错误)。

这个可以。你必须使用该项:

let dupeItem: AVPlayerItem = AVPlayerItem(asset: leadPlayer.currentItem!.asset)
yourPlayer = AVPlayer(playerItem: dupeItem)
yourPlayer.play()

幸运的是,现在这很容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接