前言
NS_CLASS_AVAILABLE(10_7, 4_0) @interface AVPlayer : NSObject
@available(iOS 4.0, *) public class AVPlayer : NSObject
NS_CLASS_AVAILABLE_IOS(8_0) @interface AVPlayerViewController : UIViewController
@available(iOS 8.0, *) public class AVPlayerViewController : UIViewController
-
AVPlayer 既可以播放音樂又可以播放視頻;使用 AVPlayer 不能直接顯示視頻,必須要加入 AVPlayerLayer 中,並添加到其他能顯示的 layer 中,AVPlayer 播放界面中不帶播放控件。
- MediaPlayer 的影片是放在 UIView 里面,而 AVPlayer 是放在 AVPlayerLayer 里面,AVPlayerLayer 是 CALayer 的子類別。
- 使用 MediaPlayer 前,要記得加入 MediaPlayer.framework 及 #import <MediaPlayer/MediaPlayer.h>
- 使用 AVPlayer 前,要記得加入 AVFoundation.framework 及 #import <AVFoundation/AVFoundation.h>
-
MeidaPlayer 框架中的 MPMoviePlayerController 類和 MPMoviePlayerViewController 類是 iOS 中視頻播放的開發相關類和方法。在 iOS8 中,iOS 開發框架中引入了一個新的視頻框架 AVKit,其中提供了視頻開發類 AVPlayerViewController 用於在應用中嵌入播放視頻的控件。AVPlayerViewcontroller 繼承自 UIViewController,一般適用於點擊一個視頻縮略圖,modal 出一個新的界面來進行播 放的情況,AVPlayerViewcontroller 既可以播放音樂又可以播放視頻,播放界面中自帶播放控件。在 iOS8 中,這兩個框架中的視頻播放功能並無太大差異,基本都可以滿足開發者的需求。iOS9 系統后,iPad Air 正式開始支持多任務與畫中畫的分屏功能,所謂畫中畫,即是用戶可以將當前播放的視頻縮小放在屏幕上同時進行其他應用程序的使用。這個革命性的功能將極大的方便用戶的使用。於此同時,在 iOS9 中,MPMoviePlayerController 與 MPMoviePlayerViewController 類也被完全棄用,開發者使用 AVPlayerViewController 可以十分方便的實現視頻播放的功能並在一些型號的 iPad 上集成畫中畫的功能。
-
實現畫中畫要實現以下三步:
-
1、確保當前調試版本在 9.0 以上。
-
2、在項目 TARGETS 中的 Capabilities -> Gapabilities -> Background Mode(選項開關打開)-> 勾選 Audio, AirPlay and Picture in Picture
-
3、設置 AVAudioSession,這兩行必須設置,不然畫中畫不能用,如果不寫模擬器中可以畫中畫,但是在 iPad 設備中不能。
AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
-
-
播放設置:
-
使用 AVPlayer 播放:
添加庫文件:AVFoundation.framework 包含頭文件:#import <AVFoundation/AVFoundation.h>
-
使用 AVPlayerViewController 播放:
添加庫文件:AVKit.framework AVFoundation.framework 包含頭文件:#import <AVKit/AVKit.h> #import <AVFoundation/AVFoundation.h>
-
1、本地/網絡音視頻播放
1.1 使用 AVPlayer 播放
-
Objective-C
添加庫文件:AVFoundation.framework 包含頭文件:#import <AVFoundation/AVFoundation.h>
-
直接由 URL 創建
// 加載本地音樂 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"藍蓮花" ofType:@"mp3"]]; // 加載本地視頻 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"步步高手機" ofType:@"mp4"]]; // 加載網絡視頻 NSURL *movieUrl = [NSURL URLWithString:@"http://w2.dwstatic.com/1/5/1525/127352-100-1434554639.mp4"]; // 創建 AVPlayer 播放器 AVPlayer *player = [AVPlayer playerWithURL:movieUrl]; // 將 AVPlayer 添加到 AVPlayerLayer 上 AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; // 設置播放頁面大小 playerLayer.frame = CGRectMake(10, 30, self.view.bounds.size.width - 20, 200); // 設置畫面縮放模式 playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; // 在視圖上添加播放器 [self.view.layer addSublayer:playerLayer]; // 開始播放 [player play];
-
由 AVPlayerItem 創建
// 加載本地音樂 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"藍蓮花" ofType:@"mp3"]]; // 加載本地視頻 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"步步高手機" ofType:@"mp4"]]; // 加載網絡視頻 NSURL *movieUrl = [NSURL URLWithString:@"http://w2.dwstatic.com/1/5/1525/127352-100-1434554639.mp4"]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:movieUrl]; // 創建 AVPlayer 播放器 AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem]; // 將 AVPlayer 添加到 AVPlayerLayer 上 AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; // 設置播放頁面大小 playerLayer.frame = CGRectMake(10, 30, self.view.bounds.size.width - 20, 200); // 設置畫面縮放模式 playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; // 在視圖上添加播放器 [self.view.layer addSublayer:playerLayer]; // 開始播放 [player play];
-
-
Swift
添加庫文件:AVFoundation.framework 包含頭文件:import AVFoundation
-
直接由 URL 創建
// 加載本地音樂 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("藍蓮花", ofType: "mp3")!) // 加載本地視頻 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("步步高手機", ofType: "mp4")!) // 加載網絡視頻 let movieUrl:NSURL = NSURL(string: "http://w2.dwstatic.com/1/5/1525/127352-100-1434554639.mp4")! // 創建 AVPlayer 播放器 let player:AVPlayer = AVPlayer(URL: movieUrl) // 將 AVPlayer 添加到 AVPlayerLayer 上 let playerLayer:AVPlayerLayer = AVPlayerLayer(player: player) // 設置播放頁面大小 playerLayer.frame = CGRectMake(10, 30, self.view.bounds.size.width - 20, 200) // 設置畫面縮放模式 playerLayer.videoGravity = AVLayerVideoGravityResizeAspect // 在視圖上添加播放器 self.view.layer.addSublayer(playerLayer) // 開始播放 player.play()
-
由 AVPlayerItem 創建
// 加載本地音樂 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("藍蓮花", ofType: "mp3")!) // 加載本地視頻 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("步步高手機", ofType: "mp4")!) // 加載網絡視頻 let movieUrl:NSURL = NSURL(string: "http://w2.dwstatic.com/1/5/1525/127352-100-1434554639.mp4")! let playerItem:AVPlayerItem = AVPlayerItem(URL: movieUrl) // 創建 AVPlayer 播放器 let player:AVPlayer = AVPlayer(playerItem: playerItem) // 將 AVPlayer 添加到 AVPlayerLayer 上 let playerLayer:AVPlayerLayer = AVPlayerLayer(player: player) // 設置播放頁面大小 playerLayer.frame = CGRectMake(10, 30, self.view.bounds.size.width - 20, 200) // 設置畫面縮放模式 playerLayer.videoGravity = AVLayerVideoGravityResizeAspect // 在視圖上添加播放器 self.view.layer.addSublayer(playerLayer) // 開始播放 player.play()
-
1.2 使用 AVPlayerViewController 播放
-
Objective-C
添加庫文件:AVKit.framework AVFoundation.framework 包含頭文件:#import <AVKit/AVKit.h> #import <AVFoundation/AVFoundation.h>
-
彈出顯示頁面直接開始播放
// 加載本地音樂 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"藍蓮花" ofType:@"mp3"]]; // 加載本地視頻 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"步步高手機" ofType:@"mp4"]]; // 加載網絡視頻 NSURL *movieUrl = [NSURL URLWithString:@"http://w2.dwstatic.com/1/5/1525/127352-100-1434554639.mp4"]; // 創建播放控制器 AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init]; playerViewController.player = [AVPlayer playerWithURL:movieUrl]; // 彈出播放頁面 [self presentViewController:playerViewController animated:YES completion:^{ // 開始播放 [playerViewController.player play]; }];
-
手動播放
// 加載本地視頻 NSURL *movieUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"步步高手機" ofType:@"mp4"]]; // 創建播放控制器 AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init]; playerViewController.player = [AVPlayer playerWithURL:movieUrl]; // 彈出播放頁面,需要點擊播放按鈕開始播放 [self presentViewController:playerViewController animated:YES completion:nil];
-
-
Swift
添加庫文件:AVKit.framework import AVFoundation 包含頭文件:import AVKit AVFoundation.framework
-
彈出顯示頁面直接開始播放
// 加載本地音樂 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("藍蓮花", ofType: "mp3")!) // 加載本地視頻 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("步步高手機", ofType: "mp4")!) // 加載網絡視頻 let movieUrl:NSURL = NSURL(string: "http://w2.dwstatic.com/1/5/1525/127352-100-1434554639.mp4")! // 創建播放控制器 let playerViewController:AVPlayerViewController = AVPlayerViewController() playerViewController.player = AVPlayer(URL: movieUrl) // 彈出播放頁面 self.presentViewController(playerViewController, animated: true) { // 開始播放 playerViewController.player?.play() }
-
手動播放
// 加載本地視頻 let movieUrl:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("步步高手機", ofType: "mp4")!) // 創建播放控制器 let playerViewController:AVPlayerViewController = AVPlayerViewController() playerViewController.player = AVPlayer(URL: movieUrl) // 彈出播放頁面,需要點擊播放按鈕開始播放 self.presentViewController(playerViewController, animated: true, completion:nil)
-
2、本地/網絡音視頻播放設置
2.1 使用 AVPlayer 播放
-
Objective-C
// 在視圖上添加播放器 /* 必須添加到 layer 上 */ avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer]; [self.view.layer addSublayer:avPlayerLayer]; // 設置播放頁面大小 avPlayerLayer.frame = CGRectMake(10, 30, self.view.bounds.size.width - 20, 200); // 設置畫面縮放模式 /* AVLayerVideoGravityResizeAspect 適應屏幕大小,保持寬高比,默認 AVLayerVideoGravityResizeAspectFill 充滿屏幕,保持寬高比 AVLayerVideoGravityResize 充滿屏幕,不保持寬高比 */ avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; // 獲取顯示在接收視圖范圍內的視頻圖像的位置和大小 CGRect videoRect = avPlayerLayer.videoRect; // 判斷是否准備好顯示 BOOL readyForDisplay = avPlayerLayer.isReadyForDisplay; // 獲取視頻准備播放狀態 /* AVPlayerItemStatusUnknown, 狀態未知 AVPlayerItemStatusReadyToPlay, 准備好播放 AVPlayerItemStatusFailed 准備失敗 */ AVPlayerItemStatus status = avPlayerItem.status; // 監聽准備播放狀態屬性 [avPlayerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; // 系統自帶監聽方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"status"]) { } } // 獲取視頻緩沖進度 NSArray<NSValue *> *loadedTimeRanges = avPlayerItem.loadedTimeRanges; CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue]; // 獲取緩沖區域 float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); float loadedSecond = startSeconds + durationSeconds; // 計算緩沖總進度 // 監聽緩沖進度屬性 [avPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; // 系統自帶監聽方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"loadedTimeRanges"]) { } } // 獲取當前播放進度 /* 或用 avPlayerItem.currentTime.value/avPlayerItem.currentTime.timescale; */ CMTime currentTime = avPlayerItem.currentTime; float currentSecond = CMTimeGetSeconds(currentTime); // 監聽播放進度 /* NULL 在主線程中執行,每個一秒執行一次該 Block */ [avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) { }]; // 添加播放完成通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:avPlayerItem]; // 獲取視頻總長度 /* 轉換成秒,或用 duration.value / duration.timescale; 計算 */ CMTime duration = avPlayerItem.duration; float totalSecond = CMTimeGetSeconds(duration); // 跳轉到指定位置 /* 10 / 1 = 10,跳轉到第 10 秒的位置處 */ [avPlayerItem seekToTime:CMTimeMake(10, 1)]; // 設置播放速率 /* 默認為 1.0 (normal speed),設為 0.0 時暫停播放。設置后立即開始播放,可放在開始播放后設置 */ avPlayer.rate = 1.0; // 獲取當前播放速率 float rate = avPlayer.rate; // 開始播放 [avPlayer play]; // 暫停播放 [avPlayer pause]; // 設置音量 /* 范圍 0 - 1,默認為 1 */ avPlayer.volume = 0;
-
Swift
// 在視圖上添加播放器 /* 必須添加到 layer 上 */ avPlayerLayer = AVPlayerLayer(player: avPlayer) self.view.layer.addSublayer(avPlayerLayer) // 設置播放頁面大小 avPlayerLayer.frame = CGRectMake(10, 30, self.view.bounds.size.width - 20, 200) // 設置畫面縮放模式 /* AVLayerVideoGravityResizeAspect 適應屏幕大小,保持寬高比,默認 AVLayerVideoGravityResizeAspectFill 充滿屏幕,保持寬高比 AVLayerVideoGravityResize 充滿屏幕,不保持寬高比 */ avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill // 獲取顯示在接收視圖范圍內的視頻圖像的位置和大小 let videoRect:CGRect = avPlayerLayer.videoRect // 判斷是否准備好顯示 let readyForDisplay:Bool = avPlayerLayer.readyForDisplay // 獲取視頻准備播放狀態 /* case Unknown 狀態未知 case ReadyToPlay 准備好播放 case Failed 准備失敗 */ let status:AVPlayerItemStatus = avPlayerItem.status // 監聽准備播放狀態屬性 avPlayerItem.addObserver(self, forKeyPath: "status", options: .New, context: nil) // 系統自帶監聽方法 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if keyPath == "status" { } } // 獲取視頻緩沖進度 let loadedTimeRanges:[NSValue] = avPlayerItem.loadedTimeRanges let timeRange:CMTimeRange = loadedTimeRanges.first!.CMTimeRangeValue // 獲取緩沖區域 let startSeconds = CMTimeGetSeconds(timeRange.start) let durationSeconds = CMTimeGetSeconds(timeRange.duration) let loadedSecond:Double = startSeconds + durationSeconds // 計算緩沖總進度 // 監聽緩沖進度屬性 avPlayerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: .New, context: nil) // 系統自帶監聽方法 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if keyPath == "loadedTimeRanges" { } } // 獲取當前播放進度 /* 或用 avPlayerItem.currentTime.value/avPlayerItem.currentTime.timescale; */ let currentTime:CMTime = self.avPlayerItem.currentTime() let currentSecond = CMTimeGetSeconds(currentTime) // 監聽播放進度 /* nil 在主線程中執行,每個一秒執行一次該 Block */ avPlayer.addPeriodicTimeObserverForInterval(CMTimeMake(1, 1), queue: nil) { (time:CMTime) in } // 添加播放完成通知 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AvPlayer.playDidEnd(_:)), name: AVPlayerItemDidPlayToEndTimeNotification, object: avPlayerItem) // 獲取視頻總長度 /* 轉換成秒,或用 duration.value / duration.timescale; 計算 */ let duration:CMTime = avPlayerItem.duration let totalSecond:Double = CMTimeGetSeconds(duration) // 跳轉到指定位置 /* 10 / 1 = 10,跳轉到第 10 秒的位置處 */ avPlayerItem.seekToTime(CMTimeMake(10, 1)) // 設置播放速率 /* 默認為 1.0 (normal speed),設為 0.0 時暫停播放。設置后立即開始播放,可放在開始播放后設置 */ avPlayer.rate = 1.0 // 獲取當前播放速率 let rate:Float = avPlayer.rate // 開始播放 avPlayer.play() // 暫停播放 avPlayer.pause() // 設置音量 /* 范圍 0 - 1,默認為 1 */ avPlayer.volume = 0
2.2 使用 AVPlayerViewController 播放
-
Objective-C
// 顯示播放頁面 [self presentViewController:avPlayerVC animated:YES completion:nil]; // 設置畫面縮放模式 /* AVLayerVideoGravityResizeAspect 適應屏幕大小,保持寬高比,默認 AVLayerVideoGravityResizeAspectFill 充滿屏幕,保持寬高比 AVLayerVideoGravityResize 充滿屏幕,不保持寬高比 */ avPlayerVC.videoGravity = AVLayerVideoGravityResizeAspect; // 獲取顯示在接收視圖范圍內的視頻圖像的位置和大小 CGRect videoBounds = avPlayerVC.videoBounds; // 獲取播放控件所在的視圖 /* 播放控件與播放內容界面之間的疊加視圖 */ UIView *contentOverlayView = avPlayerVC.contentOverlayView; // 設置是否顯示播放控件 /* Default is YES */ avPlayerVC.showsPlaybackControls = YES; // 設置是否允許畫中畫播放 /* Default is YES */ avPlayerVC.allowsPictureInPicturePlayback = YES; // 判斷是否准備好顯示 BOOL readyForDisplay = avPlayerVC.isReadyForDisplay; // 設置畫中畫播放代理,需遵守協議 <AVPlayerViewControllerDelegate> avPlayerVC.delegate = self; // 實現畫中畫播放 /* 這兩行必須設置,不然畫中畫不能用,如果不寫模擬器中可以畫中畫,但是在設備中不能 */ AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; // 獲取視頻准備播放狀態 /* AVPlayerItemStatusUnknown, 狀態未知 AVPlayerItemStatusReadyToPlay, 准備好播放 AVPlayerItemStatusFailed 准備失敗 */ AVPlayerItemStatus status = avPlayerVC.player.currentItem.status; // 監聽准備播放狀態屬性 [avPlayerVC.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; // 系統自帶監聽方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"status"]) { } } // 獲取視頻緩沖進度 NSArray<NSValue *> *loadedTimeRanges = avPlayerVC.player.currentItem.loadedTimeRanges; CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue]; // 獲取緩沖區域 float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); float loadedSecond = startSeconds + durationSeconds; // 計算緩沖總進度 // 監聽緩沖進度屬性 [avPlayerVC.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; // 系統自帶監聽方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"loadedTimeRanges"]) { } } // 獲取當前播放進度 /* 或用 avPlayerItem.currentTime.value/avPlayerItem.currentTime.timescale; */ CMTime currentTime = avPlayerVC.player.currentItem.currentTime; float currentSecond = CMTimeGetSeconds(currentTime); // 監聽播放進度 /* NULL 在主線程中執行,每個一秒執行一次該 Block */ [avPlayerVC.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) { }]; // 添加播放完成通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:avPlayerVC.player.currentItem]; // 獲取視頻總長度 /* 轉換成秒,或用 duration.value / duration.timescale; 計算 */ CMTime duration = avPlayerVC.player.currentItem.duration; float totalSecond = CMTimeGetSeconds(duration); // 跳轉到指定位置 /* 10 / 1 = 10,跳轉到第 10 秒的位置處 */ [avPlayerVC.player.currentItem seekToTime:CMTimeMake(10, 1)]; // 設置播放速率 /* 默認為 1.0 (normal speed),設為 0.0 時暫停播放。設置后立即開始播放,可放在開始播放后設置 */ avPlayerVC.player.rate = 1.0; // 獲取當前播放速率 float rate = avPlayerVC.player.rate; // 開始播放 [avPlayerVC.player play]; // 暫停播放 [avPlayerVC.player pause]; // 設置音量 /* 范圍 0 - 1,默認為 1 */ avPlayerVC.player.volume = 0;
-
Swift
// 顯示播放頁面 self.presentViewController(avPlayerVC, animated: true, completion:nil) // 設置畫面縮放模式 /* AVLayerVideoGravityResizeAspect 適應屏幕大小,保持寬高比,默認 AVLayerVideoGravityResizeAspectFill 充滿屏幕,保持寬高比 AVLayerVideoGravityResize 充滿屏幕,不保持寬高比 */ avPlayerVC.videoGravity = AVLayerVideoGravityResizeAspect // 獲取顯示在接收視圖范圍內的視頻圖像的位置和大小 let videoBounds:CGRect = avPlayerVC.videoBounds // 獲取播放控件所在的視圖 /* 播放控件與播放內容界面之間的疊加視圖 */ let contentOverlayView:UIView = avPlayerVC.contentOverlayView! // 設置是否顯示播放控件 /* Default is YES */ avPlayerVC.showsPlaybackControls = true // 設置是否允許畫中畫播放 /* Default is YES */ avPlayerVC.allowsPictureInPicturePlayback = true // 判斷是否准備好顯示 let readyForDisplay:Bool = avPlayerVC.readyForDisplay // 設置畫中畫播放代理,需遵守協議 <AVPlayerViewControllerDelegate> avPlayerVC.delegate = self // 實現畫中畫播放 /* 這兩行必須設置,不然畫中畫不能用,如果不寫模擬器中可以畫中畫,但是在設備中不能 */ let audioSession:AVAudioSession = AVAudioSession.sharedInstance() try! audioSession.setCategory(AVAudioSessionCategoryPlayback) // 獲取視頻准備播放狀態 /* AVPlayerItemStatusUnknown, 狀態未知 AVPlayerItemStatusReadyToPlay, 准備好播放 AVPlayerItemStatusFailed 准備失敗 */ let status:AVPlayerItemStatus = avPlayerVC.player!.currentItem!.status // 監聽准備播放狀態屬性 avPlayerVC.player!.currentItem!.addObserver(self, forKeyPath: "status", options: .New, context: nil) // 系統自帶監聽方法 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if keyPath == "status" { } } // 獲取視頻緩沖進度 let loadedTimeRanges:[NSValue] = avPlayerVC.player!.currentItem!.loadedTimeRanges let timeRange:CMTimeRange = loadedTimeRanges.first!.CMTimeRangeValue // 獲取緩沖區域 let startSeconds = CMTimeGetSeconds(timeRange.start) let durationSeconds = CMTimeGetSeconds(timeRange.duration) let loadedSecond:Double = startSeconds + durationSeconds // 計算緩沖總進度 // 監聽緩沖進度屬性 avPlayerVC.player!.currentItem!.addObserver(self, forKeyPath: "loadedTimeRanges", options: .New, context: nil) // 系統自帶監聽方法 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if keyPath == "loadedTimeRanges" { } } // 獲取當前播放進度 let currentTime:CMTime = self.avPlayerVC.player!.currentItem!.currentTime() let currentSecond = CMTimeGetSeconds(currentTime) // 監聽播放進度 avPlayerVC.player?.addPeriodicTimeObserverForInterval(CMTimeMake(1, 1), queue: nil, usingBlock: { (time:CMTime) in }) // 添加播放完成通知 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AvPlayer.playDidEnd(_:)), name: AVPlayerItemDidPlayToEndTimeNotification, object: avPlayerVC.player!.currentItem!) // 獲取視頻總長度 /* 轉換成秒,或用 duration.value / duration.timescale; 計算 */ let duration:CMTime = avPlayerVC.player!.currentItem!.duration let totalSecond = CMTimeGetSeconds(duration) // 跳轉到指定位置 /* 10 / 1 = 10,跳轉到第 10 秒的位置處 */ avPlayerVC.player!.currentItem!.seekToTime(CMTimeMake(10, 1)) // 設置播放速率 /* 默認為 1.0 (normal speed),設為 0.0 時暫停播放。設置后立即開始播放,可放在開始播放后設置 */ avPlayerVC.player!.rate = 1.0 // 獲取當前播放速率 let rate = avPlayerVC.player!.rate // 開始播放 avPlayerVC.player!.play() // 暫停播放 avPlayerVC.player!.pause() // 設置音量 /* 范圍 0 - 1,默認為 1 */ avPlayerVC.player!.volume = 0
3、AVPlayerViewControllerDelegate 畫中畫協議方法
-
Objective-C
// 將要開始畫中畫播放 - (void)playerViewControllerWillStartPictureInPicture:(AVPlayerViewController *)playerViewController { } // 已經開始畫中畫播放 - (void)playerViewControllerDidStartPictureInPicture:(AVPlayerViewController *)playerViewController { } // 畫中畫播放失敗 - (void)playerViewController:(AVPlayerViewController *)playerViewController failedToStartPictureInPictureWithError:(NSError *)error { } // 將要結束畫中畫播放 - (void)playerViewControllerWillStopPictureInPicture:(AVPlayerViewController *)playerViewController { } // 已經結束畫中畫播放 - (void)playerViewControllerDidStopPictureInPicture:(AVPlayerViewController *)playerViewController { } // 畫中畫播放開始時播放控制器界面是否自動退出 - (BOOL)playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart:(AVPlayerViewController *)playerViewController { // 是否在開始畫中畫時自動將當前的播放界面 dismiss 掉,返回 YES 則自動 dismiss,返回 NO 則不會自動 dismiss return NO; } // 畫中畫停止之前恢復用戶界面 - (void)playerViewController:(AVPlayerViewController *)playerViewController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler { // 用戶點擊還原按鈕,從畫中畫模式還原回 App 內嵌模式時調用的方法 }
-
Swift
// 將要開始畫中畫播放 func playerViewControllerWillStartPictureInPicture(playerViewController: AVPlayerViewController) { } // 已經開始畫中畫播放 func playerViewControllerDidStartPictureInPicture(playerViewController: AVPlayerViewController) { } // 畫中畫播放失敗 func playerViewController(playerViewController: AVPlayerViewController, failedToStartPictureInPictureWithError error: NSError) { } // 將要結束畫中畫播放 func playerViewControllerWillStopPictureInPicture(playerViewController: AVPlayerViewController) { } // 已經結束畫中畫播放 func playerViewControllerDidStopPictureInPicture(playerViewController: AVPlayerViewController) { } // 畫中畫播放開始時播放控制器界面是否自動退出 func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(playerViewController: AVPlayerViewController) -> Bool { // 是否在開始畫中畫時自動將當前的播放界面 dismiss 掉,返回 YES 則自動 dismiss,返回 NO 則不會自動 dismiss return false } // 畫中畫停止之前恢復用戶界面 func playerViewController(playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: (Bool) -> Void) { // 用戶點擊還原按鈕,從畫中畫模式還原回 App 內嵌模式時調用的方法 }