ios nslinkattributename 自定义url_iOS音视频播放指南(二)
1. 讓你的App支持畫中畫
畫中畫指可以讓視頻在小窗中播放,可以一邊看視頻一邊刷知乎
你可以使用AVPlayerViewController或者AVPictureInPictureController來實現畫中畫播放。 其中AVPictureInPictureController支持你自定義一些播放控件
在支持畫中畫播放之前,確保你按照iOS音視頻播放指南(一) 第三部分(3.音頻設置 )完成相應的設置。
支持畫中畫播放最簡單的方式就是使用 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 框架中的MPRemoteCommandCenter和MPNowPlayingInfoCenter 這兩個類。
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. 處理中斷請求
當用戶觀看視頻的時候,如果有電話打進來,系統會自動暫停視頻播放。當通話結束的時候,系統會自動恢復播放。如果你自定義了播放界面,你可能需要在這種情況下更新界面,對AVPlayer的rate屬性進行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.comGithub鏈接
https://github.com/wlixcc/AVBasicPlayback?github.com總結
以上是生活随笔為你收集整理的ios nslinkattributename 自定义url_iOS音视频播放指南(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 6 不更新无法使用_win10更新后无线
- 下一篇: android日志收集存入mysql_r