检查mp3是否可以在swift中播放

时间:2015-05-15 15:16:14

标签: ios objective-c swift mp3 avaudioplayer

我正在尝试下载&播放远程mp3。

基本上:

  1. 用户点击了mp3,
  2. 从后台开始下载
  3. 然后,当可能时,播放开始。
  4. 一切都运行得很好 - 下载是由AFHTTPRequestOperation执行的,它将mp3直接下载到文件中,每次 1000字节左右都会获得进度更新。

      

    问题是我不确切知道何时开始播放   AVAudioPlayer

    AVAudioPlayer可播放未完成的mp3,但如果没有足够的数据,则会触发 fatalError(EXC_BREAKPOINT)并且我的应用崩溃

      
        
    • 它甚至没有返回错误。
    •   

    我事先知道mp3的持续时间,我可以从中确定约。像 - (sizeDownloaded/totalSize)*duration那样下载了多少秒的播放,但这只是愚蠢的,有时会失败(我猜这是因为文件开头有ID3标签,它可以包含巨大的图像我的近似值毫无意义)。

    我目前的代码:

    op.setDownloadProgressBlock({bytesRead, totalBytesRead, totalBytesExpectedToRead in
        let approxBytesForOneSecond = totalBytesExpectedToRead/Int64(downloadableItem.length)
        let approxSecondsDownloaded = totalBytesRead/approxBytesForOneSecond
    
        if approxSecondsDownloaded > kMinimumSecondsDownloadedForPlay { //min. secs = 5
            var error: NSError?
            self.player = AVAudioPlayer(contentsOfURL: url, error: &error) // This is the line where I sometimes get EXC_Breakpoint. The reason for this is that the mp3 is not playable yet ...
            if (error != nil) {
                // Error initializing item - never called
            } else {
                // Item initialized OK -> Play
            }
        }
    })
    

    那么,是否有一些可靠的方法来确定文件是否可播放?

    我知道提高播放开始的限制会有所帮助,它似乎并不合适。并且“等到下载完成”不是答案...... :)

    非常感谢!

2 个答案:

答案 0 :(得分:1)

知道mp3文件的比特率可以让你估计你需要多少文件才能安全地开始播放,但是谁知道如果文件在打开后文件发生变化,AVAudioPlayer将会做什么?

如果您在完成播放后不需要保留mp3,则可以从AVAudioPlayer(只能播放本地文件)切换到AVPlayer,这也可以播放流式传输的文件来自互联网:

 var url = NSURL(string:"http://YOUR_URL")
 player = AVPlayer(URL:url)
 player.play()

只要有足够的数据可用于持续播放,它就会播放。

如果您想保留AVPlayer正在播放的流式字节,事情会变得更复杂,但可以通过this blog post

中详述的AVAssetResourceLoader来实现

<强>更新 如果要在后台下载多个文件,请执行此操作!您仍然可以通过AVPlayer将数据移至AVAssetResourceLoaderAVPlayer将决定何时有足够的数据进行播放(您可以播放的是什么意思?)

答案 1 :(得分:1)

我明白了。如果文件不可播放(无论出于何种原因),此函数将返回错误。在我的测试中,对于完全没有音频数据的不完整文件,它成功返回false,如果至少有一些东西要播放,则为true(无论文件是否完整)。在我看来,这与AVAudioPlayer / AVPlayer使用的功能相同。它在Obj-C中我并没有迅速重写它,但我不确定它是否会被泄漏...

+ (BOOL) isFilePlayable:(NSURL*)url {

    // Try opening audiofile -> if it's playable it will open, if not, it will return error
    AudioFileID audioFileID;;

    OSErr err;
    err = AudioFileOpenURL((__bridge CFURLRef)url,
                       kAudioFileReadPermission,
                       0,
                       &audioFileID);
    if (err != noErr) {
        NSLog(@"Couldn't open audio file...");
        return NO;
    }

    AudioFileClose(audioFileID);

    return YES;
}