iOS音视频播放-AVPlayer简单使用

article/2025/10/2 14:41:32

按公司需求需要对音频文件进行后台播放,借此机会对音频播放做了个总结.主要针对 AVPlayer 进行详细说明.

iOS 各播放器比较

名称使用环境优点确点
System Sound ServicesAVFoundationC语言的底层写法,节省内存支持的格式有限,音量无法通过音量键控制,而且播放方式单一。
AVAudioPlayerAVFoundation抒写效率更高,基本上支持所有的音频格式,对播放的控制,如循环播放,声音大小,暂停等比较方便。对内存的消耗会多些。不支持流式,即无法播放在线音乐。
AVPlayerAVFoundation可以播放音视频,可播放在线音乐,使用灵活
MPMoviePlayerControllerMediaPlayer简单易用不可定制
AVPlayerViewControllerAVKit简单易用不可定制
IJKPlayerIJKMediaFramework定制度高,支持流媒体播放使用稍复杂

AVPlayer 使用

简介

AVPlayer 是iOS上常用的视频播放器组件,支持常见的音视频格式,支持流播放,可以播放在线音乐.
支持视频格式: WMV,AVI,MKV,RMVB,RM,XVID,MP4,3GP,MPG等。
支持音频格式:MP3,WMA,RM,ACC,OGG,APE,FLAC,FLV等。

相关类

  • AVPlayer:播放器,控制播放器的播放,暂停,播放速度.
  • AVURLAsset : AVAsset 的一个子类,使用 URL 进行实例化,实例化对象包换 URL 对应视频资源的所有信息.
  • AVPlayerItem:管理资源对象,提供播放数据源.
  • AVPlayerLayer:负责显示视频,如果没有添加该类,只有声音没有画面.

简单使用

使用 url 创建 AVPlayer

let player = AVPlayer(url: URL(string: "http://www.xxxx.mp3"))

使用 AVPlayerItem 创建 AVPlayer

if let url = URL(string: "http://www.***.mp3") {let asset = AVAsset(url: url)guard asset.isPlayable else{// 检测文件是否可播放return}let playItem = AVPlayerItem(asset: asset)let player = AVPlayer(playerItem: playItem)player.play()
}

AVPlayer 控制播放

player.play() // 播放
player.pause() //暂停
player.rate = 1.0 // 播放速度 

通过通知监听播放状态变化

//播放完成
AVPlayerItemDidPlayToEndTimeNotification
//播放失败
AVPlayerItemFailedToPlayToEndTimeNotification
//异常中断
AVPlayerItemPlaybackStalledNotification// eg: 播放结束通知
NotificationCenter.default.addObserver(self, selector: #selector(finish(_:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)

监听播放进度

// 添加周期时间观察者 一秒执行一次 block
let timeObserver = player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: 1), queue: DispatchQueue.main, using: { [weak self] (cmTime) inif let totalTime = self?.currentPlayItem?.duration {self?.delegate?.player(self!, currentTime: cmTime.seconds, totalTime: totalTime.seconds)}
})
// 不要忘记移除
player.removeTimeObserver(observer)

AVPlayerItem 创建

// 使用 AVAsset 创建
if let url = URL(string: "http://www.***.mp3") {let asset = AVAsset(url: url)guard asset.isPlayable else{// 检测文件是否可播放return}let playItem = AVPlayerItem(asset: asset)
}// 使用 URL 创建
if let url = URL(string: "http://www.***.mp3") {let playItem = AVPlayerItem(url: url)
}

监听 AVPlayerItem 状态和缓存进度

// 监听 playerItem 状态变化
playItem.addObserver(self, forKeyPath: "status", options: .new, context: nil)
// 监听缓存时间
playItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: .new, context: nil)// 移除监听
currentPlayItem?.removeObserver(self, forKeyPath: "status")
currentPlayItem?.removeObserver(self, forKeyPath: "loadedTimeRanges")
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {if object is AVPlayerItem {if keyPath == "status" {if let playerItem = object as? AVPlayerItem {switch playerItem.status {case .readyToPlay:// 准备播放case .failed:// 加载失败                    default:// 未知状态}}}if keyPath == "loadedTimeRanges" {if let playerItem = object as? AVPlayerItem {if let timeRange = playerItem.loadedTimeRanges.first as? CMTimeRange {let cache = timeRange.start.seconds + timeRange.duration.seconds // 缓存总时长}}}}

音频后台播放

开启所需后台模式

选中Targets–>Capabilities–>BackgroundModes–>ON,
并勾选Audio and AirPlay选项,如下图:
权限

或者 plist 文件添加如下字段:
plist

利用 AVAudioSession 申请后台播放权限

let session = AVAudioSession.sharedInstance()
do {try session.setActive(true)try session.setCategory(AVAudioSessionCategoryPlayback)
} catch {print(error)
}

在播放控制界面接受远程控制(Remote Control)

开启远程控制

// 声明接收Remote Control事件
UIApplication.shared.beginReceivingRemoteControlEvents()

设置 Remote Control 响应

// 响应 Remote Control事件
MPRemoteCommandCenter.shared().playCommand.addTarget(self, action: #selector(play))
MPRemoteCommandCenter.shared().nextTrackCommand.addTarget(self, action: #selector(next))
MPRemoteCommandCenter.shared().pauseCommand.addTarget(self, action: #selector(pause))
MPRemoteCommandCenter.shared().previousTrackCommand.addTarget(self, action: #selector(previous))

移除 Remote Control 响应

// 在关闭播放页面时记得移除
MPRemoteCommandCenter.shared().playCommand.removeTarget(self, action: #selector(play))
MPRemoteCommandCenter.shared().nextTrackCommand.removeTarget(self, action: #selector(next))
MPRemoteCommandCenter.shared().pauseCommand.removeTarget(self, action: #selector(pause))
MPRemoteCommandCenter.shared().previousTrackCommand.removeTarget(self, action: #selector(previous))
// 停止响应 Remote Control
UIApplication.shared.endReceivingRemoteControlEvents()

通过重写父类方法响应外部事件

  • 开启接受远程控制

  • 使当前页面成为第一响应者

  • 重写 remoteControlReceivedWithEvent 方法. UIEvent Type 取值:

    • UIEventSubtypeRemoteControlTogglePlayPause // 暂停
    • UIEventSubtypeRemoteControlPreviousTrack // 上一首
    • UIEventSubtypeRemoteControlNextTrack // 下一首
    • UIEventSubtypeRemoteControlPlay // 播放
    • UIEventSubtypeRemoteControlPause // 暂停
  • 关闭接受远程控制

锁屏页面显示播放信息(Now Playing Center)

使用 MPNowPlayingInfoCenter 设置锁屏页面音乐信息.

func setLockScreenPlayingInfo(_ info: YTTMediaInfo) {// Now Playing Center可以在锁屏界面展示音乐的信息,也达到增强用户体验的作用。// https://www.jianshu.com/p/458b67f84f27var infoDic: [String : Any] = [:]infoDic[MPMediaItemPropertyTitle] = info.title // 歌曲名infoDic[MPMediaItemPropertyArtist] = info.singer // 歌手if let img = info.image {infoDic[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(image: img) // 专辑图片}infoDic[MPMediaItemPropertyPlaybackDuration] = info.totalTime // 歌曲总时长infoDic[MPNowPlayingInfoPropertyElapsedPlaybackTime] = info.currentTime // 当前播放时间infoDic[MPNowPlayingInfoPropertyPlaybackRate] = 1.0 // 播放速度MPNowPlayingInfoCenter.default().nowPlayingInfo = infoDic
}

注意: MPNowPlayingInfoPropertyElapsedPlaybackTime 设置的并不是时时的,他是根据你设置的值进行计时的,如果想要在锁屏页面得到准确的时间,请及时刷新 MPNowPlayingInfoPropertyElapsedPlaybackTime 的值.当暂停时要暂停播放时间,只需将 MPNowPlayingInfoPropertyPlaybackRate 设置为 0.播放时设置回 1.

补充说明

iOS 对后台管理十分严格,任何 app 都有大约3分钟或者10分钟的后台执行时间.3分钟或者10分钟后, app 就会被强制挂起.使用 AVAudioSession 申请后台权限时,可以保证播放本地音乐能在后台长久播放,当播放网络音乐时就会出现不能播放情况,针对这情况使用了 beginBackgroundTask 设置后台任务 ID,通过这种方式我们大约可以获得额外的 10 分钟来执行后台任务.为了能无限后台播放网络音乐添加计时器,当即将挂起时再次申请后台任务 ID.

func applicationDidEnterBackground(_ application: UIApplication) {// 这样做,可以在按home键进入后台后 ,播放一段时间,几分钟吧。但是不能持续播放网络歌曲,若需要持续播放网络歌曲,还需要申请后台任务idbgTask = application.beginBackgroundTask(expirationHandler: nil)timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}@objc func timerAction() {timerCount = timerCount + 1if timerCount < 500 {return}timerCount = 0let newTask = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)if bgTask != UIBackgroundTaskInvalid && newTask != UIBackgroundTaskInvalid {UIApplication.shared.endBackgroundTask(bgTask)bgTask = newTask}}

遇到的坑

关于 rate 倍数播放

对于 AVPlayer 的暂停和播放是通过 rate 的值来判断的,但 rate 为 1 时.播放状态,但其为 0 时为暂停.每次调用 play() 方法时,rate 的值都将会置为 1,所以当调用 play 方法时,需要重新设置 rate 的值.

关于AVPlayerItem 切换

在 iOS9 以上系统测试时AVPlayerItem切换正常,但当在 iOS8 系统下,切换了AVPlayerItem 发现无法进行播放,针对这进行百度得到解决方式,iOS8 对于replaceCurrentItem方法支持不是很好,需要每次重新创建 AVPlayer.

其他

  • AVPlayer那些坑
  • 项目参考地址

http://chatgpt.dhexx.cn/article/YeWPY6rs.shtml

相关文章

iOS音视频播放指南(二)

1. 让你的App支持画中画 画中画指可以让视频在小窗中播放,可以一边看视频一边刷知乎 你可以使用AVPlayerViewController或者AVPictureInPictureController来实现画中画播放。 其中AVPictureInPictureController支持你自定义一些播放控件 在支持画中画播放之前,确保你按照iOS音视…

iOS音视频播放指南(一)

1. 简介 苹果目前提供两个框架用来处理音视频播放 1.AVFoundation AVFoundation用于播放、处理音视频。可以通过结构图看到AVFoundation位于UIKit之下,很好理解AVFoundation并不提供用户界面,你可以自己自己构建用户界面来控制媒体的播放处理等功能。 但是苹果更推荐使用AVKit来…

iOS视频播放的基本方法

本文总结了iOS中最常见的视频播放方法&#xff0c;不同的方法都各具特点&#xff0c;我希望能够总结它们的不同&#xff0c;方便在开发中选择合适的技术方案。 Apple为我们提供了多种方法来实现视频播放&#xff0c;包括MPMoviePlayerController&#xff0c;MPMoviePlayerView…

【计算机系统1】4 Nim游戏

目录 目的与要求 内容与方法 步骤与过程 程序总体设计 核心数据结构及算法流程 核心代码 调试过程 界面展示子程序DISPLAY&#xff08;嵌套&#xff1a;球数展示子程序PUTBALL&#xff09; 游戏子程序GAME&#xff08;嵌套&#xff1a;单人每轮子程序PLAY&#xff09; 结论或体…

java nim游戏_LeetCode 292. Nim游戏

题目描述&#xff1a; 你和你的朋友&#xff0c;两个人一起玩 Nim游戏&#xff1a;桌子上有一堆石头&#xff0c;每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。 你们是聪明人&#xff0c;每一步都是最优解。 编写一个函数&#xff0c;来判断你…

Nim游戏、3的幂、4的幂

&#x1f345; Java学习路线&#xff1a;Java学习路线 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、CSDN哪吒公众号作者✌ 、Java架构师奋斗者&#x1f4aa; &#x1f345; 百日刷题计划&#xff1a;第 12 / 100 天。 &#x1f345; 扫描主页左侧二维码&a…

【数论】博弈论 —— nim游戏

知识点 一 . nim游戏的数学定义 Nim游戏是博弈论中最经典的模型&#xff0c;它又有着十分简单的规则和无比优美的结论 。 Nim游戏是组合游戏(Combinatorial Games)的一种&#xff0c;准确来说&#xff0c;属于“Impartial Combinatorial Games”&#xff08;以下简称ICG&#…

【模板题】几种常见的Nim游戏(博弈论)

一、AcWing 891. Nim游戏 【题目描述】 给定 n n n堆石子&#xff0c;两位玩家轮流操作&#xff0c;每次操作可以从任意一堆石子中拿走任意数量的石子&#xff08;可以拿完&#xff0c;但不能不拿&#xff09;&#xff0c;最后无法进行操作的人视为失败。 问如果两人都采用最优…

Kafka 为什么能那么快 | Kafka高效读写数据的原因

点击上方“服务端思维”&#xff0c;选择“设为星标” 回复”669“获取独家整理的精选资料集 回复”加群“加入全国服务端高端社群「后端圈」 无论 kafka 作为 MQ 也好&#xff0c;作为存储层也罢&#xff0c;无非就是两个功能&#xff08;好简单的样子&#xff09;&#xff0c…

【人人都懂密码学】一篇最易懂的Java密码学入门教程

密码与我们的生活息息相关&#xff0c;远到国家机密&#xff0c;近到个人账户&#xff0c;我们每天都在跟密码打交道&#xff1a; 那么&#xff0c;密码从何而来&#xff1f;生活中常见的加密是怎么实现的&#xff1f;怎么保证个人信息安全&#xff1f;本文将从这几方面进行浅谈…

Kafka必须掌握的核心技术--为什么吞吐量大、速度快?

点击上方“服务端思维”&#xff0c;选择“设为星标” 回复”669“获取独家整理的精选资料集 回复”加群“加入全国服务端高端社群「后端圈」 Kafka是大数据领域无处不在的消息中间件&#xff0c;目前广泛使用在企业内部的实时数据管道&#xff0c;并帮助企业构建自己的流计算应…

哪些软件问题也可导致硬盘录像机死机

硬盘录像机死机除了一些硬件上的问题之外&#xff0c;也有不少是由软件引起的。如&#xff1a; 1、病毒感染 病毒是计算机操作的大患&#xff0c;几乎人人恶之。病毒可以使计算机工作效率急剧下降&#xff0c;造成频繁死机、数据丢失、系统崩溃&#xff0c;甚至损坏主板、硬盘、…

导致硬盘录像机卡死的十大原因分析

硬盘录像机卡死除了一些技术上的问题之外&#xff0c;也有不少是由软件引起的。如&#xff1a; 1、病毒感染 病毒是硬盘录像机操作的大患&#xff0c;几乎人人恶之。病毒可以使硬盘录像机工作效率急剧下降&#xff0c;造成频繁死机、数据丢失、系统崩溃&#xff0c;甚至损坏主板…

谈项目管理和软件测试过程

谈项目管理和软件测试过程&#xff08;一&#xff09; 1. 软件测试在公司的组织保障是基础 1.1 研发部组织结构介绍 以华友公司研发部的组织结构为例&#xff0c;测试部门属于研发部副总裁直接管理&#xff0c;见如下结构图 公司研发部的组织结构图 …

NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

一、NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起&#xff0c;传统的关系数据库在应付Web2.0网站&#xff0c;特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经显得力不从心&#xff0c;暴露了很多难以克服的问题&#xff1a; &#xff08;1…

软件公司面试总结

文章目录 面试1面试2面试3面试4面试5面试6 面试1 1、你先做个简单的自我介绍吧 我叫张三&#xff0c;2015年在重庆邮电大学毕业。我读的专业是电子信息。工作已经快5年了。 我上家公司的主营业务是在柬埔寨做移动支付钱包。 最近做的一个项目是聚合支付的项目&#xff0c;主要…

腾讯的硬盘里,有互联网的昨天今天和明天

作者&#xff1a;史中 来源&#xff1a;浅黑科技&#xff08;qianheikeji&#xff09; 2018年1月1日&#xff0c;太阳照常升起。 世界上所有的时钟合谋&#xff0c;把最后一个90后推过了18岁的门槛。对于这些年轻的面孔来说&#xff0c;自由的风终于如期而至&#xff0c;只是其…

机械硬盘与SSD固态硬盘性能的深度

从7200转硬盘升级到10000转的迅猛龙&#xff0c;那叫量变。从10000转的迅猛龙升级到SSD&#xff0c;这个叫质变。2者的差距是有些地方相当大&#xff0c;而有些却很接近&#xff0c;主要是难比较。经常听到有人说&#xff1a;我买2个黑盘组RAID 0&#xff0c;传输率也有接近250…

sudo rm-rf引发的惨案——Linux硬盘的分区和挂载

前言 前不久&#xff0c;刚使用组里的一台服务器&#xff0c;这台服务器平时用的人不多&#xff0c; 没有严格的管理机制&#xff0c;大家都使用同一个用户名进行远程连接&#xff0c;人人都有sudo权限。我因为对Linux不是非常熟悉&#xff0c;使用管理员权限下执行了一个删除…

DVR-硬盘录像机

硬盘录像机&#xff08;Digital Video Recorder&#xff0c;简称DVR&#xff09;&#xff0c;即数字视频录像机&#xff0c;相对于传统的模拟视频录像机&#xff0c;采用硬盘录像&#xff0c;故常常被称为硬盘录像机&#xff0c;也被称为DVR。 它是一套进行图像存储处理的计算…