AVFoundation是蘋果在iOS和OS X系統中用於處理基於時間的媒體數據的Objective-C框架. 供使用者來開發媒體類型的應用程序。git
上圖是iOS系統下媒體應用的結構層. AVKit框架用於簡化媒體應用的建立過程,若是你只須要看電影,那麼使用這個就能夠了, UKit能夠支持簡單的錄製功能 . 而更多功能須要低層級框架支持.下面簡單介紹下AVFoundation內最主要的支撐框架和其提供的功能。github
CoreAudio : 處理全部音頻事件.是由多個框架整合在一塊兒的總稱,爲音頻和MIDI內容的錄製,播放和處理提供相應接口.設置能夠針對音頻信號進行徹底控制,並經過Audio Units來構建一些複雜的音頻處理.有興趣的能夠單獨瞭解一下這個框架。緩存
CoreMedia: 是AVFoundation所用到低層級媒體管道的一部分.提供音頻樣本和視頻幀處理所需的低層級數據類型和接口。bash
CoreAnimation: 動畫相關框架, 封裝了支持OpenGL和OpenGL ES功能的ObjC各類類. AVFoundation能夠利用CoreAnimation讓開發者可以在視頻的編輯和播放過程當中添加動畫和圖片效果。微信
下面我就和你們詳細的分享一下,如何使用AVFoundation來實現一個好用的視頻播放器。若是好用或者對你有所幫助,不要忘了關注點個贊呦!!!session
視頻控制界面實現app
用於視頻顯示的View建立框架
視頻數據下載器FBYVideoDownload建立ide
播放、暫停、橫豎屏操做方法實現源碼分析
監聽播放進度
控制存儲緩衝範圍
拖動滑塊,控制快進快退
定義臨時文件路徑
定義緩存文件夾路徑
發起視頻路徑網路請求方法
播放結束設置
先後視頻播放控制
根據實現思路分析,一步步進行編碼實現:
- (FBYVideoPlayerView *)videoPlayControl{
if (!_videoPlayControl) {
_videoPlayControl = [[FBYVideoPlayerView alloc] initWithFrame:self.backgroundView.bounds];
[self.backgroundView addSubview:_videoPlayControl];
}
return _videoPlayControl;
}
複製代碼
- (UIView *)videoShowView{
if (!_videoShowView) {
_videoShowView = [[UIView alloc] init];
_videoShowView.layer.masksToBounds = YES;
[self.backgroundView addSubview:_videoShowView];
}
return _videoShowView;
}
複製代碼
@property(nonatomic, weak) id <FBYVideoDownloadDelegate> delegate;
//定義初始化方法 傳入videoUrl參數(NSString)
- (instancetype)initWithURL:(NSString *)videoUrl withDelegate:(id)delegate;
//開始下載
- (void)start;
//暫停
- (void)suspend;
//關閉
- (void)cancel;
複製代碼
//全屏
[_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;
}];
複製代碼
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;
}
}];
複製代碼
[self.currentPlayerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
複製代碼
[self.currentPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
複製代碼
[self.currentPlayerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
複製代碼
- (void)playForActivity{
if (self.playButtonState) {
[self.player play];
}
self.isBufferEmpty = NO;
self.isPlaying = YES;
[self.videoPlayControl videoPlayerDidBeginPlay];
}
複製代碼
//拖動滑塊
[_videoPlayControl setSliderTouchEnd_block:^(CGFloat time) {
[weakSelf seekToTimePlay:time];
}];
//快進快退
[_videoPlayControl setFastFastForwardAndRewind_block:^(CGFloat time) {
[weakSelf seekToTimePlay:time];
}];
複製代碼
self.videoTempPath = [NSString tempFilePathWithFileName:videoName];
複製代碼
self.videoCachePath = [NSString cacheFilePathWithName:videoName];
複製代碼
- (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];
}
複製代碼
- (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];
}];
}
複製代碼
//進入後臺
- (void)appDidEnterBackground{
if (self.stopWhenAppDidEnterBackground) {
[self pauseVideo];
}
}
//進入前臺
- (void)appDidEnterForeground{
[self playVideo];
}
複製代碼
下載demo,將demo中FBYVideoData文件夾引入項目中。
#import "FBYVideoPlayer.h"
@interface ViewController ()<FBYVideoPlayerDelegate>
@property (nonatomic ,strong) FBYVideoPlayer *videoPlayer;
@property (nonatomic ,strong) UIView *videoPlayBGView;
@property (nonatomic ,copy) NSString*videoUrl;
@end
複製代碼
self.videoPlayBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 90, SCREEN_WIDTH, SCREEN_WIDTH * 0.6)];
self.videoPlayBGView.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.videoPlayBGView];
複製代碼
self.videoPlayer = [[FBYVideoPlayer alloc] init];
self.videoPlayer.delegate = self;
[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];
複製代碼
self.videoPlayer = [[FBYVideoPlayer alloc] init];
self.videoPlayer.delegate = self;
[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];
複製代碼
關注 【網羅開發】微信公衆號,回覆【97】即可領取。 網羅天下方法,方便你我開發,更多iOS技術乾貨等待領取,全部文檔會持續更新,歡迎關注一塊兒成長!
但願能夠幫助你們,若有問題可加QQ技術交流羣: 668562416 若是哪裏有什麼不對或者不足的地方,還望讀者多多提意見或建議
如需轉載請聯繫我,通過受權方可轉載,謝謝
本篇已同步到我的博客:FBY展菲
歡迎關注個人公衆號:網羅開發