iOS AVPlayer 學習
1 .使用環境:
在實際開發過程中 有需要展示流媒體的模塊 ,需求非常簡單 :播放 和 暫停 ,其實這個時候有很多選擇 ,可以選擇 MPMoviePlayerController(MediaPlayer.framework), AVAudioPlayer(AVFunction.framework)
但是考慮到擴展性,高度自定義性 我選擇使用 AVPlayer. 事實是對的 后來需求又增加了, 還需要展示播放進度,緩沖進度,變化時間,視頻時長等,還有對UI有要求,甚至不為過的說 要蘋果手機那個AVPlayer app的播放效果.
其實 我是拒絕的 基因里帶的反抗心理 但是還得去做啊 一天天的 就被產品虐待
2.關鍵核心代碼
2.1 三個監聽
2.1.1監聽視頻狀態 key : “status” 是不是一個可播放狀態 還是正在緩沖 還是加載失敗等錯誤
2.1.2監聽視頻播放完成 :endTime這個時候 根據需求 做觸發響應 要重播 那就做重播處理的方法 或者需要彈框 或者其他什么的方法
2.1.3監聽視頻播放過程: timeObserver 用來實時更新播放狀態,播放進度 緩沖進度等
重點:
視頻從播放開始 timeObserver 創建 停止播放 一定要有 timeObserver 的移除 防止空監聽
同理 “status”,endTime 在切換視頻 或者 disappear 視頻控制器頁面 時候 都要取消監聽
保證”observer first :創建或重新創建 需要先release舊的對象 再add 并且結束使用 移除對應監聽 防止空監聽”
判斷是否取消 “status”,endTime條件,我是判斷 當前player 和 AVPlayerItem是否存在 存在則 取消. 但是 有時候 一些視頻流本身的意外錯誤 ,用枚舉也沒攔住的話 很有可能意外 中的意外執行 ,也許會取消一個空監聽,這個時候 我特意給取消監聽加上了 try catch 目的很簡單 防止崩潰啊,并且它和上下文關聯的程度并不大,不會出現一個小錯誤滾啊滾滾成大錯誤的意外發生.
2.2 幾個重要類
AVAsset:主要用于獲取多媒體信息,是一個抽象類,不能直接使用。
AVURLAsset:AVAsset的子類,可以根據一個URL路徑創建一個包含媒體信息的AVURLAsset對象。
AVPlayerItem:一個媒體資源管理對象,管理者視頻的一些基本信息和狀態,一個AVPlayerItem對應著一個視頻資源。
(1)- (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler NS_AVAILABLE(10_7, 4_2); 該方法使用 獲取 到 AVKeyValueStatus keyStatus 狀態 typedef NS_ENUM(NSInteger, AVKeyValueStatus) { AVKeyValueStatusUnknown, AVKeyValueStatusLoading, AVKeyValueStatusLoaded, AVKeyValueStatusFailed, AVKeyValueStatusCancelled }; 攔截錯誤failed 做提示 就不用再往下做多余執行了 如果 asset.playable 是真 則可以添加 status (先移除 上一次的響應監聽 如果存在的話) (2)監聽status -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; typedef NS_ENUM(NSInteger, AVPlayerStatus) { AVPlayerStatusUnknown, AVPlayerStatusReadyToPlay, AVPlayerStatusFailed }; if([playerItem status] == AVPlayerStatusReadyToPlay) 是可以播放的狀態,其他情況 按需求做提示 或者其他一些必要處理 (3)AVPlayerStatusReadyToPlay 可播放狀態 如果 執行播放了 要添加timeObserver (先移除timeObserver 有必要的話), 然后處理UI 需要展示的相關視頻信息 (4) 展示播放進度 用 UISlider 展示緩沖進度用UIProgressive. 然后 先 add slider 再add progressive 這里 特別要講的是 如果 沒有對視頻觸摸有特別要求 可以把他們都放在一個toolbarView上 方便集中處理 但是如果有特殊需求的話,還是建議 把他們直接add在視頻存在的那個自定義View上. 我的處理 是add 在 視頻的 那個View上 因為 還有一個 快進快退的功能 UISlider 高度 要通過 繼承UISlider 的slider重寫 (CGRect)trackRectForBounds:(CGRect)bounds 來設置 不然就是默認高度 (UIPorgressive 也是) 并且slider 原生的UI是圓角 現在要求是扁平化方角,處理辦法 是用圖片代替 設置進度顏色 就可以了 其次 是 拖動進度條的圓點 焦點區域過小不敏感,這個也是通過重寫方法來擴大焦點區域的 //自定義 UISlider - Increase “hot spot(焦點區域)” size - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event { CGRect bounds = self.bounds; bounds = CGRectInset(bounds, -10, -15);//左右擴寬 10 像素 上下擴寬 15像素 return CGRectContainsPoint(bounds, point); } (4)快進與快退 關鍵有二 (1)觸發時間點 ,我這里給sldier 添加了 兩個方法 一個 touchDown 作為拖拽開始的響應方法 一個 touchUpinside 作為拖拽結束的響應 debug測過了 邏輯基本滿足需求.如果 你想一直監聽拖拽過程什么 也是可以的 這兩個方法 保證了快進快退后 再恢復正常播放的業務邏輯,非常關鍵,此處你要考慮 timeObserver狀態 展示進度時間的變化 拖拽slider的value變化 (2)在 touchUpinside 時候 要處理 視頻的seekToTime問題 這個我的”CMTimeMake 和 CMTimeMakeWithSeconds”特地區分了 這兩個創建一個CMTime的關鍵. 在拖拽結束后 seekToTime方法: -(void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL finished))completionHandler NS_AVAILABLE(10_7, 5_0); 還有其他的seekToTime方法 但是在我的工程項目里 這個 是精準度最高的 不論視頻的長短,拖拽都不會出現拖動按鈕跳動(實際的問題就是精準度或者時間誤差很大造成的)的問題 我處理這個精準度的問題花了好久,網上資源 豐富 不代表沒有錯誤啊,我才發現我在slack flow上還沒有評論他人的功能,資歷尚淺,只得在下邊添加了我對問題的評論. 所以我對 一個 seekToTime的問題是這么回答的 (其實我樓上的樓上 寫錯了 但是仍然獲得了五個贊)

至此 順利結束開發任務 好開心
后記:
其實流媒體的水很深, 比如相關的問題 還有 錄視頻 直播視頻什么的 涉及HTTP Live Streaming(HLS)技術 慢慢學吧 路很長. 其實 我特別討厭一些面試官問你 什么會不會的時候 當你說 不會 然后 他像抓到你小把柄似的 嘲笑你.我覺得 這樣的人道行一定不會很深,很深的人往往不會這么篩選技術伙伴.也許他比你強,但也只是暫時的問題了.我覺得,有可持續的學習能力很重要,并且能在有效的時間解決問題.這個才是重點:不會,但是在規定時間內,我可以通過各種途徑把目標技能 get了.這也就好了啊.我也沒聽過哪個大牛 上來大而全 什么都會啊.
但是面試的時候 作為我們應聘者 還是吃虧的 因為要談錢啊 所以我們得有自我學習的驅動力不斷增加自己的砝碼.
致敬所有 在奮斗的IT同行們, 今天 我看到一篇新聞說 一個IT 帶病工作 然后肺部感染 都好多個洞洞了 .突然有點心疼 . 大家都 要好好愛自己 ,健康最重要. 哈哈

不錯的一篇概要,至少能讓你基本了解幾種播放操作流媒體的使用場景
http://www.rzrgm.cn/kenshincui/p/4186022.html
HLS
http://www.rzrgm.cn/haibindev/archive/2013/01/30/2880764.html
posted on 2016-05-02 21:14 ACM_Someone like you 閱讀(2659) 評論(0) 收藏 舉報
浙公網安備 33010602011771號