首页 文章

如何独立处理AVURLAsset的单独轨道?

提问于
浏览
5

这是我的目标:我想将.3gp电影文件加载到AVURLAsset中 . 然后我想拍摄视频轨道并将输出帧泵入OpenGL ES纹理 . 这将是视频播放 . 我想继续利用AVFoundation播放音频 . 这个框架相当广泛,所以我希望能有一些老练的帮助 .

实际上我有两个部分分别工作,但当我尝试同时做两件事时总会出错 . 这是我目前的尝试,简而言之(为简洁起见省略了所有错误处理):

我将.3gp文件加载到AVURLAsset并加载轨道:

NSURL* fileURL = [[NSBundle mainBundle] URLForResource:someName withExtension:someExtension];
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^ {/* More Code */}];

在完成处理程序中,我获得了对音频和视频轨道的引用:

// Tracks loaded, grab the audio and video tracks.
AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

接下来,我创建了单独的AVMutableComposition,它们只包含音轨和视频轨道 . 我不确定这是否完全必要,但它似乎是一个好主意,它似乎也有效:

// Make a composition with the video track.
AVMutableComposition* videoComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* videoCompositionTrack = [videoComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:[videoTrack timeRange] ofTrack:videoTrack atTime:CMTimeMake(0, 1) error:nil];

// Make a composition with the audio track.
AVMutableComposition* audioComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* audioCompositionTrack = [audioComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioCompositionTrack insertTimeRange:[audioTrack timeRange] ofTrack:audioTrack atTime:CMTimeMake(0, 1) error:nil];

现在我详细介绍如何处理每个轨道 . 我非常有信心,我有处理视频轨道的唯一方法,即为视频合成创建AVAssetReader,并添加使用视频合成轨道创建的AVAssetTrackReaderOutput . 通过保持对该轨道输出的引用,我可以调用它的 -copyNextSampleBuffer 方法来获取将视频输出泵入OpenGL ES纹理所需的信息 . 这本身就足够好了:

// Create Asset Reader and Output for the video track.
NSDictionary* settings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];
_assetReader = [[AVAssetReader assetReaderWithAsset:vComposition error:nil] retain];
_videoTrackOutput = [[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:vCompositionTrack outputSettings:settings] retain];
[_assetReader addOutput:_videoTrackOutput];
[_assetReader startReading];

似乎破坏了整个事情的是试图以任何方式播放音频 . 我不确定采用哪种方法来保留剩余的音轨 . 只是坚持AVFoundation的领域,我看到两种可能的方法 . 第一种是使用AVPlayer播放音频合成:

// Create a player for the audio.
AVPlayerItem* audioPlayerItem = [AVPlayerItem playerItemWithAsset:aComposition];
AVPlayer* audioPlayer = [[AVPlayer playerWithPlayerItem:audioPlayerItem] retain];
[audioPlayer play];

这是有效的,因为我可以听到所需的音频 . 不幸的是,创建此播放器可确保在调用 -copyNextSampleBuffer 时,视频合成的AVAssetReaderTrackOutput失败并出现含义模糊错误:

AVAssetReaderStatusFailed错误域= AVFoundationErrorDomain代码= -11800“操作无法完成”UserInfo = 0x456e50 {NSLocalizedFailureReason =发生未知错误(-12785),NSUnderlyingError = 0x486570“操作无法完成 . (OSStatus error -12785 . )“,NSLocalizedDescription =操作无法完成}

我对他们如何互相干扰感到困惑,但无论如何,这种方法似乎都是死路一条 .

我考虑用于音频播放的另一个选项是AVAudioPlayer类,但是我无法使用AVAsset作为起点 . 我尝试将其 -initWithData:error: 方法与通过聚合CMSampleBufferRefs的内容而构建的NSData一起使用,该方法采用与我在视频轨道上使用的方法相同的方法,但似乎没有正确格式化 .

在这一点上,我觉得我在盲目地挥舞着,如果有人能告诉我这种方法是否可行,我会非常喜欢它 . 如果不是,我当然会欣赏一个可行的 .

1 回答

  • 3

    为每个轨道创建AVMutableCompositions(基本上是新的AVAssets)似乎是围绕着我,我只是在音轨上使用AVAssetReader . 此外,您的videoComposition似乎没有在任何地方使用,为什么要创建它?

    在任何情况下,要使任一解决方案正常工作,请将您的音频会话类别设置为 kAudioSessionCategory_MediaPlayback 并启用 kAudioSessionProperty_OverrideCategoryMixWithOthers .

    我从来没有找到任何解释为什么这是必要的文档 .

相关问题