【问题标题】:How to play mp3 audio from URL in ios swift如何在 ios swift 中从 URL 播放 mp3 音频
【发布时间】:2016-04-06 10:09:46
【问题描述】:

我得到 mp3 url 作为 api 调用的响应。 我想播放那个音频,那我该怎么做呢? (ios 迅速)

这是我的回答

 {
    content = "En este primer programa se tratar\U00e1n asuntos tan importante como este y aquel sin descuidar un poco de todo lo dem\U00e1s";
    file = "http://radio.spainmedia.es/wp-content/uploads/2015/12/ogilvy.mp3";
    image = "http://radio.spainmedia.es/wp-content/uploads/2015/12/tapas.jpg";
    number = 0001;
    subtitle = Titulareando;
    title = "Tapa 1";
}

这是我的代码::

 @IBAction func btnplayaudio(sender: AnyObject) {
    let urlstring = "http://radio.spainmedia.es/wp-content/uploads/2015/12/tailtoddle_lo4.mp3"
    let url = NSURL(string: urlstring)
    print("the url = \(url!)")

    play(url!)

}

func play(url:NSURL) {
    print("playing \(url)")

    do {
        self.player = try AVAudioPlayer(contentsOfURL: url)
        player.prepareToPlay()
        player.volume = 1.0
        player.play()
    } catch let error as NSError {
        self.player = nil
        print(error.localizedDescription)
    } catch {
        print("AVAudioPlayer init failed")
    }

}

我哪里错了?

【问题讨论】:

  • 您的代码为我抛出异常,操作无法完成。 (OSStatus 错误 2003334207
  • 它也对我抛出异常。但我怎样才能避免这种情况。简单来说,这是我的 mp3 网址radio.spainmedia.es/wp-content/uploads/2015/12/ogilvy.mp3 我怎么播放它??@satheeshwaran
  • 等一下,看看。
  • 请看我的回答,你的音频现在正在我的模拟器上播放。很棒的音乐。
  • 它在模拟器上工作,但在我的 iPhone 设备上不工作。那么有什么解决办法吗?它没有显示任何错误。甚至还调用了播放功能,但我的设备上没有声音@satheeshwaran

标签: ios swift swift2 ios9 avaudioplayer


【解决方案1】:

不要忘记取消静音模式。如果激活静音模式,AvAudioPlayer 将不会播放任何声音

【讨论】:

    【解决方案2】:

    我尝试了以下,

    let urlstring = "http://radio.spainmedia.es/wp-content/uploads/2015/12/tailtoddle_lo4.mp3"
    let url = NSURL(string: urlstring)
    print("the url = \(url!)")
    downloadFileFromURL(url!)
    

    添加以下方法,

    func downloadFileFromURL(url:NSURL){
    
        var downloadTask:NSURLSessionDownloadTask
        downloadTask = NSURLSession.sharedSession().downloadTaskWithURL(url, completionHandler: { [weak self](URL, response, error) -> Void in
            self?.play(URL)
        })
            
        downloadTask.resume()
        
    }
    

    还有你的玩法,

    func play(url:NSURL) {
        print("playing \(url)")
        
        do {
            self.player = try AVAudioPlayer(contentsOfURL: url)
            player.prepareToPlay()
            player.volume = 1.0
            player.play()
        } catch let error as NSError {
            //self.player = nil
            print(error.localizedDescription)
        } catch {
            print("AVAudioPlayer init failed")
        }
        
    }
    

    下载 mp3 文件然后尝试播放,不知何故 AVAudioPlayer 不会为您下载您的 mp3 文件。我可以下载音频文件并播放它。

    请记住将其添加到 info.plist 中,因为您是从 http 源加载的,并且您需要为 iOS 9+

    设置以下内容
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    </plist>
    

    【讨论】:

    • 它可以在模拟器上运行,但它不能在 iphone 上运行,所以有什么解决方案吗?
    • @Govind 您是否尝试在 downloadTask 之后记录 url?是否抛出任何其他异常,
    • 注意块上的保留周期!你应该使用[weak self]
    • @satheeshwaran 你能分享正确的代码,在哪里更正?
    • @satheeshwaran 在 swift 4 中获得对成员“downloadTask(with:completionHandler:)”的模棱两可的引用
    【解决方案3】:

    用进度条和其他东西创建一个完整的音频播放器...... swift 5Xcode 12.1

    var player: AVPlayer?
    var playerItem:AVPlayerItem?
    fileprivate let seekDuration: Float64 = 10
    
    
    @IBOutlet weak var labelOverallDuration: UILabel!
    @IBOutlet weak var labelCurrentTime: UILabel!
    @IBOutlet weak var playbackSlider: UISlider!
    @IBOutlet weak var ButtonPlay: UIButton!
    
    //call this mehtod to init audio player 
    func initAudioPlayer{
        let url = URL(string: "https://argaamplus.s3.amazonaws.com/eb2fa654-bcf9-41de-829c-4d47c5648352.mp3")
        let playerItem:AVPlayerItem = AVPlayerItem(url: url!)
        player = AVPlayer(playerItem: playerItem)
        
        playbackSlider.minimumValue = 0
        
        //To get overAll duration of the audio
        let duration : CMTime = playerItem.asset.duration
        let seconds : Float64 = CMTimeGetSeconds(duration)
        labelOverallDuration.text = self.stringFromTimeInterval(interval: seconds)
        
        //To get the current duration of the audio
        let currentDuration : CMTime = playerItem.currentTime()
        let currentSeconds : Float64 = CMTimeGetSeconds(currentDuration)
        labelCurrentTime.text = self.stringFromTimeInterval(interval: currentSeconds)
        
        playbackSlider.maximumValue = Float(seconds)
        playbackSlider.isContinuous = true
        
        
        
        player!.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main) { (CMTime) -> Void in
            if self.player!.currentItem?.status == .readyToPlay {
                let time : Float64 = CMTimeGetSeconds(self.player!.currentTime());
                self.playbackSlider.value = Float ( time );
                self.labelCurrentTime.text = self.stringFromTimeInterval(interval: time)
            }
            let playbackLikelyToKeepUp = self.player?.currentItem?.isPlaybackLikelyToKeepUp
            if playbackLikelyToKeepUp == false{
                print("IsBuffering")
                self.ButtonPlay.isHidden = true
                //        self.loadingView.isHidden = false
            } else {
                //stop the activity indicator
                print("Buffering completed")
                self.ButtonPlay.isHidden = false
                //        self.loadingView.isHidden = true
            }
        }
       
       //change the progress value
        playbackSlider.addTarget(self, action: #selector(playbackSliderValueChanged(_:)), for: .valueChanged)
        
        //check player has completed playing audio
        NotificationCenter.default.addObserver(self, selector: #selector(self.finishedPlaying(_:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem)}
    
    
    @objc func playbackSliderValueChanged(_ playbackSlider:UISlider) {
        let seconds : Int64 = Int64(playbackSlider.value)
        let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
        player!.seek(to: targetTime)
        if player!.rate == 0 {
            player?.play()
        }
    }
    
    @objc func finishedPlaying( _ myNotification:NSNotification) {
        ButtonPlay.setImage(UIImage(named: "play"), for: UIControl.State.normal)
        //reset player when finish   
        playbackSlider.value = 0
        let targetTime:CMTime = CMTimeMake(value: 0, timescale: 1)
        player!.seek(to: targetTime)
    }
    
    @IBAction func playButton(_ sender: Any) {
        print("play Button")
        if player?.rate == 0
        {
            player!.play()
            self.ButtonPlay.isHidden = true
            //        self.loadingView.isHidden = false
            ButtonPlay.setImage(UIImage(systemName: "pause"), for: UIControl.State.normal)
        } else {
            player!.pause()
            ButtonPlay.setImage(UIImage(systemName: "play"), for: UIControl.State.normal)
        }
        
    }
    
    
    func stringFromTimeInterval(interval: TimeInterval) -> String {
        let interval = Int(interval)
        let seconds = interval % 60
        let minutes = (interval / 60) % 60
        let hours = (interval / 3600)
        return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
    }
    
    
    
    @IBAction func seekBackWards(_ sender: Any) {
        if player == nil { return }
        let playerCurrenTime = CMTimeGetSeconds(player!.currentTime())
        var newTime = playerCurrenTime - seekDuration
        if newTime < 0 { newTime = 0 }
        player?.pause()
        let selectedTime: CMTime = CMTimeMake(value: Int64(newTime * 1000 as Float64), timescale: 1000)
        player?.seek(to: selectedTime)
        player?.play()
    
    }
    
    
    @IBAction func seekForward(_ sender: Any) {
        if player == nil { return }
        if let duration = player!.currentItem?.duration {
           let playerCurrentTime = CMTimeGetSeconds(player!.currentTime())
           let newTime = playerCurrentTime + seekDuration
           if newTime < CMTimeGetSeconds(duration)
           {
              let selectedTime: CMTime = CMTimeMake(value: Int64(newTime * 1000 as 
           Float64), timescale: 1000)
              player!.seek(to: selectedTime)
           }
           player?.pause()
           player?.play()
          }
    }
    

    最终的结果是这样的……

    【讨论】:

    • 优秀。这甚至适用于 macOS(只需使用 AppKit 而不是 UIKit)感谢您的示例。
    • 正是我想要的。谢谢:)
    【解决方案4】:
    var player : AVPlayer?
    func playSound()
        {
          guard  let url = URL(string: "https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3")
         else 
            {
              print("error to get the mp3 file")
              return
            }
         do{
             try AVAudioSession.sharedInstance().setCategory(.playback, mode.default)
             try AVAudioSession.sharedInstance().setActive(true)
             player = try AVPlayer(url: url as URL)
             guard let player = player
                   else 
                       { 
                         return 
                       }
             player.play()
          } catch let error {
                print(error.localizedDescription)
                   }
       }
    

    【讨论】:

    • @Cubo78 代码运行良好。实际上,使用 url 播放的音频不适用于 iPhone,只能在模拟器中使用。在上面的代码中它被解决了。加载几秒钟后。它的工作。
    【解决方案5】:

    SWIFT 4

    1 - import AVFoundation

    2 - 声明播放器

    var player : AVPlayer?
    

    3 - 在 ViewDidLoad 调用函数中并像 String 一样传递流 url

    loadRadio(radioURL: (radioStation?.streamURL)!)
    

    4 - 播放功能

    func loadRadio(radioURL: String) {
    
            guard let url = URL.init(string: radioURL) else { return }
            let playerItem = AVPlayerItem.init(url: url)
            player = AVPlayer.init(playerItem: playerItem)
            player?.play()
            startNowPlayingAnimation(true)
            played = true
        }
    

    对我来说是快速流式传输音频的最佳且简单的方法。

    【讨论】:

    • 嘿,我已经实施了解决方案,它工作正常。但是在我按下按钮播放音频后会有 10 秒的延迟。为了测试,我使用了这个音频源:soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3
    • 有没有办法可以将初始延迟减少到 2-3s ?谢谢
    【解决方案6】:

    经过一些研究,以及由于没有一个答案能解决我的问题而有些失望,我找到了解决方案,这是最终结果。接受的答案对了一半,您仍然需要创建一个AVPlayerLayer

    let url = URL(string: "https://www.myinstants.com/media/sounds/cade-o-respeito.mp3" ?? "")
    playerItem = AVPlayerItem(url: url!)
    player = AVPlayer(playerItem: playerItem)
    
    let playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
    self.contentView.layoutSublayers(of: playerLayer)
    
    player?.play()
    

    【讨论】:

      【解决方案7】:

      斯威夫特 4

      func playSound(soundUrl: String) {
          let sound = URL(fileURLWithPath: soundUrl)
          do {
              let audioPlayer = try AVAudioPlayer(contentsOf: sound)
              audioPlayer.prepareToPlay()
              audioPlayer.play()
          }catch let error {
              print("Error: \(error.localizedDescription)")
          }
      }
      

      【讨论】:

        【解决方案8】:

        由于AVPlayer 非常有限(例如,如果不重新生成整个AVPlayer,您无法更改url,我认为您应该使用AVQueuePlayer

        来自docs

        AVQueuePlayer 是 AVPlayer 的子类,用于播放多个项目 按顺序。使用这个类,你可以创建和管理一个队列 由本地或逐步下载的基于文件的播放器项目组成 媒体,例如 QuickTime 电影或 MP3 音频文件,以及媒体 使用 HTTP Live Streaming 提供服务。

        所以在 Swift 3 中它会像这样工作:

        lazy var playerQueue : AVQueuePlayer = {
            return AVQueuePlayer()
        }()
        

        ...

        func playTrackOrPlaylist{
            if let url = track.streamURL() { //this is an URL fetch from somewhere. In this if you make sure that URL is valid
                let playerItem = AVPlayerItem.init(url: url)
                self.playerQueue.insert(playerItem, after: nil)
                self.playerQueue.play()
            }
        }
        

        【讨论】:

        • 为什么要让 AVQueuePlayer 实例成为惰性获取器。不是每次都返回新队列吗?如果您想管理曲目队列怎么办?
        • 实际上恰恰相反。 lazy 将在您首次访问时创建一次。 var playerQueue: AVQueuePlayer { return AVQueuePlayer() } 每次都会创建新实例。使用lazy,将只有一个实例。延伸阅读:mikebuss.com/2014/06/22/lazy-initialization-swift
        【解决方案9】:

        使用AVPlayer 代替 AVAudioPlayer 来播放远程内容。根据文档 AVAudioPlayer 需要 mp3 文件来播放音频。 AVAudioPlayer 不支持streaming

        试试这个代码,它对我来说很好用

        func play(url:NSURL) {
            print("playing \(url)")
        
            do {
        
                let playerItem = AVPlayerItem(URL: url)
        
                self.player = try AVPlayer(playerItem:playerItem)
                player!.volume = 1.0
                player!.play()
            } catch let error as NSError {
                self.player = nil
                print(error.localizedDescription)
            } catch {
                print("AVAudioPlayer init failed")
            }
        }
        

        请记住在 info.plist 文件中设置 App Transport Security(ATS)。

        <key>NSAppTransportSecurity</key>
            <dict>
                <key>NSAllowsArbitraryLoads</key>
                <true/>
            </dict>
        

        【讨论】:

        • 它在模拟器上工作,但在我的 iPhone 设备上不工作。那么有什么解决办法吗?它没有显示任何错误。甚至还调用了播放功能,但我的设备上没有声音
        • 播放远程内容或本地 mp3 文件?
        • 确保您的设备处于振铃模式而不是静音模式。
        • 它处于振铃模式。最主要的是它可以免提工作。但如果没有免提,它就无法工作。
        • 我觉得AVPlayer,首先下载数据内容,然后播放。这不是流。例如,当我尝试使用此播放器从 DropBox 播放音频时,我会在开始前等待 5-6 秒...... :(
        【解决方案10】:

        在swift2中播放声音是

        func playSound(soundUrl: String)
        {
           let sound = NSURL(soundUrl)
          do{
              let audioPlayer = try AVAudioPlayer(contentsOfURL: sound)
              audioPlayer.prepareToPlay()
              audioPlayer.play()
          }catch {
              print("Error..")
          }
        }
        

        让我知道它是否有效。

        【讨论】:

        • 它的抛出错误对我来说我认为我对 mp3 文件做错了..这是我从服务器得到的响应... { content = "En este prime programa se tratar\U00e1n asuntos tan importante como este y aquel sin descuidar un poco de todo lo dem\U00e1s";文件 = "radio.spainmedia.es/wp-content/uploads/2015/12/ogilvy.mp3";图片 = "radio.spainmedia.es/wp-content/uploads/2015/12/tapas.jpg";数字 = 0001;副标题=标题;标题=“塔帕1”; }那么我该如何播放这个文件@zumry Mohamed
        • 看起来你快到了,但并不完全。您从服务器请求的不是 mp3 文件的实际字节,而是有关文件所在位置的元数据。将“文件”键从 json 中拉出,并将其与 AVMediaPlayer 一起使用。
        猜你喜欢
        • 2014-08-17
        • 1970-01-01
        • 2014-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多