Skip to content

使用AVPlayerViewController在线、离线播放hls

Notifications You must be signed in to change notification settings

zhonglaoban/HLS-Stream

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

使用AVPlayerViewController在线、离线播放hls

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

使用这个示例

请在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.

About

使用AVPlayerViewController在线、离线播放hls

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages