AVPlayer Fairplay HLS在视频暂停时不会停止播放音频

时间:2017-03-31 18:44:48

标签: ios avfoundation avplayer hls fairplay

我在https://developer.apple.com/streaming/fps/使用Apple的Fairplay Streaming示例代码时使用Fairplay实现,尽管我尝试仅选择与在线Fairplay Streaming相关的部分,而不是持久性/离线播放。在下面的代码中,没有Fairplay的视频正常播放/暂停/寻找,但是当我播放受Fairplay保护的视频时,只有视频轨道才能正常运行。

暂停播放不会停止音频播放,更改音轨不会停止上一个音轨,因此两者一起播放,搜索也可能不起作用。

除了下面的帮助程序类,我还有来自Apple的FairPlay Streaming Server SDK https://developer.apple.com/streaming/fps/客户端示例代码的AssetLoaderDelegateAssetPlaybackManager,我已更新代码以处理SPC / CKC为我们的DRM密钥提供商。

我是否错过了实现代码的一些重要部分来处理FPS Streaming的音频?你能指点我正确的方向吗?非常感谢。

class PlayHelper {

    static let shared = PlayHelper()

    fileprivate var playerViewController: PlayerViewController?

    init() {

        AssetPlaybackManager.sharedManager.delegate = self
    }

    // Play video without DRM
    func playVideo(from urlString: String, at context: UIViewController) {

        guard let videoURL = URL(string: urlString) else {
            Log.error("Video URL can't be created from string: \(urlString)")
            return }

        let player = AVPlayer(url: videoURL)

        let playerViewController = PlayerViewController()
        playerViewController.player = player

        context.present(playerViewController, animated: true) {
            playerViewController.player?.play()
        }
    }

    // Play FPS video
    func playFpsVideo(with asset: AVURLAsset, at context: UIViewController) {

        // Cleanup, should be done when playerViewController is actually dismissed
        if self.playerViewController != nil {
            // The view reappeared as a results of dismissing an AVPlayerViewController.
            // Perform cleanup.
            AssetPlaybackManager.sharedManager.setAssetForPlayback(nil)
            self.playerViewController?.player = nil
            self.playerViewController = nil
        }

        let item = AVPlayerItem(asset: asset)

        let player = AVPlayer(playerItem: item)

        // Customize player
        player.appliesMediaSelectionCriteriaAutomatically = true

        let playerViewController = PlayerViewController()
        playerViewController.player = player

        self.playerViewController = playerViewController

        context.present(playerViewController, animated: true) {
            playerViewController.player?.play()
        }
    }

    // Stop video
    func stop() {

        // Cleanup, should be done when playerViewController is dismissed
        if self.playerViewController != nil {

            // Results of dismissing an AVPlayerViewController, perform cleanup
            AssetPlaybackManager.sharedManager.setAssetForPlayback(nil)
            self.playerViewController?.player = nil
            self.playerViewController = nil
        }
    }
}


// MARK: - Extend `PlayHelper` to conform to the `AssetPlaybackDelegate` protocol

extension PlayHelper: AssetPlaybackDelegate {

    func streamPlaybackManager(_ streamPlaybackManager: AssetPlaybackManager, playerReadyToPlay player: AVPlayer) {

        player.play()
    }

    func streamPlaybackManager(_ streamPlaybackManager: AssetPlaybackManager, playerCurrentItemDidChange player: AVPlayer) {

        guard let playerViewController = playerViewController, player.currentItem != nil else { return }

        playerViewController.player = player
    }
}

如果需要,我还可以在AssetLoaderDelegateAssetPlaybackManager中提供代码。

1 个答案:

答案 0 :(得分:1)

我的坏。我在上面的代码中调用了userhash := hasher("admin") passhash := hasher("$CrazyUnforgettablePassword?") realm := "Please enter username and password" http.HandleFunc("/", authHandler(indexHandler, userhash, passhash, realm)) // Above code should obviously be in main() along with the http listener, etc. // hasher uses package "crypto/sha256" func hasher(s string) []byte { val := sha256.Sum256([]byte(s)) return val[:] } func authHandler(handler http.HandlerFunc, userhash, passhash []byte, realm string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user, pass, ok := r.BasicAuth() if !ok || subtle.ConstantTimeCompare(hasher(user), userhash) != 1 || subtle.ConstantTimeCompare(hasher(pass), passhash) != 1 { w.Header().Set("WWW-Authenticate", `Basic realm="`+realm+`"`) http.Error(w, "Unauthorized.", http.StatusUnauthorized) return } handler(w, r) } } 两次...... Grrr ..一次play()的演示完成,第二次来自PlayerViewController的回调,由KVO在{{{{}}触发1}}。这样播放器控制停止播放视频,但很可能第二(音频)流仍然在那里播放。我删除了AssetPlaybackDelegate回调中的AssetPlaybackManager,现在播放器中的所有控件都按预期工作。我可以暂停,恢复,寻找,改变音轨。