美文网首页程序员
如何使用AVPlayerViewController在线、离线播

如何使用AVPlayerViewController在线、离线播

作者: zhonglaoban | 来源:发表于2018-09-12 17:31 被阅读369次

    使用AVPlayerViewController在线、离线播放hls

    这篇文章演示了如何使用AVPlayerViewController播放hls,并且涉及了如何开始、暂停,如何下载、存储一个hls的播放。github地址!

    使用这个示例

    请在iOS 11.0或之后的真机上使用Xcode编译、运行此示例。示例中的这些APIs不支持在模拟器中工作。

    在线播放hls

    AVPlayer有很多初始化方式,我们这里采用最简单的通过url初始化。
    AVPlayerViewController可以快速的创建一个播放器,使用简单。
    AVPlayer设置给AVPlayerViewController,就能播放视频啦。

    guard let url = URL(string: "http://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8") else { return }
    let onlinePlayer = AVPlayer(url: url)
    playerViewController?.player = onlinePlayer
    

    离线播放hls

    在iOS10 之后,苹果为AVAssetDownloadTask提供了一个方法makeAssetDownloadTask用来下载hls。需要注意的是,下载下来的hls必须是一个AVURLAsset,它在本地存储为movpkg格式。

    初始化配置并下载hls

    创建一个类DownloadManager,添加URLSessionConfigurationAVAssetDownloadURLSession的实例作为属性。init()的时候初始化属性。在这里我们可以设置一个代理为自己,我们在代理方法里面就可以监听到一些下载相关的事件。

    private var config: URLSessionConfiguration!
    private var downloadSession: AVAssetDownloadURLSession!
    
    config = URLSessionConfiguration.background(withIdentifier: "background")
    downloadSession = AVAssetDownloadURLSession(configuration: config, assetDownloadDelegate: self, delegateQueue: OperationQueue.main)
    

    获取下载进度和下载的位置

    实现代理方法didLoad,它有三个值:

    • timeRange:上一次调用的时间
    • loadedTimeRanges:已下载每个资源耗费的时间
    • timeRangeExpectedToLoad:总预期的时间

    我们可以计算每一个资源的进度,综合起来就是这个下载任务的进度。然后我们把得到的进度以通知的形式发送给监听者。

    func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) {
        var percentComplete = 0.0
            
        for value in loadedTimeRanges {
            
            let loadedTimeRange = value.timeRangeValue
            
            percentComplete += loadedTimeRange.duration.seconds / timeRangeExpectedToLoad.duration.seconds
        }
        
        debugPrint("Progress \( assetDownloadTask) \(percentComplete)")
        
        let params = ["percent": percentComplete]
        NotificationCenter.default.post(name: .DownloadProgressNotification, object: nil, userInfo: params)
    }
    

    当文件下载完成时,会通过didFinishDownloadingTo代理方法告诉我们下载位置。我们把这个位置存起来,就可以在任何其他地方获取并使用了。我这里是使用task的taskDescription作为key存在了UserDefaults中。

    func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didFinishDownloadingTo location: URL) {
        print(location)
        guard let assetKey = assetDownloadTask.taskDescription else {
            return
        }
        UserDefaults.standard.set(location, forKey:assetKey)
        UserDefaults.standard.synchronize()
    }
    

    读取并播放hls

    我先用UserDefaults取出之前下载完成的文件地址,然后返回一个AVPlayerItem实例给AVPlayer使用,这样就可以播放之前下载好的hls了。

    func getPlayerItem(_ assetKey:String) -> AVPlayerItem? {
        guard let location = UserDefaults.standard.url(forKey: assetKey) else {
            return nil
        }
        if (!FileManager.default.fileExists(atPath: location.relativePath)) {
            return nil
        }
        let asset = AVURLAsset(url: location)
        let playerItem = AVPlayerItem(asset: asset)
        return playerItem
    }
    

    Requirements

    Build

    Xcode 9.0 or later; iOS 11.0 SDK or later

    Runtime

    iOS 11.0 or later.

    Copyright (C) 2017 Apple Inc. All rights reserved.

    相关文章

      网友评论

        本文标题:如何使用AVPlayerViewController在线、离线播

        本文链接:https://www.haomeiwen.com/subject/wsunsftx.html