iOS - 尝试播放mp3文件失败

时间:2012-04-17 16:42:20

标签: iphone ios ipad audio avaudioplayer

我正在尝试播放和从我的应用程序从我的服务器检索的mp3文件执行以下操作:

- (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]; 
        });
    });
}

播放失败,意味着没有声音发出,我在逐步调试我的应用程序时得到此输出:

Catchpoint 2 (exception thrown).Single stepping until exit from function __cxa_throw, which has no line number information. 

当我在模拟器中NSLog错误时出现了这个问题:

Error Domain=NSOSStatusErrorDomain Code=-50 "The operation couldn’t be completed. (OSStatus error -50.)"

没有其他事情表明它失败了,有什么想法吗?

UPDATE:根据J_D的回答修改了我的代码并在模拟器中得到了这个:

Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn:  dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable
  Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
  Expected in: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
 in /System/Library/Frameworks/Security.framework/Versions/A/Security
2012-04-17 15:03:43.054 Fonyk[8238:15307] Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn:  dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable
  Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
  Expected in: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
 in /System/Library/Frameworks/Security.framework/Versions/A/Security

UPDATE:我没有创建的真正问题,AVAudioSession实例设置为在我的代码中播放,这样做以及我接受的更正答案使其工作。

2 个答案:

答案 0 :(得分:5)

我看到你的代码至少有一个问题,就是

NSURL *fileURL = [NSURL URLWithString:filePath];

尝试使用本地文件路径创建URL。它可能会返回零。你应该使用:

NSURL *fileURL = [NSURL fileURLWithPath:filePath];

现在,即使这样,您的代码也不会运行(我尝试了它并得到了相同的错误)。我自己没有使用过AVAudioPlayer,所以我不知道为什么会发生你的特定错误。

但是,我确实尝试了一个使用你的代码的小例子,我能够正确播放MP3。您可以使用AVAudioPlayer的initWithData构造函数,而不是将数据下载到文件并从文件加载AVAudioPlayer:

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

假设audioURL有效,这对我来说很好。我指的是服务器上的mp4用于测试。

所以用这个initWithData重写你的代码给出了:

- (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]; 
        });
    });
}

正如最后一点:在开始播放之前,您正在下载整个文件,这可能需要一段时间并消耗大量的堆(或者如果您要将其保存在文件中,则存储)

如果要流式传输,可以使用MPMoviePlayerController,但不要将视图附加到视图层次结构。这样,您将只拥有音频,并且不会更改应用程序的任何视觉效果。

一个例子是:

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

同样,在我这边,在模拟器中,它工作正常。

不要忘记释放播放器。您还可以注册代表以获取重要通知。

详细信息:http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPMoviePlayerController_Class/Reference/Reference.html

答案 1 :(得分:1)

您正在某处收到EXC_BAD_ACCESS。我建议删除所有异步代码,看看会发生什么。实际上,就异步调用而言,我对你的思考过程有点困惑。

请注意,AVAudioPlayer仅适用于LOCAL文件。看起来您可能正在设置它来从服务器播放音频文件,这将无法正常工作。

另外,为什么不尝试NSLog错误变量?