我是Objective-C的新手,在iPhone开发方面只有5个月的经验。
我需要什么:
我需要将两个或多个音频文件连接成一个,并将结果导出为aiff,mp3,caf或m4a格式。
例如:
第一个音频文件包含“您需要”,第二个“下载”和第三个“文档”
每个音频部分都取决于用户的操作。
我将非常感谢您提供一段代码。
答案 0 :(得分:24)
以下代码可用于合并音频文件。
输入文件:要在数组audioIds中提供的文件的ID。 例如。 audio1.mp3,audio2.mp3 ... audioN.mp3在文档文件夹中可用 输出文件:combined.m4a
- (BOOL) combineVoices {
NSError *error = nil;
BOOL ok = NO;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
CMTime nextClipStartTime = kCMTimeZero;
//Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
for (int i = 0; i< [self.audioIds count]; i++) {
int key = [[self.audioIds objectAtIndex:i] intValue];
NSString *audioFileName = [NSString stringWithFormat:@"audio%d", key];
//Build the filename with path
NSString *soundOne = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp3", audioFileName]];
//NSLog(@"voice file - %@",soundOne);
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
if ([tracks count] == 0)
return NO;
CMTimeRange timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [avAsset duration]);
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
ok = [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:&error];
if (!ok) {
NSLog(@"Current Video Track Error: %@",error);
}
nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration);
}
// create the export session
// no need for a retain here, the session will be retained by the
// completion handler since it is referenced there
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:@"combined.m4a"];
//NSLog(@"Output file path - %@",soundOneNew);
// configure export session output with all our parameters
exportSession.outputURL = [NSURL fileURLWithPath:soundOneNew]; // output path
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type
// perform the export
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status) {
NSLog(@"AVAssetExportSessionStatusCompleted");
} else if (AVAssetExportSessionStatusFailed == exportSession.status) {
// a failure may happen because of an event out of your control
// for example, an interruption like a phone call comming in
// make sure and handle this case appropriately
NSLog(@"AVAssetExportSessionStatusFailed");
} else {
NSLog(@"Export Session Status: %d", exportSession.status);
}
}];
return YES;
}
答案 1 :(得分:3)
您可以使用此方法将3种声音合并在一起。
- (BOOL) combineVoices1
{
NSError *error = nil;
BOOL ok = NO;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
CMTime nextClipStartTime = kCMTimeZero;
//Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne =[[NSBundle mainBundle]pathForResource:@"test1" ofType:@"caf"];
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.3];
NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:@"test" ofType:@"caf"];
NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack2 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack2 setPreferredVolume:1.0];
NSString *soundOne2 =[[NSBundle mainBundle]pathForResource:@"song" ofType:@"caf"];
NSURL *url2 = [NSURL fileURLWithPath:soundOne2];
AVAsset *avAsset2 = [AVURLAsset URLAssetWithURL:url2 options:nil];
NSArray *tracks2 = [avAsset2 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack2 = [[avAsset2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset2.duration) ofTrack:clipAudioTrack2 atTime:kCMTimeZero error:nil];
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:@"combined10.m4a"];
//NSLog(@"Output file path - %@",soundOneNew);
// configure export session output with all our parameters
exportSession.outputURL = [NSURL fileURLWithPath:soundOneNew]; // output path
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type
// perform the export
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status) {
NSLog(@"AVAssetExportSessionStatusCompleted");
} else if (AVAssetExportSessionStatusFailed == exportSession.status) {
// a failure may happen because of an event out of your control
// for example, an interruption like a phone call comming in
// make sure and handle this case appropriately
NSLog(@"AVAssetExportSessionStatusFailed");
} else {
NSLog(@"Export Session Status: %d", exportSession.status);
}
}];
return YES;
}
答案 2 :(得分:1)
你可能应该看一下这篇文章: Combine two audio files into one in objective c
答案类似于Dimitar的建议。但是你要记住的两个重要的事情是,首先 - 它只适用于mp3格式,其次你尝试连接的所有文件的比特率应该是相同的,否则只有你文件的一部分会在最终输出中发挥。它会在比特率变化的地方停止播放。
SSteve-像Wav文件这样的文件有自己的标题,如果你只是一个接一个地写一个文件,它会播放第一个文件然后停止播放,尽管文件信息显示更大的文件大小。这是因为我们没有将信息更新到第一个文件的标题中。
答案 3 :(得分:0)
你有没有试过这样的事情:
AudioFileCreateWithURL //to create the output file
For each input file:
AudioFileOpenURL //open file
repeat
AudioFileReadBytes //read from input file
AudioFileWriteBytes //write to output file
until eof(input file)
AudioFileClose //close input file
AudioFileClose //close output file
这可能要求输入文件格式相同,并以相同的格式创建输出文件。如果您需要转换格式,那么在创建输出文件后可能会做得更好。
答案 4 :(得分:0)
我从AVMutableCompositionTrack中获取了两个不同的mp3文件。这两个mp3文件存储在同一个AVMutableComposition中。
当我按下按钮时,控制台将显示新mp3的路径。
-(IBAction)play
{
[self mixAudio];
}
-(void)mixAudio
{
CFAbsoluteTime currentTime=CFAbsoluteTimeGetCurrent();
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne =[[NSBundle mainBundle]pathForResource:@"KICK1" ofType:@"mp3"];
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack = [tracks objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:@"KICK2" ofType:@"mp3"];
NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack1 = [tracks1 objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset1.duration) ofTrack:clipAudioTrack1 atTime: kCMTimeZero error:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
NSString *strOutputFilePath = [libraryCachesDirectory stringByAppendingPathComponent:@"output.mov"];
NSString *requiredOutputPath = [libraryCachesDirectory stringByAppendingPathComponent:@"output.m4a"];
NSURL *audioFileOutput = [NSURL fileURLWithPath:requiredOutputPath];
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAssetExportSession *exporter=[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
exporter.outputURL=audioFileOutput;
exporter.outputFileType=AVFileTypeAppleM4A;
[exporter exportAsynchronouslyWithCompletionHandler:^{
NSLog(@" OUtput path is \n %@", requiredOutputPath);
NSFileManager * fm = [[NSFileManager alloc] init];
[fm moveItemAtPath:strOutputFilePath toPath:requiredOutputPath error:nil];
NSLog(@" OUtput path is \n %@", requiredOutputPath);
NSLog(@"export complete: %lf",CFAbsoluteTimeGetCurrent()-currentTime);
NSError *error;
audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:audioFileOutput error:&error];
audioPlayer.numberOfLoops=0;
[audioPlayer play];
}];
}
答案 5 :(得分:0)
实现aac的多种组合的最简单方法:
- (NSString *)concatenatedAACVoicesPath{
NSMutableData *concatenatedData = [[NSMutableData alloc] init];
NSArray *aacPathArr = [self queryAAC];
for (NSString *path in aacPathArr) {
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
[concatenatedData appendData: data];
}
NSString *fileNamePath = [NSString stringWithFormat:@"%@/%@.aac",[NSString createPath:currRecordDocName],currRecordDocName];
[concatenatedData writeToFile:fileNamePath atomically:YES];
return fileNamePath;
}
答案 6 :(得分:-1)
我有一个想法,不确定它会起作用。尝试从这3个文件中获取NSData,将数据附加到另一个NSData然后写入。类似的东西:
NSMutableData *concatenatedData = [NSMutableData alloc] init];
NSData *data1 = [[NSData alloc] initWithContentsOfFile:(NSString *)path];
NSData *data2 = [[NSData alloc] initWithContentsOfFile:(NSString *)path];
NSData *data3 = [[NSData alloc] initWithContentsOfFile:(NSString *)path];
[concatenatedData appendData: data1];
[concatenatedData appendData: data2];
[concatenatedData appendData: data3];
[concatenatedData writeToFile:@"/path/to/concatenatedData.mp3" atomically:YES];
这是一个理论,我不确定它会起作用:),如果我用十六进制编辑器打开一个mp3 - 复制所有内容并将其粘贴到最后 - 它实际上有效 - 然后我有两次相同的声音。请尝试一下,如果有效,请告诉我们。