iOS - Attempting to play mp3 file fails

拜拜、爱过 提交于 2019-12-06 12:38:46

I see at least one issue with your code, with the line

NSURL *fileURL = [NSURL URLWithString:filePath];

It tries to create an URL with a local file path. It will probably return nil. You should instead use:

NSURL *fileURL = [NSURL fileURLWithPath:filePath];

Now, even with this, your code does not run (I tried it and got the same error you got). I have not used AVAudioPlayer very much myself so I do not know why your specific error happens.

However, I did try a very small example using your code and I was able to play the MP3 correctly. Instead of downloading the data to a file and loading AVAudioPlayer from a file, you can use the initWithData constructor of AVAudioPlayer:

AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:[NSData dataWithContentsOfURL:audioURL] error:&error];

This works fine on my side, assuming that audioURL is valid. I pointed to a mp4 on my server for my test.

So rewriting your code with this initWithData gives:

- (IBAction)play:(UIButton *)sender {
    dispatch_queue_t downloadQueue = dispatch_queue_create("audio data downloader", NULL);
    dispatch_async(downloadQueue, ^{
        NSURL *audioURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/%@.mp3", FONYK_FILES_URL, [self.voicenote valueForKeyPath:@"Fonyker.fonykid"], [self.voicenote valueForKeyPath:@"Voicenote.vnid"]]];
        NSData *audioData = [NSData dataWithContentsOfURL:audioURL];

        dispatch_async(dispatch_get_main_queue(), ^{
            NSError *error = nil;
            AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&error];
            NSLog(@"%@", error);
            audioPlayer.delegate = self;
            [audioPlayer play]; 
        });
    });
}

Just as a last note: You are downloading the entire file before you start playing, which may take a while and consume a lot of heap (or storage if you were to save it on a file)

If you want to stream, you can use a MPMoviePlayerController, but you do not attach the view to your view hierarchy. This way, you will only have audio and will not change any visual of your application.

An example would be:

NSURL *audioURL = [NSURL URLWithString:@"MY_MP3_URL"];
MPMoviePlayerController* player = [[MPMoviePlayerController alloc] initWithContentURL:audioURL];
[player play];

Again, on my side, in the Simulator, it works fine.

Do not forget to release the player. You can also register delegates for important notifications.

Details here: http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPMoviePlayerController_Class/Reference/Reference.html

You are receiving an EXC_BAD_ACCESS somewhere. I suggest removing all asynchronous code and seeing what happens. Actually, I am a bit confused by your thought process as far as the async calls go.

Note that AVAudioPlayer only works with LOCAL files. It seems like you might be setting it up to play an audio file from a server, which won't work.

Also, why don't you try to NSLog the error variable?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!