How to play mp3 audio from URL in ios swift

后端 未结 9 668
鱼传尺愫
鱼传尺愫 2020-11-30 04:50

I am getting mp3 url as a response of api calling. I want to play that audio, so how can i do that? (ios swift)

here is my response

 {
    content =          


        
相关标签:
9条回答
  • 2020-11-30 05:16

    Swift 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)")
        }
    }
    
    0 讨论(0)
  • 2020-11-30 05:18

    Create a complete Audio player with a progress bar and other stuff ... swift 5 and Xcode 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()
          }
    }
    

    The end result looks like this ...

    0 讨论(0)
  • 2020-11-30 05:19

    After some research, and some disappointment since none of the answers solved my problem, I've come to a solution and here's the final result. The accepted answer is half right, you still need to create an 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()
    
    0 讨论(0)
  • 2020-11-30 05:27

    Since AVPlayer is very limited (for example you cannot change url there without regenerate whole AVPlayer I think you should use AVQueuePlayer:

    From the docs:

    AVQueuePlayer is a subclass of AVPlayer used to play a number of items in sequence. Using this class you can create and manage a queue of player items comprised of local or progressively downloaded file-based media, such as QuickTime movies or MP3 audio files, as well as media served using HTTP Live Streaming.

    So in Swift 3 it will work like this:

    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()
        }
    }
    
    0 讨论(0)
  • 2020-11-30 05:28

    Use AVPlayer instead of AVAudioPlayer to play remote content. As per documentation AVAudioPlayer needs mp3 file to play Audio. AVAudioPlayer not provide support for streaming.

    Try this code , its working fine for me

    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")
        }
    }
    

    Please keep in mind to set App Transport Security(ATS) in info.plist file.

    <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
        </dict>
    
    0 讨论(0)
  • 2020-11-30 05:28

    To play a sound in swift2 is

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

    Let me know if it working.

    0 讨论(0)
提交回复
热议问题