【发布时间】:2015-03-19 14:46:07
【问题描述】:
我正在尝试使用 AVAsset 和 AVAssetWriter 在 iOS 中反转音频。 以下代码有效,但输出文件比输入文件短。 例如,输入文件的持续时间为 1:59,但输出的音频内容为 1:50。
- (void)reverse:(AVAsset *)asset
{
AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:asset error:nil];
AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
NSMutableDictionary* audioReadSettings = [NSMutableDictionary dictionary];
[audioReadSettings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM]
forKey:AVFormatIDKey];
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:audioReadSettings];
[reader addOutput:readerOutput];
[reader startReading];
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
[NSNumber numberWithInt:2], AVNumberOfChannelsKey,
[NSNumber numberWithInt:128000], AVEncoderBitRateKey,
[NSData data], AVChannelLayoutKey,
nil];
AVAssetWriterInput *writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio
outputSettings:outputSettings];
NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.m4a"];
NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
NSError *writerError = nil;
AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:exportURL
fileType:AVFileTypeAppleM4A
error:&writerError];
[writerInput setExpectsMediaDataInRealTime:NO];
[writer addInput:writerInput];
[writer startWriting];
[writer startSessionAtSourceTime:kCMTimeZero];
CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];
NSMutableArray *samples = [[NSMutableArray alloc] init];
while (sample != NULL) {
sample = [readerOutput copyNextSampleBuffer];
if (sample == NULL)
continue;
[samples addObject:(__bridge id)(sample)];
CFRelease(sample);
}
NSArray* reversedSamples = [[samples reverseObjectEnumerator] allObjects];
for (id reversedSample in reversedSamples) {
if (writerInput.readyForMoreMediaData) {
[writerInput appendSampleBuffer:(__bridge CMSampleBufferRef)(reversedSample)];
}
else {
[NSThread sleepForTimeInterval:0.05];
}
}
[writerInput markAsFinished];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
[writer finishWriting];
});
}
更新:
如果我直接在第一个 while 循环中编写样本 - 一切正常(即使有 writerInput.readyForMoreMediaData 检查)。在这种情况下,结果文件的持续时间与原始文件完全相同。但是,如果我从反转的NSArray 编写相同的样本 - 结果会更短。
【问题讨论】:
-
样品都在吗? IE。是按时间压缩或截断的音频(缺少样本)...在这两种情况下,输出都比输入短。
-
这真的有效吗?我正在尝试相同的代码,但使用视频,似乎时间是内置在 CMSampleBufferRef 中的。所以即使你以相反的顺序附加帧,它仍然可以正常播放。
-
它适用于 .m4a 音频
-
@sx00 你做了什么来解决这个问题?当我尝试这段代码时,我遇到了同样的问题。当声音反转时,它似乎正在跳过。就像您说的那样,如果我不反转它,那听起来就很好,但是当我反转数组时,它的声音就不对了。 NSArray* reversedSamples = [[samples reverseObjectEnumerator] allObjects];
标签: ios objective-c core-audio avassetwriter avasset