gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-30 03:53:40 26 4
gpt4 key购买 nike

这是我的目标:我想将 .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];

这行得通,因为我可以听到所需的音频。不幸的是,创建此播放器会保证视频组合的 AVAssetReaderTrackOutput 在调用 -copyNextSampleBuffer 时失败并出现神秘错误:

AVAssetReaderStatusFailed

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x456e50 {NSLocalizedFailureReason=An unknown error occurred (-12785), NSUnderlyingError=0x486570 "The operation couldn’t be completed. (OSStatus error -12785.)", NSLocalizedDescription=The operation could not be completed}

我对它们如何相互干扰感到困惑,但无论如何,这种方法似乎是死胡同。

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

在这一点上,我觉得自己在盲目地四处乱窜,如果有人能告诉我这种方法是否可行,我会非常高兴。如果不是,我当然会感激一个可行的。

最佳答案

为每个音轨创建 AVMutableCompositions(基本上是新的 AVAssets)对我来说似乎是迂回的,我只是在音轨上使用 AVAssetReader。此外,您的 videoComposition 似乎没有在任何地方使用,那么为什么要创建它?

在任何情况下,要使任一解决方案都起作用,请将 Audio Session 类别设置为 kAudioSessionCategory_MediaPlayback 并启用 kAudioSessionProperty_OverrideCategoryMixWithOthers

我从未找到任何文档来解释为什么这是必要的。

关于objective-c - 如何独立处理 AVURLAsset 的单独轨道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6038951/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com