今天我們拿 AVFoundation 的冰山一角來闡述一下我個人的喜好秋泳!相信每個人都會用 iPhone、iPad 來觀看“視頻”倡缠,優(yōu)酷米母、愛奇藝、搜狐毡琉?嗯铁瞒!還有 Youtube。
原文點擊這里:http://www.zengxianhua.com/2016/02/19/avfoundationde-le-qu/
現(xiàn)在的產(chǎn)品體驗已經(jīng)足以讓我們玩的爽桅滋,也可以玩的 High慧耍!
于是我開始研究他們的細節(jié)身辨,果然不錯,在體驗和兼容性上確實有一定的難度芍碧。
不想用 MPMoviePlayerController 的同學煌珊,都會想到 AVFoundation 去自定義,其實重載 MPMoviePlayerController 也可以 自定義UI泌豆,但我還是喜歡自己琢磨定庵。
我想用自己寫的播放器來看視頻,可以嗎踪危?當然我就這么干了蔬浙!
先理解幾個名稱的基本概念。
AVPLayer
我理解的官方解釋:你可以使用 AVPlayer 對象實現(xiàn)控制和自定義UI的單個或多個播放贞远。
這意味著你項目如果有多個播放的需求畴博,這不就幫你解決了嗎?
AVPlayer支持本地與遠程的多媒體文件蓝仲,正好俱病,我本意就是可以緩存到本地看,也可以在線看袱结。
我們需要怎樣呈現(xiàn)可視內(nèi)容呢亮隙?
AVPlayerLayer
我理解的官方解釋:APLayerLayer 是 CALayer 的子類,AVPLayer可以通過它指導(dǎo)視頻輸出和可視化垢夹。
那音頻需要嗎咱揍?沒有可視化內(nèi)容,使用 AVPlayer 就可以播放啦棚饵!
AVAsset
我理解的官方解釋:AVAsset是定時的視聽媒體,它可以是視頻掩完、影片噪漾、歌曲、播客節(jié)目且蓬;可以是本地或者遠程的欣硼;也可以是限定或者非限定的流;
AVPlayerItem
我理解的官方解釋:協(xié)調(diào)AVPlayer和AVAsset恶阴,同樣具有AVPlayerItemTrack對象诈胜,可以控制音量、播放速率等等冯事。
基本實現(xiàn)流程
了解 AVPlayer焦匈、AVPlayerLayer、AVPlayerItem昵仅、AVAsset 基本概念之后缓熟,那如何定制自己的播放器呢累魔?
-
第一步首先需要一個展示的容器,繼承 UIView够滑,隨你喜歡取個類名唄垦写!( VideoLayerView )做以下操作:
.h @property (nonatomic, strong) AVPlayer *player; @property (nonatomic, readonly) AVPlayerLayer *playerLayer; @property (nonatomic, copy) NSString *videoFillMode; .m + (Class)layerClass { return [AVPlayerLayer class]; } - (void)commit { self.playerLayer.backgroundColor = [[UIColor blackColor] CGColor]; self.videoFillMode = AVLayerVideoGravityResizeAspect; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self commit]; } return self; } - (void)awakeFromNib { [self commit]; } - (void)setPlayer:(AVPlayer *)player { [(AVPlayerLayer *)[self layer] setPlayer:player]; } - (AVPlayer *)player { return [(AVPlayerLayer *)[self layer] player]; } - (AVPlayerLayer *)playerLayer { return (AVPlayerLayer *)self.layer; } - (void)setVideoFillMode:(NSString *)videoFillMode { [self playerLayer].videoGravity = videoFillMode; } - (NSString *)videoFillMode { return [self playerLayer].videoGravity; }
第二步創(chuàng)建 AVAsset 進行加載多媒體文件
你的是遠程地址?我的是本地路徑彰触?OMG梯投,這些都不是問題
NSURL *mediaURL = [NSURL URLWithString:mediaPath];
if (!mediaURL || ![mediaURL scheme]) {
mediaURL = [NSURL fileURLWithPath:mediaPath];
}
AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:mediaURL options:nil];
AVURLAsset 是 AVAsset的子類
-
第三步通過 AVAsset 的 loadValuesAsynchronouslyForKeys: completionHandler: 方法得到 AVPlayerItem,我們暫時只需要playable况毅、 duration 這兩個key分蓖,這里是異步加載數(shù)據(jù),你需要判斷加載的狀態(tài)俭茧。整理如下:
NSArray *keys = @[@“playable", @“duration"]; __weak typeof(self.mediaAsset) weakAsset = urlAsset; [urlAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ // check the keys for (NSString *key in keys) { NSError *error = nil; AVKeyValueStatus keyStatus = [weakAsset statusOfValueForKey:key error:&error]; if (keyStatus == AVKeyValueStatusFailed) { NSLog(@"error (%@)", [[error userInfo] objectForKey:AVPlayerItemFailedToPlayToEndTimeErrorKey]); return; } } // check playable if (!weakAsset.playable) { return; } // get AVPlayerItem AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:weakAsset]; }); }];
-
第四步通過異步得到的 AVPlayerItem 進行創(chuàng)建AVPlayer
AVPlayer *player = [AVPLayer playerWithPlayerItem:playerItem]; VideoLayerView *layerView = [[VideoLayerView alloc] initWithFrame:frame]; layerView.player = player; [player play];
這樣就初步完成播放本地咆疗、遠程多媒體的播放器了,如果想趕上大公司的產(chǎn)品體驗母债,還需好好打磨一下午磁。
期待下一回的優(yōu)化唄!
下一期:打造一個上百Star的開源庫