五.AV Foundation 视频播放 - 标题和字幕

引言

本篇博客主要介绍使用AV Foundation加载视频资源的时候,如何获取视频标题,获取字幕并让其显示到播放界面。

设置标题

资源标题的元数据内容,我们需要从资源的commonMetadata中获取,在加载AVPlayerItem的时候我们已经指定了需要加载commonMetadata数据,所以这里不需要做任何改动,可以在AVPlayerItem的status变为.readyToPlay的时候直接读取标题内容。

添加方法

首先我们需要在PHControlDelegate中添加两个代理方法,分别对应设置视频标题和设置设置字幕标题,并在PHControlView中实现。

protocol PHControlDelegate:NSObjectProtocol {var delegate:PHPlayerDelegate? { get set }/// 开始播放func playstart()/// 设置当前时间////// - Parameters:///   - time: 当前时间///   - duration: 总时间func setCuttentTime(time:TimeInterval,duration:TimeInterval)/// 设置视频标题////// - Parameters:///   - title: 标题func setTitle(title:String)/// 设置字幕标题////// - Parameters:///   - titles: 字幕标题数组func setSubtitle(titles:[String])/// 播放完成func playbackComplete()
}

设置标题代理方法的实现。

// 设置标题func setTitle(title: String) {titleLabel.text = title}



加载commonMetadata数据

首先来看一下创建AVPlayerItem的时候加载commonMetadata的实现。

/// 准备播放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)self.delegate = playerView?.controlViewself.delegate?.delegate = selfplayerItem.addObserver(self, forKeyPath: status_keypath, context: &playerItemContext)}

获取标题数据

在视频准备好播放后,从commonMetadata中获取我们需要的视频标题数据。

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()let duration = playerItem.duration// 同步页面开始播放self.delegate?.playstart()// 同步时间self.delegate?.setCuttentTime(time: 0.0, duration: CMTimeGetSeconds(duration))// 设置标题let assetTitle = assertTitle()self.delegate?.setTitle(title: assetTitle)// 监听播放进度addPlayerItemTimeObserver()}} else {super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)}}

获取标题数据。

/// 获取func assertTitle() -> String {var title = ""guard let asset = asset else { return title }let status = asset.status(of: .commonMetadata)if case .loaded(let metatadaItems) = status {let titleItem = metatadaItems.firstlet itemStatus = titleItem?.status(of: .value)if case .loaded(let value) = itemStatus {if let itemTitle = value as? String {title = itemTitle}}}return title}

再次运行播放器会发现播放器的左上角已经显示出了视频的标题。

设置字幕

AV Foundation为显示字幕提供了非常可靠的方法,AVPlayerLayer会自动渲染这些元数据到页面上,并且还可以手动选择需要显示那种字幕。要完成这个功能需要用到AVMediaSelectionGrop和AVMediaSelectionOption这两个类。
 

AVMediaSelectionOption标识AVAsset中的备用媒体呈现方式。比如备用音频、视频或者文本轨道。想要确定存在哪些备用轨道要用到一个名为availableMediaCharacteristicsWithMediaSelectionOptions属性。它会返回一个包含字符串的数组,这些字符串用于表示保存在资源中可用选项的媒体特征,包含AVMediaCharacteristicVisual(视频),AVMediaCharacteristicAudible(音频)、AVMediaCharacteristicLegible(字幕或隐藏式字幕)。

请求可用媒体特性数据后,调用AVAsset的mediaSelectionGroupForMediaCharacteristic:方法,(iOS16后推荐使用loadMediaSelectionGroup(for mediaCharacteristic: AVMediaCharacteristic) 方法),为其传递要检索的选项的特定媒体特征。这个方法会返回一个AVMediaSelectionGroup,它作为一个或多个互斥的AVMediaSelectionOption实例的容器。

加载availableMediaCharacteristicsWithMediaSelectionOptions数据

下面就在视频准备开始播放的时候进行字幕数据的加载,在这之前呢和加载其它元数据一样需要在创建AVPlayerItem的时候指定所需加载的元数据。

 /// 准备播放private func prepareToPlay() {let keys = ["tracks","duration","commonMetadata","availableMediaCharacteristicsWithMediaSelectionOptions"]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)self.delegate = playerView?.controlViewself.delegate?.delegate = selfplayerItem.addObserver(self, forKeyPath: status_keypath, context: &playerItemContext)}

获取字幕数据

在监听到视频状态转换为.readyToPlay时开始调用方法处理字幕数据。

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()let duration = playerItem.duration// 同步页面开始播放self.delegate?.playstart()// 同步时间self.delegate?.setCuttentTime(time: 0.0, duration: CMTimeGetSeconds(duration))// 设置标题let assetTitle = assertTitle()self.delegate?.setTitle(title: assetTitle)// 设置字幕let subtitles = loadMediaOptions()self.delegate?.setSubtitle(titles: subtitles)// 监听播放进度addPlayerItemTimeObserver()}} else {super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)}}

加载字幕方法实现。

/// 加载字幕func loadMediaOptions() -> [String] {var subtitles = [String]()guard let asset = asset else { return subtitles }let mc = AVMediaCharacteristic.legibleasset.loadMediaSelectionGroup(for: mc) {[weak self] selectionGroup, error inguard let self = self, let selectionGroup = selectionGroup else { return }// 获取字幕选项for option in selectionGroup.options {let displayName = option.displayNamesubtitles.append(displayName)}}return  subtitles}

字幕选择页面实现

获取到字幕数据后,我们借助delegate将其专递到了PHControlView中供使用,目前在控制页面还没有选择字幕的按钮,先来把它添加到播放器的右上角,并实现点击事件。

实现代理方法

// 设置字幕标题func setSubtitle(titles: [String]) {subtitles = titles}

实现点击事件。

// 显示字幕列表@objc func subtitleOnclick() {guard let subtitles = subtitles else { return }guard let delegate = delegate else { return }let alertViewController = UIAlertController(title: "选择字幕", message: nil, preferredStyle: .actionSheet)for subtitle in subtitles {let action = UIAlertAction(title: subtitle, style: .default) { action indelegate.selectedSubtitle(subtitle: subtitle)}alertViewController.addAction(action)}let cancel = UIAlertAction(title: "取消字幕", style: .cancel)alertViewController.addAction(cancel)self.window?.rootViewController?.present(alertViewController, animated: true)}

显示字幕

在播放控制器内,接收选择的字幕信息开始设置字幕。

/// 指定字幕////// - Parameters:///   - subtitle: 字幕名称func selectedSubtitle(subtitle: String) {guard let asset = asset else { return }guard let playerItem = playerItem else { return }let mc = AVMediaCharacteristic.legibleasset.loadMediaSelectionGroup(for: mc) {[weak self] selectionGroup, error inguard let self = self, let selectionGroup = selectionGroup else { return }var selected = false// 获取字幕选项for option in selectionGroup.options {if option.displayName == subtitle {playerItem.select(option, in: selectionGroup)selected = truebreak}}if selected == false {playerItem.select(nil, in: selectionGroup)}}}

结语

显示标题和字幕的功能就完成了,主要就是读取AVAsset资源中的元数据并同步到视频播放的过程中,播放器的整体用户体验有了进一步的提升。到目前为止我们在处理的都是播放过程中是逻辑,但关于视频播放结束的处理也同样重要,下一篇博客就专门来介绍关于视频资源播放结束逻辑的实现。

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2809128.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

03|JOIN关联查询优化

1. mysql关联算法 1.1 嵌套循环连接 Nested-Loop Join(NLJ) 算法 先去t2表(驱动表)拿一行数据,然后去t1表(被驱动表)做关联, 关联之后把结果集存下来最后返回. 1.2 基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法 1.把 t…

Vulnhub靶机:DC8

一、介绍 运行环境:Virtualbox 攻击机:kali(10.0.2.15) 靶机:DC8(10.0.2.61) 目标:获取靶机root权限和flag 靶机下载地址:https://www.vulnhub.com/entry/dc-8,367/…

Linux字符设备驱动中同类型多设备节点的创建---一个驱动程序支持多个同类型设备

文章目录 前言1 代码解析1.1 驱动层1.2 应用层 2 运行结果总结 前言 本期分享的内容相对比较简单,那就是同时注册多个同类型的字符设备驱动,那么这样我们就可以同时支持多个同类型的设备了!下面来带大家看一下: 1 代码解析 1.1 …

基于springboot+vue的精准扶贫管理系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

从Unity到Three.js(outline 模型描边功能)

指定模型高亮功能,附带设置背景颜色,获取随机数方法。 百度查看说是gltf格式的模型可以携带PBR材质信息,如果可以这样,那就完全可以在blender中配置好材质导出了,也就不需要像在unity中调整参数了。 import * as THRE…

Autosar 开篇

背景 AUTOSAR(Automotive Open System Architecture)是一个跨汽车行业的标准化软件架构,旨在促进汽车电子系统的开发和部署。下面是AUTOSAR发展的一些关键点: 起源和背景: AUTOSAR最初于2003年由汽车制造商宝马、戴姆…

使用GPT生成python图表

首先,生成一脚本,读取到所需的excel表格 import xlrddata xlrd.open_workbook(xxxx.xls) # 打开xls文件 table data.sheet_by_index(0) # 通过索引获取表格# 初始化奖项字典 awards_dict {"一等奖": 0,"二等奖": 0,"三等…

MCU多核异构通信原理

摘要: 本文结合瑞萨RZ/G2L 多核处理器,给大家讲述一下多核异构设计及通信的原理。 随着电子技术的不断发展,以及市场需求的日益增长,嵌入式系统不仅要求执行复杂的控制任务,还需要实时地采集和处理数据。 为了满足这…

HarmonyOS开发行业前景就业分析与实例解析

HarmonyOS的简介 鸿蒙系统(HarmonyOS)是华为公司自主研发的一种全场景分布式操作系统,旨在为各种设备提供统一的开发和运行环境。它的编程基础主要建立在多种技术和语言之上,包括鸿蒙系统的核心框架和应用程序开发框架。 本章将…

Easy-Jmeter: 性能测试平台

目录 写在开始1 系统架构2 表结构设计3 测试平台生命周期4 分布式压测5 压力机管理6 用例管理6.1 新增、编辑用例6.2 调试用例6.3 启动测试6.4 动态控量6.5 测试详情6.6 环节日志6.7 实时数据6.8 测试结果 7 测试记录7 用例分析8 系统部署8.1普通部署8.2容器化部署 写在最后 写…

【技术分享】使用nginx完成动静分离➕集成SpringSession➕集成sentinel➕集成seata

🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于技术点的相关分享吧 目录 🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 一、 使用nginx完成动静分离 1.下载…

【数据集】世界水评估方案指标:灌溉面积/灌溉用水等

世界水评估方案指标 概述(Overview)数据下载(Data Download)案例1:F. Irrigated lands案例2:G. Irrigated water use参考World Water Development Report II-Indicators for World Water Assessment Programme 概述(Overview) 在关于全球环境变化和可持续发展的辩论…

微信小程序(1)- 小程序开发工具

1. 小程序开发工具下载 地址:官网 微信小程序账号只要开发者满足开发资质都可以进行注册,并且会获得对应的 开发者 ID。一个完整的开发者 ID 由 小程序 ID(AppID)和一个 小程序密钥(AppSecret)组成。小程…

JAVA算法和数据结构

一、Arrays类 1.1 Arrays基本使用 我们先认识一下Arrays是干什么用的,Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。 下面我们用代码来演示一下:遍历、拷贝、排序等操作。需要用到的方法如下 public…

嵌入式学习第二十天!(进程)

进程基本概念: 1. 进程: 程序:存放在外存中的一段数据组成的文件 进程:是一个程序动态执行的过程,包括进程的创建、进程的调度、进程的消亡 2. 进程相关命令: 1. top: 动态查看当前系统中的所有进程信息…

HarmonyOS—添加/删除Module

Module是应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。一个HarmonyOS应用/服务通常会包含一个或多个Module,因此,可以在工程中创建多个Module&#xff0…

docker部署grafana+zabbix监控

1. grafana介绍 Grafana 是一个开源的数据可视化工具,它可以帮助用户将数据源中的数据进行图形化展示和实时监控,以便于用户能够更加直观地理解数据。Grafana 支持多种数据源,包括 Graphite、Elasticsearch、InfluxDB、Prometheus 等&#x…

SpringBoot -【BeanFactory】基础使用及应用场景

1.介绍 在 Spring 框架中,BeanFactory 是 Spring IoC 容器的核心接口,负责管理 bean 的创建、配置和装配。它是 Spring IoC 容器的基础。BeanFactory 接口定义了一系列方法,用于管理和访问容器中的 bean 对象。 BeanFactoryAware 用于在 Sp…

相机图像质量研究(39)常见问题总结:编解码对成像的影响--运动模糊

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结:光学结构对成…

智慧医疗新篇章:山海鲸可视化引领行业变革

随着科技的不断发展,智慧医疗已经成为医疗行业的新趋势。山海鲸可视化以其独特的视角和前沿的技术,为智慧医疗提供了全方位的解决方案。其强大的数据可视化能力,使得医疗数据更加直观、易于理解。无论是病例分析、手术模拟,还是患…