I am developing music application, in which I have need of storing converted song to "Document directory" for later usage. For some reason its not playing from stored directory url but I am not getting any error as well. I checked inside the directory and found the same stored song present inside it.
The same song url played successfully from Directory before.
My code to store song after conversion from mp3 to m4a.
{
NSURL *assetURL = [NSURL URLWithString:_assertURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
/* approach 1: export just the song itself
*/
AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
initWithAsset: songAsset
presetName: AVAssetExportPresetAppleM4A];
NSLog (@"created exporter. supportedFileTypes: %@", exporter.supportedFileTypes);
exporter.outputFileType = @"com.apple.m4a-audio";
NSString *exportFile = [myDocumentsM4aDirectory() stringByAppendingPathComponent: [NSString stringWithFormat:@"%@.m4a",_title]];
// end of approach 1
// set up export (hang on to exportURL so convert to PCM can find it)
[self myDeleteFile:exportFile];
//[exportURL release];
_exportURL = [NSURL fileURLWithPath:exportFile];
exporter.outputURL = _exportURL;
// do the export
[exporter exportAsynchronouslyWithCompletionHandler:^{
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed: {
// log error to view
NSError *exportError = exporter.error;
NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
break;
}
case AVAssetExportSessionStatusCompleted: {
NSLog (@"AVAssetExportSessionStatusCompleted");
//Final document url
NSURL *audioUrl = _exportURL;
NSLog(@"Audio Url=%@",audioUrl);
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;
}
}
}];
}
Deleting the existing file which available inside the current path:
- (void)myDeleteFile:(NSString*)path{
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSError *deleteErr = nil;
[[NSFileManager defaultManager] removeItemAtPath:path error:&deleteErr];
if (deleteErr) {
NSLog (@"Can't delete %@: %@", path, deleteErr);
}
}
}
This is code used to create m4a directory:
NSString* myDocumentsM4aDirectory(){
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSError *error = nil;
NSString *dataPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/m4aFolder"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
//Create folde
return dataPath;
}
How to figure out this issue to play locally stored song permanently?
EDIT:
//This below function to call to play song
- (void)playSong
{
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:_exportURL] options:nil];
NSError *error = nil;
AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:asset.URL error:&error];
if(error == nil)
{
[player play]
}else
{
NSLog (@"Error during playing: %@", error);
}
}
Thanks,
Answer: I found the solution for songs not playing from document, reason I am previously storing the entire assert URL to core data. As ID of document "xxxxxx-xxxxxxx-xxxxxxx-xxxxxxxxx" will keep on changing for each launch.
So, I am fetching the assert path based on the title and extension which I was appended to the URL before. Now its working fine.
This answered helped to resolve this issue: Play local audio file with AVAudioPlayer