1. 让你的App支持画中画


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

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

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

  1. AVPlayerViewController

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

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

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

letcontroller=AVPlayerViewController()

controller.delegate=self

extensionViewController:AVPlayerViewControllerDelegate{

//在这里处理App的恢复逻辑

funcplayerViewController(_playerViewController:AVPlayerViewController,restoreUserInterfaceForPictureInPictureStopWithCompletionHandlercompletionHandler:@escaping(Bool)->Void){

//重新present playerViewController

present(playerViewController,animated:true){

//通知系统我们已经完成了视频的界面恢复

completionHandler(true)

}

}

}

\2. 使用AVPictureInPictureController

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

funcsetupPictureInPicture(){

// 判断设备是否支持画中画

ifAVPictureInPictureController.isPictureInPictureSupported(){

//创建AVPlayerLayer

playerLayer=AVPlayerLayer(player:AVPlayer(url:url))

playerLayer.frame=CGRect(x:100,y:100,width:100,height:100)

view.layer.addSublayer(playerLayer)

playerLayer.player?.play()

// 创建AVPictureInPictureController

pictureInPictureController=AVPictureInPictureController(playerLayer:playerLayer)

pictureInPictureController.delegate=self

}else{

// 不支持画中画

startButton.isEnabled=false

stopButton.isEnabled=false

}

}

@objcfunctogglePictureInPictureMode(_sender:UIButton){

ifpictureInPictureController.isPictureInPictureActive{

//停止

pictureInPictureController.stopPictureInPicture()

}else{

//开始

pictureInPictureController.startPictureInPicture()

}

}

funcpictureInPictureController(_pictureInPictureController:AVPictureInPictureController,restoreUserInterfaceForPictureInPictureStopWithCompletionHandlercompletionHandler:@escaping(Bool)->Void){

//在这里进行用户视频播放界面的恢复逻辑

print("restore")

completionHandler(true)

}

funcpictureInPictureControllerWillStartPictureInPicture(_pictureInPictureController:AVPictureInPictureController){

//在界面上显示placeholder,隐藏播放控件等操作

print("will start")

}

funcpictureInPictureControllerWillStopPictureInPicture(_pictureInPictureController:AVPictureInPictureController){

//在界面上隐藏placeholder,恢复播放控件等操作

print("will stop")

}

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

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

2. 音频控制


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

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

funcsceneWillEnterForeground(_scene:UIScene){

guardletvc=(scene.delegateas?SceneDelegate)?.window?.rootViewControlleras?ViewControllerelse{

return

}

ifletplayerLayer=vc.playerLayer,letplayer=vc.player{

// 进入前台重新连接player

playerLayer.player=player

}

}

funcsceneDidEnterBackground(_scene:UIScene){

guardletvc=(scene.delegateas?SceneDelegate)?.window?.rootViewControlleras?ViewControllerelse{

return

}

ifletplayerLayer=vc.playerLayer{

// 进入后台断开与player的连接

playerLayer.player=nil

}

}

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

MPRemoteCommandCenter用于处理远程控制

importMediaPlayer

funcsetupRemoteTransportControls(){

// 获取 MPRemoteCommandCenter

letcommandCenter=MPRemoteCommandCenter.shared()

// 播放控制

commandCenter.playCommand.addTarget{[unownedself]eventin

ifself.player.rate==0.0{

self.player.play()

return.success

}

return.commandFailed

}

// 停止控制

commandCenter.pauseCommand.addTarget{[unownedself]eventin

ifself.player.rate==1.0{

self.player.pause()

return.success

}

return.commandFailed

}

}

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

funcsetupNowPlaying(){

// 由我们自己控制锁屏界面的显示,如果设置为false可能会使耳机控制失效

playerViewController.updatesNowPlayingInfoCenter=false

// 设置显示内容

varnowPlayingInfo=[String:Any]()

nowPlayingInfo[MPMediaItemPropertyTitle]="My Movie"

ifletimage=UIImage(named:"lockscreen"){

nowPlayingInfo[MPMediaItemPropertyArtwork]=

MPMediaItemArtwork(boundsSize:image.size){sizein

returnimage

}

}

nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime]=playerItem.currentTime().seconds

nowPlayingInfo[MPMediaItemPropertyPlaybackDuration]=playerItem.asset.duration.seconds

nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate]=player.rate

// 提交给MPNowPlayingInfoCenter

MPNowPlayingInfoCenter.default().nowPlayingInfo=nowPlayingInfo

}

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

3. 处理中断请求


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

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

funcsetupInterruptionNotification(){

letnotificationCenter=NotificationCenter.default

notificationCenter.addObserver(self,

selector:#selector(handleInterruption),

name:AVAudioSession.interruptionNotification,

object:nil)

}

@objcfunchandleInterruption(notification:Notification){

guardletuserInfo=notification.userInfo,

lettypeValue=userInfo[AVAudioSessionInterruptionTypeKey]as?UInt,

lettype=AVAudioSession.InterruptionType(rawValue:typeValue)else{

return

}

iftype==.began{

// 中断请求触发,在这里处理你的业务逻辑

}

elseiftype==.ended{

ifletoptionsValue=userInfo[AVAudioSessionInterruptionOptionKey]as?UInt{

letoptions=AVAudioSession.InterruptionOptions(rawValue:optionsValue)

ifoptions.contains(.shouldResume){

// 系统会自动恢复播放 (通话结束)

}else{

// 系统不会自动恢复播放

}

}

}

}

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

funcsetupRouteChangeNotification(){

letnotificationCenter=NotificationCenter.default

notificationCenter.addObserver(self,

selector:#selector(handleRouteChange),

name:AVAudioSession.routeChangeNotification,

object:nil)

}

@objcfunchandleRouteChange(notification:Notification){

guardletuserInfo=notification.userInfo,

letreasonValue=userInfo[AVAudioSessionRouteChangeReasonKey]as?UInt,

letreason=AVAudioSession.RouteChangeReason(rawValue:reasonValue)else{

return

}

switchreason{

case.newDeviceAvailable:

//耳机插入、蓝牙连接等情况

letsession=AVAudioSession.sharedInstance()

//获取当前路由信息

foroutputinsession.currentRoute.outputswhereoutput.portType==AVAudioSession.Port.headphones{

//耳机已连接

//headphonesConnected = true

break

}

case.oldDeviceUnavailable:

//耳机拔出、蓝牙断开等情况

//获取先前的路由信息

ifletpreviousRoute=

userInfo[AVAudioSessionRouteChangePreviousRouteKey]as?AVAudioSessionRouteDescription{

foroutputinpreviousRoute.outputswhereoutput.portType==AVAudioSession.Port.headphones{

//耳机已断开连接

//headphonesConnected = false

break

}

}

default:()

}

}

原文https://zhuanlan.zhihu.com/p/335956344

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

iOS音视频播放指南(二)相关推荐

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

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

  2. ios nslinkattributename 自定义url_iOS音视频播放指南(二)

    没看第一篇的小伙伴可以先看第一篇 wlzz:iOS音视频播放指南(一)​zhuanlan.zhihu.com 本章主要内容 画中画支持 后台音频播放,锁屏界面显示,远程音频控制 在耳机插拔.接听电话等 ...

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

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

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

    按公司需求需要对音频文件进行后台播放,借此机会对音频播放做了个总结.主要针对 AVPlayer 进行详细说明. iOS 各播放器比较 名称 使用环境 优点 确点 System Sound Servic ...

  5. IOS音视频(三)AVFoundation 播放和录音

    IOS音视频(三)AVFoundation 播放和录音 1. 音频理论知识 1.1 声音的物理性质 1.2 数字音频 1.2.1 采样.量化和编码 1.2.2 音频编码 1.3 音频编解码 2. 播放 ...

  6. iOS音视频开发七:视频采集

    将通过拆解采集 → 编码 → 封装 → 解封装 → 解码 → 渲染流程并实现 Demo 来向大家介绍如何在 iOS/Android 平台上手音视频开发. 这里是第七篇:iOS 视频采集 Demo.这个 ...

  7. iOS音视频开发八:视频编码,H.264 和 H.265 都支持

    我们将通过拆解采集 → 编码 → 封装 → 解封装 → 解码 → 渲染流程并实现 Demo 来向大家介绍如何在 iOS/Android 平台上手音视频开发. 这里是第八篇:iOS 视频编码 Demo. ...

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

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

  9. 李洪强iOS之集成极光推送二iOS 证书 设置指南

    李洪强iOS之集成极光推送二iOS 证书 设置指南 创建应用程序ID 登陆 iOS Dev Center 选择进入iOS Provisioning Portal. 在 iOS Provisioning ...

最新文章

  1. Equinix公司在巴西圣保罗开通了一个数据中心
  2. JAVA入门级教学之(构造方法)
  3. 前端windows下常用的CMD 命令归纳
  4. Java Object 类 深入分析
  5. SPSS分析技术:多元方差分析
  6. java 取pdf 文本域_使用PDFBox获取文本行的位置
  7. 程序员怒了!你敢削减专利奖金,我敢拒绝提交代码!
  8. 报表下拉框多选查询及一般在sql中添加查询条件
  9. 转:iPhone官换机和新机的区别
  10. asp.net 性能优化细节
  11. 模块电源(一):DC-DCLDO
  12. 换头软件测试,抖音女大十八变换脸测试
  13. python爬取饿了么评论_爬虫实例:饿了么爬虫
  14. java sqlite sqlite_busy_sqlite3 busy timeout
  15. Linux系统tar、rar、7z、zip压缩解压缩命令使用
  16. JVM性能调优1:JVM性能调优理论及实践(收集整理)
  17. Windows 2003 工作手册
  18. 反相器的Cadence仿真
  19. 第4关 注册配置中心实现
  20. 无线降噪蓝牙耳机对比:NANK南卡和苹果AirPods Pro哪个好用?

热门文章

  1. 脉冲神经网络2:SNN的仿真2—感受野
  2. Form表单控件与浮动
  3. DM8登录用户名密码增强加密
  4. 趣玩科技(TT语音)一面
  5. html css js 3d元素周期表源码
  6. Python| 阿尔法函数和代码复用
  7. 【神界原罪2】ce修改
  8. ArcMap基础练习之点转线转面
  9. NVIDA GTX2080 Ubuntu18.04 cuda10.0 cudnn7.5 tensorflow 1.12 install
  10. ArcMap:第一届全国大学生GIS应用技能大赛(滁州学院)详解-上午题