一:簡介
AVFoundation是蘋果在iOS和OS X系統中用於處理基於時間的媒體資料的Objective-C框架. 供使用者來開發媒體型別的應用程式。
上圖是iOS系統下媒體應用的結構層. AVKit框架用於簡化媒體應用的建立過程,如果你只需要看電影,那麼使用這個就可以了, UKit可以支援簡單的錄製功能 . 而更多功能需要低層級框架支援.下面簡單介紹下AVFoundation內最主要的支撐框架和其提供的功能。
-
CoreAudio : 處理所有音訊事件.是由多個框架整合在一起的總稱,為音訊和MIDI內容的錄製,播放和處理提供相應介面.設定可以針對音訊訊號進行完全控制,並通過Audio Units來構建一些複雜的音訊處理.有興趣的可以單獨瞭解一下這個框架。
-
CoreMedia: 是AVFoundation所用到低層級媒體管道的一部分.提供音訊樣本和視訊幀處理所需的低層級資料型別和介面。
-
CoreAnimation: 動畫相關框架, 封裝了支援OpenGL和OpenGL ES功能的ObjC各種類. AVFoundation可以利用CoreAnimation讓開發者能夠在視訊的編輯和播放過程中新增動畫和圖片效果。
下面我就和大家詳細的分享一下,如何使用AVFoundation來實現一個好用的視訊播放器。如果好用或者對你有所幫助,不要忘了關注點個贊呦!!!
二:實現思路分析
-
視訊控制介面實現
-
用於視訊顯示的View建立
-
視訊資料下載器FBYVideoDownload建立
-
播放、暫停、橫豎屏操作方法實現
-
監聽播放進度
-
控制儲存緩衝範圍
-
拖動滑塊,控制快進快退
-
定義臨時檔案路徑
-
定義快取資料夾路徑
-
發起視訊路徑網路請求方法
-
播放結束設定
-
前後視訊播放控制
三:實現原始碼分析
根據實現思路分析,一步步進行編碼實現:
1. 視訊控制介面實現
- (FBYVideoPlayerView *)videoPlayControl{
if (!_videoPlayControl) {
_videoPlayControl = [[FBYVideoPlayerView alloc] initWithFrame:self.backgroundView.bounds];
[self.backgroundView addSubview:_videoPlayControl];
}
return _videoPlayControl;
}
複製程式碼
2. 用於視訊顯示的View建立
- (UIView *)videoShowView{
if (!_videoShowView) {
_videoShowView = [[UIView alloc] init];
_videoShowView.layer.masksToBounds = YES;
[self.backgroundView addSubview:_videoShowView];
}
return _videoShowView;
}
複製程式碼
3. 視訊資料下載器FBYVideoDownload建立
@property(nonatomic, weak) id <FBYVideoDownloadDelegate> delegate;
//定義初始化方法 傳入videoUrl引數(NSString)
- (instancetype)initWithURL:(NSString *)videoUrl withDelegate:(id)delegate;
//開始下載
- (void)start;
//暫停
- (void)suspend;
//關閉
- (void)cancel;
複製程式碼
4. 播放、暫停、橫豎屏操作方法實現
//全屏
[_videoPlayControl setFullScreenButtonClick_block:^{
if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(videoPlayerDidFullScreenButtonClick)]) {
[weakSelf.delegate videoPlayerDidFullScreenButtonClick];
}
}];
//播放/暫停
[_videoPlayControl setPlayButtonClick_block:^(BOOL play) {
if (play) {
[weakSelf.player play];
}else{
[weakSelf.player pause];
}
weakSelf.playButtonState = !weakSelf.playButtonState;
}];
複製程式碼
5. 監聽播放進度
self.timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
CGFloat current = CMTimeGetSeconds(time);
CGFloat total = CMTimeGetSeconds(weakSelf.currentPlayerItem.duration);
CGFloat progress = current / total;
weakSelf.videoPlayControl.currentTime = current;
weakSelf.videoPlayControl.playValue = progress;
if (weakSelf.isCanToGetLocalTime) {
weakSelf.localTime = [weakSelf getLocalTime];
}
NSInteger timeNow = [weakSelf getLocalTime];
if (timeNow - weakSelf.localTime > 1.5) {
[weakSelf.videoPlayControl videoPlayerDidBeginPlay];
weakSelf.isCanToGetLocalTime = YES;
}
}];
複製程式碼
6. 監聽播放器的狀態
[self.currentPlayerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
複製程式碼
7. 監聽當前的緩衝進度
[self.currentPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
複製程式碼
8. 監聽到當前沒有緩衝資料
[self.currentPlayerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
複製程式碼
9. 控制儲存緩衝範圍
- (void)playForActivity{
if (self.playButtonState) {
[self.player play];
}
self.isBufferEmpty = NO;
self.isPlaying = YES;
[self.videoPlayControl videoPlayerDidBeginPlay];
}
複製程式碼
10. 拖動滑塊,控制快進快退
//拖動滑塊
[_videoPlayControl setSliderTouchEnd_block:^(CGFloat time) {
[weakSelf seekToTimePlay:time];
}];
//快進快退
[_videoPlayControl setFastFastForwardAndRewind_block:^(CGFloat time) {
[weakSelf seekToTimePlay:time];
}];
複製程式碼
11. 定義臨時檔案路徑
self.videoTempPath = [NSString tempFilePathWithFileName:videoName];
複製程式碼
12. 定義快取資料夾路徑
self.videoCachePath = [NSString cacheFilePathWithName:videoName];
複製程式碼
13. 發起視訊路徑網路請求方法
- (void)sendHttpRequst
{
[_fileHandle seekToEndOfFile];
NSURL *url = [NSURL URLWithString:_videoUrl];
NSMutableURLRequest *requeset = [NSMutableURLRequest requestWithURL:url];
//指定頭資訊 當前已下載的進度
[requeset setValue:[NSString stringWithFormat:@"bytes=%ld-", _curruentLength] forHTTPHeaderField:@"Range"];
//建立請求
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:requeset];
self.dataTask = dataTask;
//發起請求
[self.dataTask resume];
}
複製程式碼
14. 播放結束設定
- (void)playerItemDidPlayToEnd:(NSNotification *)notification{
//重新開始播放
__weak typeof(self) weak_self = self;
[self.player seekToTime:CMTimeMake(0, 1) completionHandler:^(BOOL finished) {
__strong typeof(weak_self) strong_self = weak_self;
if (!strong_self) return;
[strong_self.player play];
}];
}
複製程式碼
15. 前後視訊播放控制
//進入後臺
- (void)appDidEnterBackground{
if (self.stopWhenAppDidEnterBackground) {
[self pauseVideo];
}
}
//進入前臺
- (void)appDidEnterForeground{
[self playVideo];
}
複製程式碼
五:專案實際使用
1. 下載demo
下載demo,將demo中FBYVideoData資料夾引入專案中。
2. 在專案中引入FBYVideoPlayer並繼承FBYVideoPlayerDelegate代理
#import "FBYVideoPlayer.h"
@interface ViewController ()<FBYVideoPlayerDelegate>
@property (nonatomic ,strong) FBYVideoPlayer *videoPlayer;
@property (nonatomic ,strong) UIView *videoPlayBGView;
@property (nonatomic ,copy) NSString*videoUrl;
@end
複製程式碼
3. 初始化建立基層view
self.videoPlayBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 90, SCREEN_WIDTH, SCREEN_WIDTH * 0.6)];
self.videoPlayBGView.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.videoPlayBGView];
複製程式碼
4. 初始化呼叫視訊播放方法
self.videoPlayer = [[FBYVideoPlayer alloc] init];
self.videoPlayer.delegate = self;
[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];
複製程式碼
5. 初始化呼叫視訊播放方法
self.videoPlayer = [[FBYVideoPlayer alloc] init];
self.videoPlayer.delegate = self;
[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];
複製程式碼
本篇文章demo原始碼:
關注 【網羅開發】微信公眾號,回覆【97】便可領取。 網羅天下方法,方便你我開發,更多iOS技術乾貨等待領取,所有文件會持續更新,歡迎關注一起成長!
希望可以幫助大家,如有問題可加QQ技術交流群: 668562416 如果哪裡有什麼不對或者不足的地方,還望讀者多多提意見或建議
如需轉載請聯絡我,經過授權方可轉載,謝謝
本篇已同步到個人部落格:FBY展菲
歡迎關注我的公眾號:網羅開發