Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone: AVAudioPlayer unsupported file type

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?

like image 534
mtmurdock Avatar asked Feb 04 '11 18:02

mtmurdock


3 Answers

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!

like image 65
mtmurdock Avatar answered Sep 23 '22 08:09

mtmurdock


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.

like image 25
Don Avatar answered Sep 19 '22 08:09

Don


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;
like image 23
Yankouski Roman Avatar answered Sep 21 '22 08:09

Yankouski Roman