Export session error - When using AVAudioPlayer for mp3 files - ios

In my app I can access the device music library, and when you select a song, it loads, however, it no longer works, and I am constantly met with the error 'export session error'
Then the app just hangs with the spinning loading bar forever until I close the app.
Select music AssetUrl = ipod-library://item/item.mp3?id=2023536838012570661
export session error
The files that I believe are troublesome are .mp3 files;
If I use .m4a files, it seems to work fine - so is there a way to block mp3 files from appearing in the mediapicker? Or at least an alert to show the user they can't use them if they try to select an mp3 file?
Here is the code;
Picker code;
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection
{
dispatch_async(dispatch_get_main_queue(), ^{
// Dismiss the media item picker.
[self dismissViewControllerAnimated:YES completion:nil];
if ([mediaItemCollection count] < 1) {
return;
}
[selectedItem release];
selectedItem = [[[mediaItemCollection items] objectAtIndex:0] retain];
NSURL* filePath = [selectedItem valueForProperty: MPMediaItemPropertyAssetURL];
NSLog(#"Select music AssetUrl = %#", filePath);
});
}
- (void)exportAssetAsSourceFormat:(MPMediaItem *)item {
dispatch_async(dispatch_get_main_queue(), ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL]; //MPMediaItemPropertyAssetURL
if (assetURL == nil)
{
NSLog(#"assetURL is null");
[pool release];
return;
}
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
// JP
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:songAsset
presetName:AVAssetExportPresetPassthrough];
NSArray *tracks = [songAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *track = [tracks objectAtIndex:0];
id desc = [track.formatDescriptions objectAtIndex:0];
const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
FourCharCode formatID = audioDesc->mFormatID;
NSString *fileType = nil;
NSString *ex = nil;
switch (formatID) {
case kAudioFormatLinearPCM:
{
UInt32 flags = audioDesc->mFormatFlags;
if (flags & kAudioFormatFlagIsBigEndian) {
fileType = #"public.aiff-audio";
ex = #"aif";
} else {
fileType = #"com.microsoft.waveform-audio";
ex = #"wav";
}
}
break;
case kAudioFormatMPEGLayer3:
fileType = #"com.apple.quicktime-movie";
ex = #"mp3";
break;
case kAudioFormatMPEG4AAC:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
case kAudioFormatAppleLossless:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
default:
break;
}
exportSession.outputFileType = fileType;
NSString *exportPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[EXPORT_NAME stringByAppendingPathExtension:ex]] retain];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) {
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
exportSession.outputURL = [NSURL fileURLWithPath:exportPath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSLog(#"export session completed");
//return YES;
[self performSelectorOnMainThread:#selector(gotoMainView:)
withObject:[EXPORT_NAME stringByAppendingPathExtension:ex]
waitUntilDone:NO];
} else {
NSLog(#"export session error");
//return NO;
}
[exportSession release];
}];
[pool release];
});
}

Related

IOS:MPMediaItems raw song converting to NSData

I used this code It's fine,but after converted the song to data and when i'm trying to send that converted data to MFMailComposeViewController or MFMessageComposeViewController, It's coming in Document format some times but failed to get the mp3 format.When I'm playing the song,which we sent to the MFmailComposeViewcontroller or MFMessageComposeViewController , the songs which converted correctly was playing correct but some is converting to document format . How to overcome this. Please suggest me .
SelectedAlbumUrl = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongUrl"];
This method calling like this.
[self mediaItemToData:[arr_tablVArray objectAtIndex:indexPath.row]];
-(void)mediaItemToData : (MPMediaItem * ) curItem
{
NSURL *url = SelectedAlbumUrl;
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
presetName:AVAssetExportPresetAppleM4A];
exporter.outputFileType = #"com.apple.m4a-audio";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * myDocumentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
[[NSDate date] timeIntervalSince1970];
NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
NSString *intervalSeconds = [NSString stringWithFormat:#"%0.0f",seconds];
NSString * fileName = [NSString stringWithFormat:#"%#.caf",intervalSeconds];
NSLog(#"the file name is --->%#",fileName);
NSString *exportFile = [myDocumentsDirectory stringByAppendingPathComponent:fileName];
exportURL = [NSURL fileURLWithPath:exportFile];
exporter.outputURL = exportURL;
// (completion handler block omitted)
[exporter exportAsynchronouslyWithCompletionHandler:
^{
int exportStatus = exporter.status;
switch (exportStatus)
{
case AVAssetExportSessionStatusFailed:
{
NSError *exportError = exporter.error;
NSLog (#"AVAssetExportSessionStatusFailed: %#", exportError);
break;
}
case AVAssetExportSessionStatusCompleted:
{
NSLog (#"AVAssetExportSessionStatusCompleted");
NSData *data = [NSData dataWithContentsOfFile: [myDocumentsDirectory
stringByAppendingPathComponent:fileName]];
data = nil;
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;
}
}
}];
}
After that url converting to NSData sending through email,message and airdrop like this
NSData *Data = [NSData dataWithContentsOfURL:exportURL];
[composer addAttachmentData:Data mimeType:#".caf" fileName:str_songtitle];
Try this
- (void)addAttachmentData:(NSData*)attachment mimeType:(NSString*)mimeType fileName:(NSString*)filename
with mimeType = audio/mpeg

Why don't I get video when exporting a movie using AVAssetExportSession?

It is trimming the audio, but the video is blank.
This is the function that initiates trimming
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor blackColor];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(finishedTrimming:)
name:#"videoFinishedTrimming"
object:nil];
NSURL *furl = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:#"capture0.mp4"]];
//[self playVideoWithURL:furl]; //Play original video
//Play trimmed video
CMTime startTrim = CMTimeMake(0, 1);
CMTime endTrim = CMTimeMake(2,1);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTrim, endTrim);
[ProcessingHelper trimAssetWithURL:furl andRange:exportTimeRange];
}
This is the function that exports and trims the video.
+(void)trimAssetWithURL:(NSURL *)urlIn andRange:(CMTimeRange)timeRangeIn
{
AVAsset *videoAsset = [AVAsset assetWithURL:urlIn];
//Creates the session with the videoasset
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:AVAssetExportPresetHighestQuality];
//Creates the path to export to - Saving to temporary directory
NSString* filename = [NSString stringWithFormat:#"TrimmedCapture%d.mp4", 0];
NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
//Checks if there is already a file at the output URL. session will not overwrite previous data
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSLog(#"Removing item at path: %#", path);
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}
//Set the output url
exportSession.outputURL = [NSURL fileURLWithPath:path];
//Set the output file type
exportSession.outputFileType = AVFileTypeMPEG4; //AVFileTypeAC3; // AVFileTypeMPEGLayer3; // AVFileTypeWAVE; // AVFileTypeQuickTimeMovie;
exportSession.timeRange = timeRangeIn;
exportSession.metadata = nil;
//Exports!
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:{
NSLog(#"Export Complete");
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:exportSession.outputURL, #"outputURL", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"videoFinishedTrimming" object:self userInfo:options];
break;
}
case AVAssetExportSessionStatusFailed:
NSLog(#"Export Error: %#", [exportSession.error description]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export Cancelled");
break;
default:
break;
}
}];
exportSession = nil;
}
This is the function that initiates the playing of the video
-(void)finishedTrimming:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
NSURL *outputURL = [userInfo objectForKey:#"outputURL"];
[self playVideoWithURL:outputURL];
}
This is the function that plays the video
-(void)playVideoWithURL:(NSURL *)furl
{
NSData *movieData;
NSError *dataReadingError = nil;
movieData = [NSData dataWithContentsOfURL: furl options:NSDataReadingMapped error:&dataReadingError];
if(movieData != nil)
NSLog(#"Successfully loaded the data.");
else
NSLog(#"Failed to load the data with error = %#", dataReadingError);
//AVPlayer
self.avPlayer = [AVPlayer playerWithURL:furl];
AVPlayerLayer *avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
avPlayerLayer.frame = self.vPlayBackMovie.bounds;
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
avPlayerLayer.needsDisplayOnBoundsChange = YES;
[self.vPlayBackMovie.layer addSublayer:avPlayerLayer];
self.vPlayBackMovie.layer.needsDisplayOnBoundsChange = YES;
[self.avPlayer play];
}
Thanks ChrisH, you were right! The Export was taking place on another thread so in the handler I need to get the main queue...
I needed to get the main thread after
case AVAssetExportSessionStatusCompleted:{
dispatch_async(dispatch_get_main_queue(), ^{
//post the notification!
});
break;
}

Cutting video on iPhone

I have a video file from the device camera -- stored as /private/var/mobile/Media/DCIM/100APPLE/IMG_0203.MOV, for example, and I need to cut the first 10 seconds of this video. What API or libraries I can use?
I found solution with standard API: AVAssetExportSession
- (void)getTrimmedVideoForFile:(NSString *)filePath withInfo:(NSArray *)info
{
//[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:filePath] options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSAllDomainsMask, YES);
// NSString *outputURL = paths[0];
NSFileManager *manager = [NSFileManager defaultManager];
// [manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil];
// outputURL = [outputURL stringByAppendingPathComponent:#"output.mp4"];
NSString *outputURL = [NSString stringWithFormat:#"/tmp/%#.mp4", [info objectAtIndex:2]];
NSLog(#"OUTPUT: %#", outputURL);
// Remove Existing File
// [manager removeItemAtPath:outputURL error:nil];
if (![manager fileExistsAtPath:outputURL]) {
exportSession.outputURL = [NSURL fileURLWithPath:outputURL];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime start = kCMTimeZero;
CMTime duration = kCMTimeIndefinite;
if ([[NSString stringWithFormat:#"%#", [info objectAtIndex:3]] floatValue] > 20.0) {
start = CMTimeMakeWithSeconds(1.0, 600);
duration = CMTimeMakeWithSeconds(10.0, 600);
}
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:
NSLog(#"Export Complete %d %#", exportSession.status, exportSession.error);
[self sendVideoPreview:info];
break;
case AVAssetExportSessionStatusFailed:
NSLog(#"Failed:%#",exportSession.error);
// [self addToDelayed:info withAction:#"add"];
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Canceled:%#",exportSession.error);
// [self addToDelayed:info withAction:#"add"];
break;
default:
break;
}
}];
} else {
[self sendVideoPreview:info];
}

Trim video without displaying UIVideoEditorController?

Currently I'm working on a application which deals with the videos.
In my application user can trim the video, I have a custom control for selecting the start time and end time. I need to trim the video by these two values. I tried with UIVideoEditorController like follows.
UIVideoEditorController* videoEditor = [[[UIVideoEditorController alloc] init] autorelease];
videoEditor.delegate = self;
NSString* videoPath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"MOV"];
if ( [UIVideoEditorController canEditVideoAtPath:videoPath] )
{
videoEditor.videoPath = videoPath;
[self presentModalViewController:videoEditor animated:YES];
}
else
{
NSLog( #"can't edit video at %#", videoPath );
}
But the issue is the above code will display apple's video editor control and user can do some operations on that view. I don't want to display this view, because I have already displayed the video on MPMoviePlayer and received the user input (start time and end time) for trimming the video on a custom control.
How can I trim a video without displaying UIVideoEditorController ?
Finally I found the solution.
We can use AVAssetExportSession for trimming video without displaying UIVideoEditorController.
My code is like:
- (void)splitVideo:(NSString *)outputURL
{
#try
{
NSString *videoBundleURL = [[NSBundle mainBundle] pathForResource:#"Video_Album" ofType:#"mp4"];
AVAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:videoBundleURL] options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality])
{
[self trimVideo:outputURL assetObject:asset];
}
videoBundleURL = nil;
[asset release];
asset = nil;
compatiblePresets = nil;
}
#catch (NSException * e)
{
NSLog(#"Exception Name:%# Reason:%#",[e name],[e reason]);
}
}
This method trims the video
- (void)trimVideo:(NSString *)outputURL assetObject:(AVAsset *)asset
{
#try
{
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
exportSession.outputURL = [NSURL fileURLWithPath:outputURL];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime start = CMTimeMakeWithSeconds(splitedDetails.startTime, 1);
CMTime duration = CMTimeMakeWithSeconds((splitedDetails.stopTime - splitedDetails.startTime), 1);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[self checkExportSessionStatus:exportSession];
[exportSession release];
exportSession = nil;
}
#catch (NSException * e)
{
NSLog(#"Exception Name:%# Reason:%#",[e name],[e reason]);
}
}
This method checks the status of trimming:
- (void)checkExportSessionStatus:(AVAssetExportSession *)exportSession
{
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
{
switch ([exportSession status])
{
case AVAssetExportSessionStatusCompleted:
NSLog(#"Export Completed");
break;
case AVAssetExportSessionStatusFailed:
NSLog(#"Error in exporting");
break;
default:
break;
}
}];
}
I'm calling the splitVideo method from the export button action method and passes the output URL as argument.
We can import AVFoundation/AVFoundation.h
-(BOOL)trimVideofile
{
float videoStartTime;//define start time of video
float videoEndTime;//define end time of video
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd_HH-mm-ss"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:#"Caches"];
NSString *OutputFilePath = [libraryCachesDirectory stringByAppendingFormat:#"/output_%#.mov", [dateFormatter stringFromDate:[NSDate date]]];
NSURL *videoFileOutput = [NSURL fileURLWithPath:OutputFilePath];
NSURL *videoFileInput;//<Path of orignal Video file>
if (!videoFileInput || !videoFileOutput)
{
return NO;
}
[[NSFileManager defaultManager] removeItemAtURL:videoFileOutput error:NULL];
AVAsset *asset = [AVAsset assetWithURL:videoFileInput];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
presetName:AVAssetExportPresetLowQuality];
if (exportSession == nil)
{
return NO;
}
CMTime startTime = CMTimeMake((int)(floor(videoStartTime * 100)), 100);
CMTime stopTime = CMTimeMake((int)(ceil(videoEndTime * 100)), 100);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);
exportSession.outputURL = videoFileOutput;
exportSession.timeRange = exportTimeRange;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(#"Export OK");
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
}
}];
return YES;
}

Application crashed while importing songs from Ipod library in iPhone for iOs 5.0

Hello i am using below framworks,
#import <MediaPlayer/MediaPlayer.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
In one of button event i have implemented below code to open Library.
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
mediaPicker.delegate = self;
mediaPicker.allowsPickingMultipleItems = YES; // this is the default
[self presentModalViewController:mediaPicker animated:YES];
[mediaPicker release];
And in delegate methods of MPMediaPickerController implemented code as below
#pragma mark MPMediaPickerController delegate methods
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
// We need to dismiss the picker
[self dismissModalViewControllerAnimated:YES];
// Assign the selected item(s) to the music player and start playback.
counterIpod = [mediaItemCollection.items count];
totalcollection = counterIpod;
if (totalcollection > 10) {
NSString *str = [NSString stringWithFormat:#"App Only supports importing 10 songs at a time"];
UIAlertView *connectionAlert = [[UIAlertView alloc] initWithTitle:#"Message !" message:str delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[connectionAlert show];
[connectionAlert release];
}
else {
[self performSelector:#selector(saveMediaItem:) withObject:mediaItemCollection afterDelay:0.1];
//[self saveMediaItem:mediaItemCollection];
//[self showLoadingView];
}
}
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
// User did not select anything
// We need to dismiss the picker
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark Sace Item Collection to documentsDirectory
-(void)saveMediaItem:(MPMediaItemCollection *)mediaItemCollection {
for (int i = 0; i < [mediaItemCollection.items count]; i++) {
[self exportAssetAsSourceFormat:[[mediaItemCollection items] objectAtIndex:i]];
NSLog(#"for loop : %d", i);
}
NSArray *itemsArray1 = appDelegate.mediaItemCollection1.items;
MPMediaItemCollection *mediaItemCollection2;
if ([itemsArray1 count] != 0) {
mediaItemCollection2 = [self collectionByAppendingCollection:mediaItemCollection];
}
else {
mediaItemCollection2 = mediaItemCollection;
}
[self saveMediaItemAfterDeletting:mediaItemCollection2];
}
-(void)saveMediaItemAfterDeletting:(MPMediaItemCollection *)mediaItemCollection {
NSMutableData* data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:mediaItemCollection forKey:#"my_playlist"];
[archiver finishEncoding];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/playlist.data", documentsDirectory];
NSLog(#"file path = %#", filePath);
[data writeToFile:filePath atomically:YES];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
NSLog(#"file exists : ===========>>>>>>>>>>>");
} else {
NSLog(#"file doesn't exist");
}
//NSLog(#"archiving playlist success = %d", success);
[archiver release];
[data release];
[self UpdateMediaCollection];
}
-(NSString*) getExtension:(MPMediaItem *)item {
// [self showLoadingView];
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
// JP
// AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
// initWithAsset:songAsset
// presetName:AVAssetExportPresetPassthrough];
NSArray *tracks = [songAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *track = [tracks objectAtIndex:0];
id desc = [track.formatDescriptions objectAtIndex:0];
const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
FourCharCode formatID = audioDesc->mFormatID;
//exportAudioMix.inputParameters = [NSArray arrayWithObject:exportAudioMixInputParameters];
//exportSession.audioMix = exportAudioMix;
NSString *fileType = nil;
NSString *ex = nil;
switch (formatID) {
case kAudioFormatLinearPCM:
{
UInt32 flags = audioDesc->mFormatFlags;
if (flags & kAudioFormatFlagIsBigEndian) {
fileType = #"public.aiff-audio";
ex = #"aif";
} else {
fileType = #"com.microsoft.waveform-audio";
ex = #"wav";
}
}
break;
case kAudioFormatMPEGLayer3:
fileType = #"com.apple.quicktime-movie";
ex = #"mp3";
break;
case kAudioFormatMPEG4AAC:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
case kAudioFormatAppleLossless:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
default:
break;
}
return ex;
}
#pragma mark Covert Item separate item collection and store songs into directory
- (void)exportAssetAsSourceFormat:(MPMediaItem *)item {
// [self showLoadingView];
NSLog(#"export asset called");
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSLog(#"\n>>>> assetURL : %#",[assetURL absoluteString]);
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
// JP
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:songAsset
presetName:AVAssetExportPresetPassthrough];
NSArray *tracks = [songAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *track = [tracks objectAtIndex:0];
id desc = [track.formatDescriptions objectAtIndex:0];
const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
FourCharCode formatID = audioDesc->mFormatID;
//exportAudioMix.inputParameters = [NSArray arrayWithObject:exportAudioMixInputParameters];
//exportSession.audioMix = exportAudioMix;
NSString *fileType = nil;
NSString *ex = nil;
switch (formatID) {
case kAudioFormatLinearPCM:
{
UInt32 flags = audioDesc->mFormatFlags;
if (flags & kAudioFormatFlagIsBigEndian) {
fileType = #"public.aiff-audio";
ex = #"aif";
} else {
fileType = #"com.microsoft.waveform-audio";
ex = #"wav";
}
}
break;
case kAudioFormatMPEGLayer3:
fileType = #"com.apple.quicktime-movie";
ex = #"mp3";
break;
case kAudioFormatMPEG4AAC:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
case kAudioFormatAppleLossless:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
default:
break;
}
exportSession.outputFileType = fileType;
NSString *fileName = nil;
fileName = [NSString stringWithString:[item valueForProperty:MPMediaItemPropertyTitle]];
fileName = [[fileName stringByAppendingString:#"-"] stringByAppendingString:[item valueForProperty:MPMediaItemPropertyArtist]];
NSArray *fileNameArray = nil;
fileNameArray = [fileName componentsSeparatedByString:#" "];
fileName = [fileNameArray componentsJoinedByString:#""];
NSLog(#">>>>> fileName = %#", fileName);
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [[docDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:ex];
NSLog(#"filePath = %#", filePath);
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
//NSLog(#"file exist::::::::::==============>>>>>>>>>>>>>>>>>");
counterIpod--;
if(counterIpod == 0) {
//[self showAlertView];
//[self hideLoadingView];
}
NSString *str = [NSString stringWithFormat:#"Loading %d of %d Beats", totalcollection - counterIpod ,totalcollection];
[lbl performSelectorOnMainThread:#selector(setText:) withObject:str waitUntilDone:NO];
//NSLog(#"loading string : %#", str);
return;
}
//NSLog(#"file not exist ===========>>>>>>>>>");
// -------------------------------------
int fileNumber = 0;
NSString *fileNumberString = nil;
NSString *fileNameWithNumber = nil;
while ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
fileNumber++;
fileNumberString = [NSString stringWithFormat:#"-%02d", fileNumber];
fileNameWithNumber = [fileName stringByAppendingString:fileNumberString];
filePath = [[docDir stringByAppendingPathComponent:fileNameWithNumber] stringByAppendingPathExtension:ex];
//NSLog(#"filePath = %#", filePath);
}
// -------------------------------------
myDeleteFile(filePath);
exportSession.outputURL = [NSURL fileURLWithPath:filePath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSLog(#"export session completed");
counterIpod--;
NSString *str = [NSString stringWithFormat:#"Loading %d of %d Beats", totalcollection - counterIpod ,totalcollection];
//[self performSelector:#selector(setLabelText:) withObject:str afterDelay:0.02];
[lbl performSelectorOnMainThread:#selector(setText:) withObject:str waitUntilDone:NO];
NSLog(#"loading string : %#", str);
if(counterIpod == 0) {
//[self showAlertView];
//[self hideLoadingView];
}
} else {
NSLog(#"export session error");
counterIpod--;
NSString *str = [NSString stringWithFormat:#"Loading %d of %d Beats", totalcollection - counterIpod ,totalcollection];
[lbl performSelectorOnMainThread:#selector(setText:) withObject:str waitUntilDone:NO];
//return NO;
if(counterIpod == 0) {
//[self showAlertView];
//[self hideLoadingView];
}
}
[exportSession release];
}];
//[appDelegate hideLoadingView];
}
#pragma mark method to delete file from document directory
void myDeleteFile (NSString* path) {
// NSLog(#"file path delete file :::::::::: %#", path);
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSError *deleteErr = nil;
[[NSFileManager defaultManager] removeItemAtPath:path error:&deleteErr];
if (deleteErr) {
NSLog (#"Can't delete %#: %#", path, deleteErr);
}
}
}
Above code work without any error on iOS 4.0 or prior version but for iOS 5.0 is crashes on device, I can't resolve these issues since last 15 days.
Thanks in advance for Help.
I have solved this issues,
just comment out this line
fileName = [[fileName stringByAppendingString:#"-"] stringByAppendingString:[item valueForProperty:MPMediaItemPropertyArtist]];
because for some songs there is null artist so it's crash...................
This is because you are using some songs has artist name while some with blank artist name, so you are trying to append blank name in string that's why app going to crash.
Hope you unserstand what i say...

Resources