My app downloads an mp3 from our server and plays it back to the user. The file is 64 kbps (which is well within the acceptable range for iPhone if I understand correctly). I have looked up how to do this on dozens of sites and they all suggest that i do exactly this:
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://.../file.mp3"]];
NSError *e = nil;
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:data error&e];
[player setDelegate:self];
When I run the code, player comes back null and I get this error:
2011-02-04 10:44:46.176 MyApp[6052:207] Error loading audio: Error Domain=NSOSStatusErrorDomain Code=1954115647 "The operation couldn’t be completed. (OSStatus error 1954115647.)"
2011-02-04 10:44:49.647 MyApp[6052:207] unsupported file type
I have checked the file and I know that it works. It will play with no problems on Windows Media Player, and Quicktime on mac. I have also uploaded the file to the iPhone emulator and it plays with no problems whatsoever. The file is fine, but for some reason AVAudioPlayer doesn't like it.
Is there something I need to change? Is there some kind of setting for NSData to specify what kind of file it is? Does anyone have any idea?
At long last i have found a solution to this problem! Instead of initializing the audio player with the NSData object, I saved the file to the Documents folder, and then initialized the player with the file URL
//download file and play from disk NSData *audioData = [NSData dataWithContentsOfURL:someURL]; NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *filePath = [NSString stringWithFormat:@"%@/%@.mp3", docDirPath , fileName]; [audioData writeToFile:filePath atomically:YES]; NSError *error; NSURL *fileURL = [NSURL fileURLWithPath:filePath]; player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error]; if (player == nil) { NSLog(@"AudioPlayer did not load properly: %@", [error description]); } else { [player play]; }
When the app is done with the file, it can be deleted. Hope that his helps more than just me!
We were dealing with the same issue - we had to write the file to disk first. What I found eventually was that the data we were downloading had extra, blank bytes at the beginning. When reading from disk using initWithContentsOfURL
, AVAudioPlayer knew how to deal with this, but when loading from NSData using initWithData
, it did not. Trimming those bytes fixed it.
From iOS 7 AVAudioPlayer has new initializer
NSError *error;
[[AVAudioPlayer alloc] initWithData:soundData fileTypeHint:AVFileTypeMPEGLayer3 error:&error]
The supported UTIs
NSString *const AVFileType3GPP;
NSString *const AVFileType3GPP2;
NSString *const AVFileTypeAIFC;
NSString *const AVFileTypeAIFF;
NSString *const AVFileTypeAMR;
NSString *const AVFileTypeAC3;
NSString *const AVFileTypeMPEGLayer3;
NSString *const AVFileTypeSunAU;
NSString *const AVFileTypeCoreAudioFormat;
NSString *const AVFileTypeAppleM4V;
NSString *const AVFileTypeMPEG4;
NSString *const AVFileTypeAppleM4A;
NSString *const AVFileTypeQuickTimeMovie;
NSString *const AVFileTypeWAVE;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With