insertTimeRange:ofTrack:atTime:error: (class AVMutableCompositionTrack) fails on iPhone
insertTimeRange:ofTrack:atTime:error: (class AVMutableCompositionTrack) fails on iPhone
insertTimeRange:ofTrack:atTime:error: of class AVMutableCompositionTrack 返回 NO 并且在 iPhone(但不是模拟器)上返回错误 "The operation could not be completed"。错误消息没有帮助,我很难想出错误的原因,更不用说解决方法了。任何帮助将不胜感激。
在下面的示例代码中,我所做的只是尝试将音频剪辑添加到 AVMutableCompositionTrack。这是代码中发生的事情:
AVMutableComposition 和 AVMutableCompositionTrack 对象在 init 中创建。
class方法addPhrase:atTime:调用添加音频剪辑到合成轨道
实际插入的函数是addAudioClip:atTime:.
辅助函数audioClipWithName:ofType将请求的音频文件加载到 AVAssetTrack 中。
--> NSLOG 输出:
insertTimeRange atTime=0.0 range=(0.0, 2.1) compositionTrack=
- - - - - 错误! Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=操作无法完成,NSUnderlyingError=0x16fc1c90 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=发生未知错误(-12780)}
--> 示例代码:
@interface MyAudioPlayer()
@property (strong, nonatomic) AVMutableComposition *composition;
@property (strong, nonatomic) AVMutableCompositionTrack *compositionTrack;
@end
@implementation MyAudioPlayer
- (id) init
{
self = [super init];
if (self != nil) {
self.composition = [AVMutableComposition composition];
self.compositionTrack = [self.composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
}
return self;
}
// Add the phrase into compositionAudioTrack at the given time.
- (void) addPhrase:(NSString *)phrase atTime:(CMTime)atTime
{
// Add the phrase to the audio.
AVAssetTrack *audioClip = [self audioClipWithName:phrase ofType:@"mp3"];
// Add the phrase to the audio track.
[self addAudioClip:audioClip atTime];
}
// Add the given audio clip to the composed audio at the given time.
- (void) addAudioClip:(AVAssetTrack *)audioClip atTime:(CMTime)atTime
{
NSError *error = [[NSError alloc] init];
CMTimeRange audioClipRange = CMTimeRangeMake(kCMTimeZero, audioClip.timeRange.duration);
BOOL success = [self.compositionTrack insertTimeRange:audioClipRange ofTrack:audioClip atTime:atTime error:&error];
NSLog(@"insertTimeRange atTime=%.1f range=(%.1f, %.1f) compositionTrack=%@\n", CMTimeGetSeconds(atTime), CMTimeGetSeconds(audioClipRange.start), CMTimeGetSeconds(audioClipRange.duration), self.compositionTrack);
if (!success) {
NSLog(@"----------ERROR! %@", error);
}
}
// Return an audio clip with the given name and type.
- (AVAssetTrack *) audioClipWithName:(NSString *)name ofType:(NSString *)type
{
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:name ofType:type];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
AVAssetTrack *audioClip = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
return audioClip;
}
@end
你的问题出在
- (AVAssetTrack *) audioClipWithName:(NSString *)name ofType:(NSString *)type;
它让轨道的所有者 AVAsset
超出范围并被释放,使轨道处于不良状态。
确保 AVAsset
被引用(至少)直到您调用 insertTimeRange
。实际上,这意味着您应该将 AVAsset
及其 AVAssetTrack
一起传递。
insertTimeRange:ofTrack:atTime:error: of class AVMutableCompositionTrack 返回 NO 并且在 iPhone(但不是模拟器)上返回错误 "The operation could not be completed"。错误消息没有帮助,我很难想出错误的原因,更不用说解决方法了。任何帮助将不胜感激。
在下面的示例代码中,我所做的只是尝试将音频剪辑添加到 AVMutableCompositionTrack。这是代码中发生的事情:
AVMutableComposition 和 AVMutableCompositionTrack 对象在 init 中创建。
class方法addPhrase:atTime:调用添加音频剪辑到合成轨道
实际插入的函数是addAudioClip:atTime:.
辅助函数audioClipWithName:ofType将请求的音频文件加载到 AVAssetTrack 中。
--> NSLOG 输出:
insertTimeRange atTime=0.0 range=(0.0, 2.1) compositionTrack= - - - - - 错误! Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=操作无法完成,NSUnderlyingError=0x16fc1c90 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=发生未知错误(-12780)}
--> 示例代码:
@interface MyAudioPlayer()
@property (strong, nonatomic) AVMutableComposition *composition;
@property (strong, nonatomic) AVMutableCompositionTrack *compositionTrack;
@end
@implementation MyAudioPlayer
- (id) init
{
self = [super init];
if (self != nil) {
self.composition = [AVMutableComposition composition];
self.compositionTrack = [self.composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
}
return self;
}
// Add the phrase into compositionAudioTrack at the given time.
- (void) addPhrase:(NSString *)phrase atTime:(CMTime)atTime
{
// Add the phrase to the audio.
AVAssetTrack *audioClip = [self audioClipWithName:phrase ofType:@"mp3"];
// Add the phrase to the audio track.
[self addAudioClip:audioClip atTime];
}
// Add the given audio clip to the composed audio at the given time.
- (void) addAudioClip:(AVAssetTrack *)audioClip atTime:(CMTime)atTime
{
NSError *error = [[NSError alloc] init];
CMTimeRange audioClipRange = CMTimeRangeMake(kCMTimeZero, audioClip.timeRange.duration);
BOOL success = [self.compositionTrack insertTimeRange:audioClipRange ofTrack:audioClip atTime:atTime error:&error];
NSLog(@"insertTimeRange atTime=%.1f range=(%.1f, %.1f) compositionTrack=%@\n", CMTimeGetSeconds(atTime), CMTimeGetSeconds(audioClipRange.start), CMTimeGetSeconds(audioClipRange.duration), self.compositionTrack);
if (!success) {
NSLog(@"----------ERROR! %@", error);
}
}
// Return an audio clip with the given name and type.
- (AVAssetTrack *) audioClipWithName:(NSString *)name ofType:(NSString *)type
{
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:name ofType:type];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
AVAssetTrack *audioClip = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
return audioClip;
}
@end
你的问题出在
- (AVAssetTrack *) audioClipWithName:(NSString *)name ofType:(NSString *)type;
它让轨道的所有者 AVAsset
超出范围并被释放,使轨道处于不良状态。
确保 AVAsset
被引用(至少)直到您调用 insertTimeRange
。实际上,这意味着您应该将 AVAsset
及其 AVAssetTrack
一起传递。