- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试在播放期间更改视频合成的布局(即其组件帧的变换)。似乎有时这行得通,并且视频合成无缝地更改为新的变换集,但其他时候它只是卡住并保持当前变换。 AVPlayer 实例上没有状态代码更改,播放器或播放器项目上也没有错误。
有没有人遇到过这种情况?任何关于为什么会发生这种情况或如何解决它的建议,我们将不胜感激。
部分代码如下所示。重要的一点是“playerItem.videoComposition = videoComposition”,这里是在点击视频时触发的(出于测试目的)。
此问题的另一种解决方案是在单独的图层上显示视频,但视频必须同步,因此合成似乎是实现此目的的唯一方法。
@implementation VideoView
{
CGSize _videoSize;
CMTimeRange _videoFullRange;
AVMutableCompositionTrack * _compositionTrackVideoA;
AVMutableCompositionTrack * _compositionTrackVideoB;
}
+ (Class)layerClass
{
return [AVPlayerLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if ( self )
{
NSString * videoAPath = [[NSBundle mainBundle] pathForResource:@"cam09v2" ofType:@"mp4"];
NSString * videoBPath = [[NSBundle mainBundle] pathForResource:@"cam10v2_b" ofType:@"mp4"];
AVURLAsset * videoAAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:videoAPath] options:nil];
AVURLAsset * videoBAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:videoBPath] options:nil];
AVAssetTrack * videoATrack = [[videoAAsset tracksWithMediaType:AVMediaTypeVideo] lastObject];
AVAssetTrack * videoBTrack = [[videoBAsset tracksWithMediaType:AVMediaTypeVideo] lastObject];
AVAssetTrack * audioTrack = [[videoAAsset tracksWithMediaType:AVMediaTypeAudio] lastObject];
_videoSize = [videoATrack naturalSize];
CMTime videoDuration = videoAAsset.duration;
_videoFullRange = CMTimeRangeMake(kCMTimeZero, videoDuration);
AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack * compositionTrackVideoA = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack * compositionTrackVideoB = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack * compositionTrackAudio = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
compositionTrackVideoA.preferredTransform = videoATrack.preferredTransform;
NSError * error = nil;
if ( ! [compositionTrackVideoA insertTimeRange:_videoFullRange ofTrack:videoATrack atTime:kCMTimeZero error:&error] )
NSLog(@"%@", error);
if ( ! [compositionTrackVideoB insertTimeRange:_videoFullRange ofTrack:videoBTrack atTime:kCMTimeZero error:&error] )
NSLog(@"%@", error);
if ( ! [compositionTrackAudio insertTimeRange:_videoFullRange ofTrack:audioTrack atTime:kCMTimeZero error:&error] )
NSLog(@"%@", error);
_compositionTrackVideoA = [compositionTrackVideoA copy];
_compositionTrackVideoB = [compositionTrackVideoB copy];
AVPlayerItem * playerItem = [AVPlayerItem playerItemWithAsset:composition];
AVPlayer * player = [AVPlayer playerWithPlayerItem:playerItem];
[(AVPlayerLayer *)self.layer setPlayer:player];
[player play];
[player addObserver:self forKeyPath:@"status" options:0 context:0];
[self updateCompositionForPlayerItem:playerItem];
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)];
[self addGestureRecognizer:tapGesture];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ( [keyPath isEqualToString:@"status"] )
NSLog(@"STATUS %d", ((AVPlayer *)object).status );
}
- (void)updateCompositionForPlayerItem:(AVPlayerItem *)playerItem
{
AVMutableVideoComposition * videoComposition = [AVMutableVideoComposition videoComposition];
AVMutableVideoCompositionInstruction *videoInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
videoInstruction.enablePostProcessing = NO;
videoInstruction.timeRange = _videoFullRange;
AVMutableVideoCompositionLayerInstruction * layerInstructionA = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:_compositionTrackVideoA];
CGAffineTransform transformA = CGAffineTransformMakeScale(0.5, 0.5);
[layerInstructionA setTransform:transformA atTime:kCMTimeZero];
AVMutableVideoCompositionLayerInstruction * layerInstructionB = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:_compositionTrackVideoB];
CGAffineTransform transformB = CGAffineTransformMakeScale(0.5, 0.5);
static int i = 0;
transformB = CGAffineTransformTranslate(transformB, (i++ % 2 == 0) ? _videoSize.width : 0, _videoSize.height);
[layerInstructionB setTransform:transformB atTime:kCMTimeZero];
videoInstruction.layerInstructions = [NSArray arrayWithObjects:layerInstructionA, layerInstructionB, nil];
videoComposition.instructions = [NSArray arrayWithObject:videoInstruction];
videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps
videoComposition.renderSize = _videoSize;
playerItem.videoComposition = videoComposition;
}
- (void)didTap:(UITapGestureRecognizer *)tapGesture
{
[self updateCompositionForPlayerItem:((AVPlayerLayer *)self.layer).player.currentItem];
}
@end
最佳答案
您可以保存您想要更改它的时间,并用新的视频组合替换播放器项目,并从您停止播放的时间开始使用新的播放器项目重新启动播放器。
关于objective-c - 在播放期间更改 AVPlayerItem 的 videoComposition 属性 (AVMutableVideoComposition),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10663736/
我对 AVPlayer.timeControlStatus 属性进行 KVO 处理,播放器有一个 AVPlayerItem。 该视频是托管在远程服务器上的 mpeg4 编码的 10 秒视频文件: le
我有一个崩溃影响了我大约 10% 的用户,但我无法重现它,并且不知道发生这种情况的确切时间。 Crashlytics 报告说,大约一半的崩溃用户没有关注应用程序,即做背景音频或 AirPlay。该应用
我一直收到这个错误: 'An AVPlayerItem can occupy only one position in a player's queue at a time.' 我对玩家项目进行了 N
我正在使用 AVPlayer 播放流式网络音频。我观察流项目的状态如下: ios avplayer trigger streaming is out of buffer 工作看起来不错,但我遇到了一个
这段代码在iOS 12上崩溃,并带有无法识别的选择器异常: [AVPlayerItem externalMetadata]: unrecognized selector sent to instanc
我正在使用 AVQueuePlayer 在我们的应用程序中播放视频列表。我正在尝试缓存 AVQueuePlayer 播放的视频,这样就不必每次都下载视频。 因此,在视频播放完毕后,我尝试将 AVPla
我收到警报消息“无法解码。此媒体所需的解码器正忙。”当尝试在应用程序中第五次播放视频文件时。搜索后我发现AVPlayerItem fails with AVStatusFailed and error
我正在使用“initWithUrl:”方法初始化 AVPlayerItem。 问题是当初始化中断时(例如连接丢失) 假设我们有以下内容: self.avPlayerItem = [[AVPlayerI
刚刚发现一个很奇怪的问题, 从本地存储加载 mp3 文件时, avplayeritem一直处于未知状态,如果文件放在文件夹中则无法播放。 方式一: //AVAsset *asset = [[AVURL
我正在使用 AVPlayer,它通过 AVPlayerItem 连接到远程 URL。问题是我想立即播放来自 URL 的声音,不要让用户等待 AVPlayer 缓冲。 问题在于,如果远程 URL 的 A
我知道当使用 AVQueuePlayer 播放 AVPlayerItem 对象列表时,播放器会预加载队列中的下一个项目,以便在用户到达该项目时更快地重新加载。 问题是我需要对预加载哪些项目有更多的控制
我看过many questions对此,没有人有解决方案。我得到: An AVPlayerItem can occupy only one position in a player's queue a
尝试从我的临时目录播放视频时出现此错误: NSString *tmpDir = [NSTemporaryDirectory() stringByAppendingString:@"/"]; NSStr
如果我使用 KVO 来观察我的播放器项目,如下所示: AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
我正在使用 AVPlayer 播放 AVMutableVideoComposition 并且从 IOS8 开始一切都很好。 但是现在视频开始播放,在 4 或 5 秒后停止,比如缓冲或类似的东西,声音继
我目前正在使用 AVPlayerItem 从 URL 播放实时流。我的代码是 - (void)viewDidLoad { AVPlayerItem* playerItem = [AVPlaye
我在我的应用程序中使用 AVQueuePlayer,我需要一个数组,其中包含类型为 [AVPlayerItem] 的轨道。每次 TableView 加载时都必须创建数组。我还有一个包含当前文件夹中元素
我有一个缓存类,它将 MP3 文件下载到某个缓存文件夹并将其命名为 xxxx.cache 我有一个加载 MP3 文件的 AVQueuePlayer。从我的 NSBundle Resources 文件夹
我有一个使用 AVQueuePlayer 对象的简单音频播放列表。通过迭代包含自定义 UITableViewCell 对象 PlayableAudioCell 的 UITableView 来填充队列。
我正在开发一个播放音频文件或流媒体的应用程序,遇到了一个我无法解决的问题。基本上我的 AVPlayer 在当前项目发生故障后不再播放新项目。下面是一个快速应用程序,您可以复制/粘贴以进行复制。 imp
我是一名优秀的程序员,十分优秀!