没看第一篇的小伙伴可以先看第一篇

wlzz:iOS音视频播放指南(一)​zhuanlan.zhihu.com

本章主要内容

  1. 画中画支持
  2. 后台音频播放,锁屏界面显示,远程音频控制
  3. 在耳机插拔、接听电话等情况下处理音频业务逻辑

1. 让你的App支持画中画

画中画指可以让视频在小窗中播放,可以一边看视频一边刷知乎

你可以使用AVPlayerViewController或者AVPictureInPictureController来实现画中画播放。 其中AVPictureInPictureController支持你自定义一些播放控件

在支持画中画播放之前,确保你按照iOS音视频播放指南(一) 第三部分(3.音频设置 )完成相应的设置

  1. AVPlayerViewController

支持画中画播放最简单的方式就是使用 AVPlayerViewController 。如果你的设备支持画中画播放,使用AVPlayerViewController点击按钮就能看到效果。支持画中画播放的设备在视频播放的时候直接返回桌面,视频也会以画中画形式继续播放。

如果你返回桌面的时候视频不会以画中画形式继续播放,检测一下设置-通用-画中画。查看是否开启

但是当你想还原画中画视频的时候,AVKit在默认情况下会停止视频的播放(系统不知道如何处理你App的用户界面),我们需要自己实现代理来完成视频的恢复。

 let controller = AVPlayerViewController()controller.delegate = selfextension ViewController: AVPlayerViewControllerDelegate {//在这里处理App的恢复逻辑func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {//重新present playerViewControllerpresent(playerViewController, animated: true) {//通知系统我们已经完成了视频的界面恢复completionHandler(true)}}
}

2. 使用AVPictureInPictureController

当你自定义的播放器需要支持画中画的时候,你需要用到AVPictureInPictureController ,它管理着AVPlayerLayer

   func setupPictureInPicture() {        //  判断设备是否支持画中画if AVPictureInPictureController.isPictureInPictureSupported() {//创建AVPlayerLayerplayerLayer = AVPlayerLayer(player: AVPlayer(url: url))playerLayer.frame = CGRect(x: 100, y: 100, width: 100, height: 100)view.layer.addSublayer(playerLayer)playerLayer.player?.play()//  创建AVPictureInPictureControllerpictureInPictureController = AVPictureInPictureController(playerLayer: playerLayer)pictureInPictureController.delegate = self} else {// 不支持画中画startButton.isEnabled = falsestopButton.isEnabled = false}}@objc func togglePictureInPictureMode(_ sender: UIButton) {if pictureInPictureController.isPictureInPictureActive {//停止pictureInPictureController.stopPictureInPicture()} else {//开始pictureInPictureController.startPictureInPicture()}}func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {//在这里进行用户视频播放界面的恢复逻辑print("restore")completionHandler(true)}func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {//在界面上显示placeholder,隐藏播放控件等操作print("will start")}func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {//在界面上隐藏placeholder,恢复播放控件等操作print("will stop")}

其中AVPictureInPictureController 创建使用到了AVPlayerLayer,但是实际播放的时候PIP不使用AVPlayerLayer进行显示。当PIP开始使用的时候,系统会自动停止向AVPlayerLayer输出视频帧。

你一定要让用户通过操作(点击按钮等)来开始画中画显示。 不能直接在代码中直接startPictureInPicture ,这样的话你的APP上架审核会被拒绝。

2. 音频控制

后台播放请参考iOS音视频播放指南(一)第三部分(3.音频设置 )

当你完成后台播放设置以后,如果你播放的是音频文件,你退到后台的时候系统会自动继续播放。但是当你播放的是视频文件,默认情况下进入后台系统会自动停止播放。 如果你想在退到后台继续播放声音,需要在进入后台时断开AVPlayer的连接,进入前台重新连接。

    func sceneWillEnterForeground(_ scene: UIScene) {guard let vc = (scene.delegate as? SceneDelegate)?.window?.rootViewController as? ViewController else {return}if let playerLayer = vc.playerLayer, let player = vc.player {// 进入前台重新连接playerplayerLayer.player = player}}func sceneDidEnterBackground(_ scene: UIScene) {guard let vc = (scene.delegate as? SceneDelegate)?.window?.rootViewController as? ViewController else {return}if let playerLayer = vc.playerLayer {// 进入后台断开与player的连接playerLayer.player = nil}}

如果你的App支持后台音频播放,你可能还需要支持远程控制(耳机控制等)以及在锁屏界面的控制。这里我们使用到MediaPlayer 框架中的MPRemoteCommandCenterMPNowPlayingInfoCenter 这两个类。

MPRemoteCommandCenter用于处理远程控制

     import MediaPlayerfunc setupRemoteTransportControls() {// 获取 MPRemoteCommandCenterlet commandCenter = MPRemoteCommandCenter.shared()// 播放控制commandCenter.playCommand.addTarget { [unowned self] event inif self.player.rate == 0.0 {self.player.play()return .success}return .commandFailed}//  停止控制commandCenter.pauseCommand.addTarget { [unowned self] event inif self.player.rate == 1.0 {self.player.pause()return .success}return .commandFailed}}

MPNowPlayingInfoCenter用于锁屏界面的显示。其中我们需要注意的是AVPlayerViewController会自动刷新锁屏界面显示内容,这里我们关闭自动刷新。

   func setupNowPlaying() {// 由我们自己控制锁屏界面的显示,如果设置为false可能会使耳机控制失效playerViewController.updatesNowPlayingInfoCenter = false// 设置显示内容var nowPlayingInfo = [String : Any]()nowPlayingInfo[MPMediaItemPropertyTitle] = "My Movie"if let image = UIImage(named: "lockscreen") {nowPlayingInfo[MPMediaItemPropertyArtwork] =MPMediaItemArtwork(boundsSize: image.size) { size inreturn image}}nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playerItem.currentTime().secondsnowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.secondsnowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate// 提交给MPNowPlayingInfoCenterMPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo} 

我们可以在屏幕上看到我们提供显示的内容

3. 处理中断请求

当用户观看视频的时候,如果有电话打进来,系统会自动暂停视频播放。当通话结束的时候,系统会自动恢复播放。如果你自定义了播放界面,你可能需要在这种情况下更新界面,对AVPlayerrate属性进行KVO可以很方便的处理业务逻辑。

此外,你也可以通过监听通知来处理业务逻辑

   func setupInterruptionNotification() {let notificationCenter = NotificationCenter.defaultnotificationCenter.addObserver(self,selector: #selector(handleInterruption),name: AVAudioSession.interruptionNotification,object: nil)}@objc func handleInterruption(notification: Notification) {guard let userInfo = notification.userInfo,let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {return}if type == .began {// 中断请求触发,在这里处理你的业务逻辑}else if type == .ended {if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt {let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)if options.contains(.shouldResume) {// 系统会自动恢复播放 (通话结束)} else {// 系统不会自动恢复播放}}}}

AVAudioSession一个比较重要的功能是处理音频路由变化。 一般情况下,在用户插入耳机的时候,音频会继续播放,在用户拔出耳机的时候,音频停止播放,这一切都由系统为你自动完成。你可能需要在App中对这种情况进行一些业务处理。对AVPlayer的rate属性进行KVO或者使用AVAudioSession.routeChangeNotification进行监听

    func setupRouteChangeNotification() {let notificationCenter = NotificationCenter.defaultnotificationCenter.addObserver(self,selector: #selector(handleRouteChange),name: AVAudioSession.routeChangeNotification,object: nil)}@objc func handleRouteChange(notification: Notification) {guard let userInfo = notification.userInfo,let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,let reason = AVAudioSession.RouteChangeReason(rawValue:reasonValue) else {return}switch reason {case .newDeviceAvailable://耳机插入、蓝牙连接等情况let session = AVAudioSession.sharedInstance()//获取当前路由信息for output in session.currentRoute.outputs where output.portType == AVAudioSession.Port.headphones {//耳机已连接//headphonesConnected = truebreak}case .oldDeviceUnavailable://耳机拔出、蓝牙断开等情况//获取先前的路由信息if let previousRoute =userInfo[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription {for output in previousRoute.outputs where output.portType == AVAudioSession.Port.headphones {//耳机已断开连接//headphonesConnected = falsebreak}}default: ()}}


第三篇链接

wlzz:iOS音视频播放指南(三)​zhuanlan.zhihu.com

Github链接

https://github.com/wlixcc/AVBasicPlayback​github.com

ios nslinkattributename 自定义url_iOS音视频播放指南(二)相关推荐

  1. iOS音视频播放指南(二)

    1. 让你的App支持画中画 画中画指可以让视频在小窗中播放,可以一边看视频一边刷知乎 你可以使用AVPlayerViewController或者AVPictureInPictureControlle ...

  2. iOS音视频播放指南(一)

    1. 简介 苹果目前提供两个框架用来处理音视频播放 1.AVFoundation AVFoundation用于播放.处理音视频.可以通过结构图看到AVFoundation位于UIKit之下,很好理解A ...

  3. QT视频播放器(windows qt、linux qt 音视频播放器)

    想要更多项目私wo!!! 一.项目简介        这是基于Qt的QMediaPlayer实现的音视频播放器,实现了播放器的常用功能,例如根据播放列表选择播放的音视频,拖动滑块控制音视频播放. 二. ...

  4. [ISUX译]iOS 9人机界面指南(二):设计策略

    [ISUX译]iOS 9人机界面指南(二):设计策略 雪糕 2015.11.09 文章索引 2.1 设计原则(Design Principles) 2.1.1 美学完整性(Aesthetic Inte ...

  5. HTML5实现自定义音视频播放器

    相关资源:点击跳转到资源下载 https://download.csdn.net/download/weixin_45632016/20363517 目的: 通过综合性实验的设计,使学生综合训练自己的 ...

  6. Linux系统的madplay、mplayer音视频播放器的制作

    Linux系统音视频播放器的制作 madplay和mplayer的安装环境 一.Linux系统录音播放源码的下载和移植 1.需要下载alsa-lib-1.2.6.tar.bz2(声音驱动的内核组件库) ...

  7. android音视频播放器开发百度云,Android 播放端 SDK

    1 概述 PLDroidPlayer 是一个适用于 Android 平台的音视频播放器 SDK,可高度定制化和二次开发,为 Android 开发者提供了简单.快捷的接口,帮助开发者在 Android ...

  8. iOS】AVPlayer 播放音视频

    1.常见的音视频播放器 iOS开发中不可避免地会遇到音视频播放方面的需求. 常用的音频播放器有 AVAudioPlayer.AVPlayer 等.不同的是,AVAudioPlayer 只支持本地音频的 ...

  9. iOS:简易的音视屏播放框架XYQPlayer

    一.前缀 一直都想好好学学音视频这方面的知识,抽了几个周末参考一些资料,尝试着写了一个简易的音视频播放框架,支持音视频播放.视频截图.音乐缓存,其实吧,也就是尽可能的封装罢了,方便以后自己使用.目前只 ...

最新文章

  1. mysql-数据库模式定义语言(DDL)
  2. malloc()之后free报错的原因[详细解析]
  3. VTK:Video之MPEG2
  4. php调用mysql库_PHP调用三种数据库的方法(1)
  5. TinycoreLinux的安装使用
  6. Microsoft Edge 81 稳定版发布
  7. CSS规则重要性以及继承、层叠
  8. java定时器 不延时_ScheduledExecutorService 将一个定时任务延迟
  9. Win11进桌面闪屏,亲测恢复正常
  10. 【第8题】求 s=a+aa+aaa+aaaa+aa...a 的值
  11. Yii框架验证码不显示、不刷新、验证不正确的一些解决办法
  12. Charles配合手机模拟器抓取APP数据包教程
  13. 写文档时经常用到的图标(对勾、叉号)
  14. Eigen aligned_allocator
  15. matlab round函数怎么用,round函数的使用方法【处理模式】
  16. R语言 RStudio快捷键
  17. 多御安全浏览器安卓版迎来重大更新:新增分享二维码功能
  18. JavaConfig+springboot入门
  19. 吃灰5年的iMac,今天才发现为啥那么卡。
  20. ad15的stc元件库_STC单片机 STC15F系列单片机 Altium PROTEL 设计的器件原理图+PCB封装库文件...

热门文章

  1. Codeforces Round #496 (Div. 3)【未完结】
  2. 第二章 数据结构 【完结】
  3. 红黑树(三)之 C++的实现
  4. 【JUC并发编程13】异步回调
  5. MySql之DDL操作创建表(添加主键, 外键约束以及基本的数据类型)
  6. 无法识别的配置节appsettings_人脸识别门禁考勤系统安装使用注意事项
  7. (Mybatis)lombok使用
  8. 图片加载框架Glide的简单使用
  9. PyCharm简单使用介绍及注意事项
  10. Python访问MySQL数据库并实现其增删改查功能