2

次のようにして、アプリからサーバーから取得した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.)"

失敗したことを示すものは他にありません。何か考えはありますか?

更新: 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

更新:私が抱えていた本当の問題は、AVAudioSessionインスタンスを作成せず、コードで再生するように設定することでした。これにより、受け入れた修正の回答が機能しました。

4

2 に答える 2

5

あなたのコードには、次の行で少なくとも 1 つの問題があります。

NSURL *fileURL = [NSURL URLWithString:filePath];

ローカル ファイル パスで URL を作成しようとします。おそらくnilを返します。代わりに次を使用する必要があります。

NSURL *fileURL = [NSURL fileURLWithPath:filePath];

これでも、コードは実行されません (試してみたところ、同じエラーが発生しました)。私は AVAudioPlayer をあまり使用していないので、特定のエラーが発生する理由がわかりません。

ただし、コードを使用して非常に小さな例を試してみたところ、MP3 を正しく再生できました。データをファイルにダウンロードしてファイルから AVAudioPlayer をロードする代わりに、AVAudioPlayer の initWithData コンストラクターを使用できます。

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

于 2012-04-17T17:47:57.903 に答える
1

EXC_BAD_ACCESS をどこかで受け取っています。すべての非同期コードを削除して、何が起こるかを確認することをお勧めします。実際、非同期呼び出しに関する限り、私はあなたの思考プロセスに少し混乱しています。

AVAudioPlayer は LOCAL ファイルでのみ機能することに注意してください。サーバーからオーディオファイルを再生するように設定しているようですが、動作しません。

また、エラー変数を NSLog してみませんか?

于 2012-04-17T16:51:15.243 に答える