二.AV Foundation 视频播放 - 创建播放器

引言

当我们探讨播放功能时,上一篇文章简要介绍了与核心类和API相关的内容,并提供了一个简单的播放案例。然而,实际使用视频播放器时,我们通常不会采用类似的写法,而是更倾向于构建一个完整、可重用的播放组件。在接下来的部分,让我们深入探讨创建播放组件的过程。

本篇博客我们先来实现一个简单的仅可播放的是播放组件,后续会不断地丰富它的功能。

创建播放视图

首先我们创建一个可以用来显示视频内容的视图,创建一个名PHPlayerView的类。

Swift 复制代码
import UIKit
import AVFoundation

class PHPlayerView: UIView {

    /// 重写layerClass方法,
    override class var layerClass: AnyClass{
        get {
            return AVPlayerLayer.self
        }
    }
    
    /// 重写init方法
    ///
    /// - Parameters:
    ///   - player: 播放器
    init(player:AVPlayer) {
        super.init(frame: CGRectZero)
        guard let playerLayer = self.layer as? AVPlayerLayer else { return }
        playerLayer.player = player
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

1.通过重写layerClass熟悉的get方法,使得AVPlayerLayer为PHPlayerView的支持图层。

2.自定义一个init方法将player与AVPlayerLayer图层进行关联。

创建视频控制器

视频控制器里面封装了我们创建的播放器组件的所有功能,也是我们处理系统核心播放API的地方。创建一个名为PHPlayerController的类。

Swift 复制代码
import UIKit
import AVFoundation

let status_keypath = "status"
var playerItemContext = 0

class PHPlayerController: NSObject {
    
    /// 资源
    private var asset:AVAsset?
    /// AVPlatyerItem
    private var playerItem:AVPlayerItem?
    /// AVPlayer
    private var player:AVPlayer?
    /// 播放视图
    private var playerView:PHPlayerView?
    /// 只读属性view返回PHPlayerView实例
    var view:UIView? {
        get {
            return playerView
        }
    }
    
    /// 重写init方法
    ///
    /// - Parameters:
    ///   - url: 资源URL
    init(url:URL) {
        super.init()
        asset = AVAsset(url: url)
        prepareToPlay()
    }
    
    
    /// 准备播放
    private func prepareToPlay() {
        let keys = ["tracks","duration","commonMetadata"]
        guard let asset = asset else { return }
        playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: keys)
        guard let playerItem = playerItem else { return }
        player = AVPlayer(playerItem: playerItem)
        guard let player = player else { return }
        playerView = PHPlayerView(player: player)
        playerItem.addObserver(self, forKeyPath: status_keypath, context: &playerItemContext)
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if context == &playerItemContext {
            guard let playerItem = playerItem else { return }
            guard let player = player else { return }
            if playerItem.status == .readyToPlay{
                playerItem.removeObserver(self, forKeyPath: status_keypath)
                player.play()
            }
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }

}

1.在PHPlayerController中定义了一系列的视频播放使用的对象,还有视频播放视图PHPlayerView的实例,以及一个只读属性view返回播放视图。

2.自定义初始化方法传入资源的URL。

3.定义私有方法prepareToPlay创建播放器及播放视图,通过init (asset: AVAsset, automaticallyLoadedAssetKeys: [String]?)方法,让框架自动载入资源的tracks,duration,commonMetadata属性,使用KVO监听AVPlayerItem的status属性。

4.实现监听的方法,当属性由.unknown变为.readyToPlay的时候,palyer调用playe方法来进行视频播放。

播放组件使用

一个带有视频播放功能的播放组件就已经构建完成了,下面我们就在视图控制器来开始使用它。

Swift 复制代码
class ViewController: UIViewController {

    /// 播放控制器
    var playerController:PHPlayerController?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let url = Bundle.main.url(forResource: "waves", withExtension: "mp4")  else { return }
        playerController = PHPlayerController(url: url)
        guard let playerView = playerController?.view else { return }
        playerView.frame = view.bounds
        view.addSubview(playerView)
    }
}

结语

使用的代码并不多,但我们的确已经实现了一个可以播放的视频组件,下面我们会逐步的往组件中添加播放,暂停,快进等各种提升用户体验的功能。

相关推荐
码农阿强8 分钟前
技术解析|doubao‑seedance 全系列模型深度解读:API 开放生态赋能 AI 视频生成工程化
人工智能·音视频
大拿爱科技9 分钟前
声音克隆接入短视频流程时,哪些环节最容易出问题?
人工智能·aigc·音视频·语音识别
DogDaoDao22 分钟前
libaom源码search_intra_modes_in_interframe函数深度分析
音视频·视频编解码·av1·libaom·帧内预测·预测编码·预测模式
网管NO.130 分钟前
视频核心技术 03:H.264 / H.265 / AV1 编码标准对比 —— 压缩率、复杂度、适用场景
音视频·h.265·h.264
黄昏恋慕黎明33 分钟前
音视频测试
音视频
果果开发ggdoc.cn1 小时前
我找到一个在线视频处理工具,不用上传,本地就能转格式、提取音频和字幕
音视频
网管NO.11 小时前
视频核心技术 05:流媒体传输协议 —— RTMP、HLS、WebRTC 怎么选?延迟、卡顿、原理全解
音视频
呉師傅1 小时前
将CD音频抓轨转换成MP3的两种方法【图文解释】
运维·服务器·网络·windows·电脑·音视频
愚公搬代码1 小时前
【愚公系列】《AI漫剧创作一本通》024-Al 漫剧视频生成(AI漫剧视频生成工具)
人工智能·音视频
沉浸式学习ing16 小时前
B站视频怎么快速总结?AI自动生成要点+思维导图+逐字稿
人工智能·ai·自然语言处理·音视频·语音识别·notion