【问题标题】:AVPlayer audio buffering in swift 3 source disconnected observerswift 3源断开的观察者中的AVPlayer音频缓冲
【发布时间】:2016-11-22 18:15:31
【问题描述】:

我有播放 AAC 音频流的应用。一切正常,但是当我断开流并在一秒钟后再次连接时,音频在半分钟后停止播放。当我不重新连接时,我在一两分钟后出现错误。要重新连接,我必须停止 AVPlayer 并重新开始。我想在播放器停止播放音乐后立即重新连接流或显示消息。我怎样才能做到这一点?此外,我还有一个问题:我将代码转换为 swift 3,但一行有问题:

fileprivate var playerItem = AVPlayerItem?()

错误:不能调用没有参数的初始化程序 我该如何解决?也许这就是问题所在?

我的收音机播放器课程:

import Foundation
import AVFoundation
import UIKit

protocol errorMessageDelegate {
    func errorMessageChanged(_ newVal: String)
}

protocol sharedInstanceDelegate {
    func sharedInstanceChanged(_ newVal: Bool)
}

class RadioPlayer : NSObject {
    static let sharedInstance = RadioPlayer()
    var instanceDelegate:sharedInstanceDelegate? = nil
    var sharedInstanceBool = false {
        didSet {
            if let delegate = self.instanceDelegate {
                delegate.sharedInstanceChanged(self.sharedInstanceBool)
            }
        }
    }
    fileprivate var player = AVPlayer(url: URL(string: Globals.radioURL)!)
 //   fileprivate var playerItem = AVPlayerItem?()
    fileprivate var isPlaying = false

    var errorDelegate:errorMessageDelegate? = nil
    var errorMessage = "" {
        didSet {
            if let delegate = self.errorDelegate {
                delegate.errorMessageChanged(self.errorMessage)
            }
        }
    }

    override init() {
        super.init()

        errorMessage = ""

        let asset: AVURLAsset = AVURLAsset(url: URL(string: Globals.radioURL)!, options: nil)

        let statusKey = "tracks"

        asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: {
            var error: NSError? = nil

            DispatchQueue.main.async(execute: {
                let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error)

                if status == AVKeyValueStatus.loaded{

                    let playerItem = AVPlayerItem(asset: asset)

                    self.player = AVPlayer(playerItem: playerItem)
                    self.sharedInstanceBool = true

                } else {
                    self.errorMessage = error!.localizedDescription
                    print(error!)
                }

            })


        })

        NotificationCenter.default.addObserver(
            forName: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime,
            object: nil,
            queue: nil,
            using: { notification in
                print("Status: Failed to continue")
                self.errorMessage = NSLocalizedString("STREAM_INTERUPT", comment:"Stream was interrupted")
        })

        print("Initializing new player")

    }

    func resetPlayer() {
        errorMessage = ""

        let asset: AVURLAsset = AVURLAsset(url: URL(string: Globals.radioURL)!, options: nil)

        let statusKey = "tracks"

        asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: {
            var error: NSError? = nil

            DispatchQueue.main.async(execute: {
                let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error)

                if status == AVKeyValueStatus.loaded{

                    let playerItem = AVPlayerItem(asset: asset)
          //          playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: &ItemStatusContext)

                    self.player = AVPlayer(playerItem: playerItem)
                    self.sharedInstanceBool = true

                } else {
                    self.errorMessage = error!.localizedDescription
                    print(error!)
                }

            })
        })
    }

    func bufferFull() -> Bool {
        return bufferAvailableSeconds() > 45.0
    }

    func bufferAvailableSeconds() -> TimeInterval {
        // Check if there is a player instance
        if ((player.currentItem) != nil) {

            // Get current AVPlayerItem
            let item: AVPlayerItem = player.currentItem!
            if (item.status == AVPlayerItemStatus.readyToPlay) {

                let timeRangeArray: NSArray = item.loadedTimeRanges as NSArray
                if timeRangeArray.count < 1 { return(CMTimeGetSeconds(kCMTimeInvalid)) }
                let aTimeRange: CMTimeRange = (timeRangeArray.object(at: 0) as AnyObject).timeRangeValue
         //       let startTime = CMTimeGetSeconds(aTimeRange.end)
                let loadedDuration = CMTimeGetSeconds(aTimeRange.duration)

                return (TimeInterval)(loadedDuration);
            }
            else {
                return(CMTimeGetSeconds(kCMTimeInvalid))
            }
        } 
        else {
            return(CMTimeGetSeconds(kCMTimeInvalid))
        }
    }

    func play() {
        player.play()
        isPlaying = true
        print("Radio is \(isPlaying ? "" : "not ")playing")
    }

    func pause() {
        player.pause()
        isPlaying = false
        print("Radio is \(isPlaying ? "" : "not ")playing")
    }

    func currentlyPlaying() -> Bool {
        return isPlaying
    }
}

我将不胜感激;)

【问题讨论】:

    标签: iphone swift3 xcode8


    【解决方案1】:

    第二期fileprivate var playerItem = AVPlayerItem?() 写这个,它应该可以工作fileprivate var playerItem: AVPlayerItem?

    第一期

    当我断开流并在一秒钟音频停止后再次连接时 半分钟后播放。当我不重新连接后我有错误 一到两分钟。要重新连接,我必须停止 AVPlayer 并重新开始。一世 想要在播放器后立即重新连接流或显示消息 停止播放音乐。我该怎么做?

    我不明白怎么了?您按下按钮暂停播放器,然后再次按下按钮,一两分钟后它会自行停止?

    我今天测试了同一个类,它工作得很好,即使在与服务器的连接丢失后(当连接恢复时,你可以点击播放按钮,它会播放)

    我会把我的代码留在这里,试试看

    import Foundation
    import AVFoundation
    import UIKit
    
    protocol errorMessageDelegate {
        func errorMessageChanged(newVal: String)
    }
    
    protocol sharedInstanceDelegate {
        func sharedInstanceChanged(newVal: Bool)
    }
    
    
    
    class RadioPlayer : NSObject {
    
        static let sharedInstance = RadioPlayer()
        var instanceDelegate:sharedInstanceDelegate? = nil
        var sharedInstanceBool = false {
            didSet {
                if let delegate = self.instanceDelegate {
                    delegate.sharedInstanceChanged(newVal: self.sharedInstanceBool)
                }
            }
        }
        private var player = AVPlayer(url: NSURL(string: "<# YOUR STREAM HERE #>")! as URL)
        private var playerItem: AVPlayerItem?
        private var isPlaying = false
    
        var errorDelegate:errorMessageDelegate? = nil
        var errorMessage = "" {
            didSet {
                if let delegate = self.errorDelegate {
                    delegate.errorMessageChanged(newVal: self.errorMessage)
                }
            }
        }
    
        override init() {
            super.init()
    
            errorMessage = ""
    
            let asset: AVURLAsset = AVURLAsset(url: NSURL(string: "<# YOUR STREAM HERE #>")! as URL, options: nil)
    
            let statusKey = "tracks"
    
            asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: {
    
                var error: NSError? = nil
    
                DispatchQueue.main.async(execute: {
                    let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error)
    
                    if status == AVKeyValueStatus.loaded{
    
                        let playerItem = AVPlayerItem(asset: asset)
    
                        self.player = AVPlayer(playerItem: playerItem)
                        self.sharedInstanceBool = true
    
                    } else {
                        self.errorMessage = error!.localizedDescription
                        print(error!)
                    }
    
                })
    
            })
    
            NotificationCenter.default.addObserver(
                forName: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime,
                object: nil,
                queue: nil,
                using: { notification in
                    print("Status: Failed to continue")
                    self.errorMessage = "Stream was interrupted"
            })
    
            print("Initializing new player")
    
        }
    
        func resetPlayer() {
            errorMessage = ""
    
            let asset: AVURLAsset = AVURLAsset(url: NSURL(string: "<# YOUR STREAM HERE #>")! as URL, options: nil)
    
            let statusKey = "tracks"
    
            asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: {
                var error: NSError? = nil
    
                DispatchQueue.main.async(execute: {
                    let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error)
    
                    if status == AVKeyValueStatus.loaded{
    
                        let playerItem = AVPlayerItem(asset: asset)
                        //playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: &ItemStatusContext)
    
                        self.player = AVPlayer(playerItem: playerItem)
                        self.sharedInstanceBool = true
    
                    } else {
                        self.errorMessage = error!.localizedDescription
                        print(error!)
                    }
    
                })
            })
        }
    
        func bufferFull() -> Bool {
            return bufferAvailableSeconds() > 45.0
        }
    
        func bufferAvailableSeconds() -> TimeInterval {
            // Check if there is a player instance
            if ((player.currentItem) != nil) {
    
                // Get current AVPlayerItem
                let item: AVPlayerItem = player.currentItem!
                if (item.status == AVPlayerItemStatus.readyToPlay) {
    
                    let timeRangeArray: NSArray = item.loadedTimeRanges as NSArray
                    if timeRangeArray.count < 1 { return(CMTimeGetSeconds(kCMTimeInvalid)) }
                    let aTimeRange: CMTimeRange = (timeRangeArray.object(at: 0) as AnyObject).timeRangeValue
                    //let startTime = CMTimeGetSeconds(aTimeRange.end)
                    let loadedDuration = CMTimeGetSeconds(aTimeRange.duration)
                    return (TimeInterval)(loadedDuration)
                }
                else {
                    return(CMTimeGetSeconds(kCMTimeInvalid))
                }
            }
            else {
                return(CMTimeGetSeconds(kCMTimeInvalid))
            }
        }
    
        func play() {
            player.play()
            isPlaying = true
            print("Radio is \(isPlaying ? "" : "not ")playing")
        }
    
        func pause() {
            player.pause()
            isPlaying = false
            print("Radio is \(isPlaying ? "" : "not ")playing")
        }
    
        func currentlyPlaying() -> Bool {
            return isPlaying
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-18
      • 2015-12-13
      • 2016-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 2015-09-07
      • 1970-01-01
      相关资源
      最近更新 更多