最近做的app需要从iOS系统的音乐库里面拷贝选中的歌曲到APP的Documents目录下,在网上找了好久之后,终于找到两种方法,分别是可以导出成指定的格式和导出成Core Audio支持的caf格式,代码分别记录在下面
1,导出成caf格式,这种导出方式,文件名必须以.caf作为后缀,使用其他后缀会导出失败
- - (void) convertToCAF:(NSString *)filename (MPMediaItem *)song
- {
- NSURL *assetURL = [song valueForProperty:MPMediaItemPropertyAssetURL];
- AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
- NSError *assetError = nil;
- AVAssetReader *assetReader = [[AVAssetReader assetReaderWithAsset:songAsset
- error:&assetError]
- retain];
- if (assetError) {
- NSLog (@"error: %@", assetError);
- return;
- }
- AVAssetReaderOutput *assetReaderOutput = [[AVAssetReaderAudioMixOutput
- assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
- audioSettings: nil]
- retain];
- if (! [assetReader canAddOutput: assetReaderOutput]) {
- NSLog (@"can't add reader output... die!");
- return;
- }
- [assetReader addOutput: assetReaderOutput];
- NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
- NSString *exportPath = [[documentsDirectoryPath stringByAppendingPathComponent:filename] retain];
- if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) {
- [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
- }
- NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
- AVAssetWriter *assetWriter = [[AVAssetWriter assetWriterWithURL:exportURL
- fileType:AVFileTypeCoreAudioFormat
- error:&assetError]
- retain];
- if (assetError) {
- NSLog (@"error: %@", assetError);
- return;
- }
- AudioChannelLayout channelLayout;
- memset(&channelLayout, 0, sizeof(AudioChannelLayout));
- channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
- NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
- [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
- [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
- [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
- [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
- [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
- [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
- [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
- nil];
- AVAssetWriterInput *assetWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
- outputSettings:outputSettings]
- retain];
- if ([assetWriter canAddInput:assetWriterInput]) {
- [assetWriter addInput:assetWriterInput];
- } else {
- NSLog (@"can't add asset writer input... die!");
- return;
- }
- assetWriterInput.expectsMediaDataInRealTime = NO;
- [assetWriter startWriting];
- [assetReader startReading];
- AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
- CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
- [assetWriter startSessionAtSourceTime: startTime];
- __block UInt64 convertedByteCount = 0;
- dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
- [assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue
- usingBlock: ^
- {
- // NSLog (@"top of block");
- while (assetWriterInput.readyForMoreMediaData) {
- CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
- if (nextBuffer) {
- // append buffer
- [assetWriterInput appendSampleBuffer: nextBuffer];
- // NSLog (@"appended a buffer (%d bytes)",
- // CMSampleBufferGetTotalSampleSize (nextBuffer));
- convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
- } else {
- // done!
- [assetWriterInput markAsFinished];
- [assetWriter finishWriting];
- [assetReader cancelReading];
- NSDictionary *outputFileAttributes = [[NSFileManager defaultManager]
- attributesOfItemAtPath:exportPath
- error:nil];
- NSLog (@"done. file size is %lld",
- [outputFileAttributes fileSize]);
- // release a lot of stuff
- [assetReader release];
- [assetReaderOutput release];
- [assetWriter release];
- [assetWriterInput release];
- [exportPath release];
- break;
- }
- }
- }];
- }
2,导出成mp3或者其他格式
- - (void) convertToMp3: (MPMediaItem *)song
- {
- NSURL *url = [song valueForProperty:MPMediaItemPropertyAssetURL];
- AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil];
- NSFileManager *fileManager = [NSFileManager defaultManager];
- NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
- NSLog (@"compatible presets for songAsset: %@",[AVAssetExportSession exportPresetsCompatibleWithAsset:songAsset]);
- NSArray *ar = [AVAssetExportSession exportPresetsCompatibleWithAsset: songAsset];
- NSLog(@"%@", ar);
- AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
- initWithAsset: songAsset
- presetName: AVAssetExportPresetAppleM4A];
- NSLog (@"created exporter. supportedFileTypes: %@", exporter.supportedFileTypes);
- exporter.outputFileType = @"com.apple.m4a-audio";
- NSString *exportFile = [documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.m4a",[song valueForProperty:MPMediaItemPropertyTitle]]];
- NSError *error1;
- if([fileManager fileExistsAtPath:exportFile])
- {
- [fileManager removeItemAtPath:exportFile error:&error1];
- }
- NSURL* exportURL = [[NSURL fileURLWithPath:exportFile] retain];
- exporter.outputURL = exportURL;
- // do the export
- [exporter exportAsynchronouslyWithCompletionHandler:^
- {
- NSData *data1 = [NSData dataWithContentsOfFile:exportFile];
- //NSLog(@"==================data1:%@",data1);
- int exportStatus = exporter.status;
- switch (exportStatus) {
- case AVAssetExportSessionStatusFailed: {
- // log error to text view
- NSError *exportError = exporter.error;
- NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
- break;
- }
- case AVAssetExportSessionStatusCompleted: {
- NSLog (@"AVAssetExportSessionStatusCompleted");
- break;
- }
- case AVAssetExportSessionStatusUnknown: {
- NSLog (@"AVAssetExportSessionStatusUnknown");
- break;
- }
- case AVAssetExportSessionStatusExporting: {
- NSLog (@"AVAssetExportSessionStatusExporting");
- break;
- }
- case AVAssetExportSessionStatusCancelled: {
- NSLog (@"AVAssetExportSessionStatusCancelled");
- break;
- }
- case AVAssetExportSessionStatusWaiting: {
- NSLog (@"AVAssetExportSessionStatusWaiting");
- break;
- }
- default:
- { NSLog (@"didn't get export status");
- break;
- }
- }
- }];
- }
- AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
- initWithAsset: songAsset
- presetName: AVAssetExportPresetPassthrough];