【问题标题】:Stream Audio is not working with Avplayer流音频不适用于 Avplayer
【发布时间】:2017-07-07 01:52:53
【问题描述】:

我将一首歌曲上传到 CloudKit。它是 CkAsset 格式。因为我无法在 iOS 中使用标准 CloudKit 连接获取网页 url。我正在使用 javascript 获取它(CloudKit 允许通过 web 直接连接获取 web url)。问题是我可以通过链接在 VLC 或任何其他媒体播放器上播放音乐。但是,当我在 AvPlayer 上尝试时。它不播放任何东西。我将链接作为字符串,然后将其转入 NSURL。

    let a = webView.stringByEvaluatingJavaScript(from: "myVar")
    print(a!)
    let url : NSString = a! as NSString
    let urlStr : NSString = url.addingPercentEscapes(using: String.Encoding.utf8.rawValue)! as NSString
    let searchURL : NSURL = NSURL(string: urlStr as String)!
    print(searchURL)
    /*https://cvws.icloud-content.com/B/AVHgxc_-X3u9H5xK684KmUQrzDqp/$%7Bf%7D?o=Apgif1Giyg-lwRiNre2KJYl-5EhUAiL1m1OgE3-osxpxexWD7YGjCAOFCoQLRv8sGUglywu2tGr-OgfGtDZ15k0&v=1&x=3&a=BbLB0UptOX3bA-k6OQ&e=1487341935&k=_&fl=&r=0f83571c-d168-4743-b38b-0e808baa0a1a-1&ckc=iCloud.com.emreonder.ogun-dalka-music&ckz=_defaultZone&p=61&s=OuE127GKlo_0EIZ6y5t49gMv0qM 
     */
    let playerItem = AVPlayerItem(url: searchURL as URL)
    player = AVPlayer(playerItem: playerItem)
    let playerLayer:AVPlayerLayer = AVPlayerLayer(player: player)
    self.view.layer.addSublayer(playerLayer)
    self.player.play()

【问题讨论】:

    标签: ios swift stream assets avplayer


    【解决方案1】:

    尝试创建一个“AVAsset”并异步加载它。观察播放器的状态,如就绪、失败等,并以此为基础开始播放。

    func initializePlayer() {
            //audio session for handling interuptions - Done Appdelegate
            /*
             1. Create Asset (Asset represent a single media), AVAsset -> AVAssetTrack
             2. Resource properties like metadata, duration etc are loaded from asset, but if taken syncrn will block so use async
             */
    
            let audioPath = Bundle.main.path(forResource: "big_buck_bunny", ofType: "mp4")
            let resourceUrl = URL(fileURLWithPath: audioPath!)
            let asset = AVAsset(url: resourceUrl)
    
            let playableKey = "playable"
    
    
    
            //        addObserver(self, forKeyPath: #keyPath(AVPlayerItem.rate), options: [.new, .initial], context: &audioPlayerInterfaceViewControllerKVOContext)
            //        addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.new, .initial], context: &audioPlayerInterfaceViewControllerKVOContext)
    
            // Load the "playable" property
    
            asset.loadValuesAsynchronously(forKeys: [playableKey]) { [unowned self] in
    
                var error: NSError? = nil
    
                let status = asset.statusOfValue(forKey: playableKey, error: &error)
    
                switch status {
    
                case .loaded:
                    debugPrint("Sucessfuly loaded")
                    self.playerItem = AVPlayerItem(asset: asset)
    
                    self.playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: &audioPlayerInterfaceViewControllerKVOContext)
                    self.playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.duration), options: [.new, .initial], context: &audioPlayerInterfaceViewControllerKVOContext)
                    self.player = AVPlayer(playerItem: self.playerItem)
                    self.player.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: [.new,.initial], context: &audioPlayerInterfaceViewControllerKVOContext)
                    let interval = CMTimeMake(1, 1)
    //                self.player.volume = 0.5
                    self.timeObserveToken = self.player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) { [unowned self] time in
                        let timeElapsed = Float(CMTimeGetSeconds(time))
                        UIView.animate(withDuration: 1.5, animations: {
                            if self.userActionEnabled {
                                self.durationSlider.setValue(Float(timeElapsed), animated: true)
                            }
    
                        })
                        if self.userActionEnabled {
                            self.startTimeLabel.text = self.createTimeString(time: timeElapsed)
                        }
                    }
    
                    break
    
                    // Sucessfully loaded. Continue processing.
    
                case .failed:
                    self.showErrorAlert(errorString: "Failed to load")
                    debugPrint("failed")
                    break
    
                    // Handle error
    
                case .cancelled:
                    self.showErrorAlert(errorString: "Failed to load")
                    debugPrint("Cancelled")
                    break
    
                    // Terminate processing
    
                default:
                    debugPrint("Error occured")
                    self.showErrorAlert(errorString: "Failed to load")
                    break
    
                    // Handle all other cases
    
                }
    
            }
        }
    
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    
            guard context == &audioPlayerInterfaceViewControllerKVOContext else {
                super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    
                return
            }
    
            if keyPath == #keyPath(AVPlayerItem.status) {
    
                let status: AVPlayerItemStatus
    
                if let statusNumber = change?[.newKey] as? NSNumber {
    
                    status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
    
                } else {
    
                    status = .unknown
    
                }
    
                // Switch over status value
    
                switch status {
    
                case .readyToPlay:
                    player.play()
                    break
    
                    // Player item is ready to play.
    
                case .failed:
                    showErrorAlert(errorString: "Failed to load")
                    break
    
                    // Player item failed. See error.
    
                case .unknown:
                    showErrorAlert(errorString: "Failed to load")
                    break
    
                    // Player item is not yet ready.
    
                }
    
            }
    
            if keyPath == #keyPath(AVPlayerItem.duration) {
                let newDuration: CMTime
                if let newDurationAsValue = change?[NSKeyValueChangeKey.newKey] as? NSValue {
                    newDuration = newDurationAsValue.timeValue
                }
                else {
                    newDuration = kCMTimeZero
                }
    
                let hasValidDuration = newDuration.isNumeric && newDuration.value != 0
                let newDurationSeconds = hasValidDuration ? CMTimeGetSeconds(newDuration) : 0.0
                let currentTime = hasValidDuration ? Float(CMTimeGetSeconds((player.currentTime()))) : 0.0
    
                durationSlider.maximumValue = Float(newDurationSeconds)
    
                durationSlider.value = currentTime
    
                nextBtn.isEnabled = hasValidDuration
    
                playPauseBtn.isEnabled = hasValidDuration
    
                previousBtn.isEnabled = hasValidDuration
    
                durationSlider.isEnabled = hasValidDuration
    
                startTimeLabel.isEnabled = hasValidDuration
                startTimeLabel.text = createTimeString(time: currentTime)
    
                endTimeLabel.isEnabled = hasValidDuration
                endTimeLabel.text = createTimeString(time: Float(newDurationSeconds))
            }
    
            if keyPath == #keyPath(AVPlayer.rate) {
                // Update `playPauseButton` image.
    
                let newRate = (change?[NSKeyValueChangeKey.newKey] as? NSNumber)?.doubleValue
    
                let buttonImageName = newRate == 1.0 ? "Pause" : "Play"
    
                let buttonImage = UIImage(named: buttonImageName)
    
                playPauseBtn.setImage(buttonImage, for: UIControlState())
            }
    
        }
    

    【讨论】:

    • 我觉得问题是我们在写audioPath的时候可以声明类型。但是,我不能用 url 做到这一点。除了你的代码对我来说太复杂之外,我想不通。
    猜你喜欢
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 2012-01-18
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多