JPVideoPlayer
version 2.0 版本發佈而寫,若是你想了解 2.0 版本的更新內容和全部實現細節,請點擊前往 GitHub。導言:我幾個月前寫了一個在
UITableView
中滑動UITableViewCell
播放視頻的框架,相似於「新浪微博」 和 「Facebook」 首頁視頻播放。我也爲初版本的JPVideoPlayer
實現寫了兩篇文章:
0一、[iOS]仿微博視頻邊下邊播之封裝播放器 講述如何封裝一個實現了邊下邊播而且緩存的視頻播放器。
0二、[iOS]仿微博視頻邊下邊播之滑動TableView自動播放 講述如何實如今
UITableView
中滑動播放視頻,而且是流暢,不阻塞線程,沒有任何卡頓的實現滑動播放視頻。同時也將講述當UITableView
滾動時,以什麼樣的策略,來肯定究竟哪個cell應該播放視頻。
當時匆忙實現功能,沒有仔細斟酌架構的問題,也沒有完全的實現單個功能的組件化。並且因爲架構設計不足帶來一些不可避免的問題。這些問題,1.0 版本的用戶應該有所體會。前段時間獨自回了一趟老家,車程比較長,並且能夠專一而不被打擾,在車上寫了一個 2.0 版本。2.0 版本有部份內容模仿了
SDWebImage
的設計。html
2.x 版本效果以下:
考慮到 API 和架構都從新設計了,尤爲是 API 所有從新設計,1.0 版本的 API 已經不能沿用了,機智的我已經作好了被罵得很慘的心理準備了。git
若是你是新的用戶,就不會受以前版本的影響。最終無論你是新用戶仍是老用戶,你必定會喜歡這種新的 API 設計的,由於這是目前 iOS 最受歡迎的 API 設計。github
Objective-C:
#import <UIView+WebVideoCache.h>
...
NSURL *url = [NSURL URLWithString:@"http://lavaweb-10015286.video.myqcloud.com/%E5%B0%BD%E6%83%85LAVA.mp4"];
[aview jp_playVideoWithURL:url];
複製代碼
不少用戶可能不會有時間去讀源碼,可是也許會關心 2.0 版本內部實現的一些大的方式,因此這裏我總結了一張 2.0 版本的實現大體結構圖表,以下:web
下面我用文字來表述一下框架內部的運做順序:緩存
01.提供給外部調用的 API 很是簡潔,採用爲 UIView
添加分類方法的形式爲外界調用,只要導入了頭文件,全部 UIView
的子類都擁有播放視頻的方法。框架把 UIView
的分類方法做爲和框架內部交互的橋樑。安全
02.JPVideoPlayerManager
負責甄別用戶傳過來的 URL,根據不一樣的 URL 做出不一樣的反應進行視頻播放。具體細節以下:微信
02.一、是不是本地文件路徑,若是是本地路徑,直接把路徑給負責視頻播放的工具類 JPVideoPlayerPlayVideoTool
進行視頻播放;網絡
02.二、若是不是本地路徑,再根據 URL 生成緩存的 key 給 JPVideoPlayerCache
工具類查找是否有本地緩存文件,若是有緩存就把緩存路徑返還給JPVideoPlayerManager
,JPVideoPlayerManager
會把路徑給負責視頻播放的工具類 JPVideoPlayerPlayVideoTool
進行視頻播放;架構
02.三、若是沒有本地緩存,就把 URL 給 JPVideoPlayerDownloader
下載工具類,這個工具類就會去網絡上下載視頻數據,每下載完一段數據,都會返回給 JPVideoPlayerManager
,JPVideoPlayerManager
會先把這段數據給 JPVideoPlayerCache
, JPVideoPlayerCache
先把數據緩存到磁盤,而後再把緩存的路徑返還給JPVideoPlayerManager
,JPVideoPlayerManager
會把路徑給負責視頻播放的工具類 JPVideoPlayerPlayVideoTool
進行視頻播放。框架
類名 | 功能點 |
---|---|
JPVideoPlayerDownloaderOperation |
下載單個視頻文件工具 |
JPVideoPlayerDownloader |
下載工具類,管理下載操做隊列 |
JPVideoPlayerCachePathTool |
管理臨時和完整視頻存儲路徑 |
JPVideoPlayerCacheConfig |
緩存配置文件,包括緩存週期,最大磁盤緩存等 |
JPVideoPlayerCache |
緩存工具類,負責視頻數據的存、取、刪、更新 |
JPVideoPlayerResourceLoader |
視頻播放器的數據代理,負責將網絡視頻數據填充給播放器 |
JPVideoPlayerPlayVideoTool |
視頻播放工具類 |
JPVideoPlayerManager |
管理者,協調各個模塊相互配合工做 |
接下來我將大體描述一下每一個類的實現:
01.JPVideoPlayerDownloaderOperation
:它繼承自 NSOperation
,它內部持有一個 NSURLSession
實例對象,由這個實例對象去負責下載視頻數據,JPVideoPlayerDownloaderOperation
成爲這個實例對象的代理,監聽獲取下載到的數據,並將得到的數據回傳給操做的全部者 JPVideoPlayerDownloader
。
02.JPVideoPlayerDownloader
:它持有一個下載隊列,下載隊列裏存放的是 JPVideoPlayerDownloaderOperation
實例對象。考慮到播放視頻數據量較大並且是持續的,爲了將全部的網絡資源用於加載當前用戶播放的視頻,提高使用體驗,因此這個隊列在任什麼時候候都只容許一個下載操做運行。它接收到 JPVideoPlayerDownloaderOperation
回調的數據之後會繼續把數據回傳出去。
03.JPVideoPlayerCachePathTool
:它負責管理緩存文件的路徑,包括臨時和完整視頻存儲路徑兩個部分。
04.JPVideoPlayerCacheConfig
:這個類存放着緩存存儲週期,最大磁盤緩存等緩存配置數據。
05.JPVideoPlayerCache
:它負責數據的存、取、刪、更新等功能。當調用存數據的功能時,會在臨時文件存放的文件夾內新建一個 mp4 文件,並開始將數據寫入到這個文件內,存完一段數據之後,會將存儲數據的路徑回調出去。每次播放視頻的時候,都會去查詢緩存中有沒有這個 URL 的完整數據緩存,若是有就會把路徑回調出去。它還對外提供獲取緩存大小的功能,若是你須要在設置裏獲取當前視頻緩存,能夠調用這個接口。它還有刪除緩存視頻數據的功能。
06.JPVideoPlayerResourceLoader
這個類沿用自 1.0 版本,負責從已經下載的數據中找出播放器須要的數據,並將數據填充到播放器的數據請求中進行視頻播放。
07.JPVideoPlayerPlayVideoTool
這個類持有一個視頻播放器,負責串聯從視頻數據到圖像和影音的整個播放功能。
08.JPVideoPlayerManager
它是框架的管理者、大管家,它的具體功能上面「內部細節」已經陳述過了,這裏不重複了。
09.其餘還有一個數據加載進度條和一個緩衝狀態指示器,這些都很簡單。還有就是 2.0 版本的 Demo 將 UITableViewController
視頻播放抽到一個分類中集中管理,也方便後期維護,若是你的需求和 Demo 相似,能夠考慮直接把這個分類拽進項目,須要改動的代碼不多,就能實現。
這個問題我想從用戶和我本身,還有它原本應該是什麼樣子這些維度來分析。
01.首先,受用戶歡迎的框架應該要具有兩個基本的素質。第一,調用起來方便,能一行代碼解決的,毫不搞兩行。第二,不侵入用戶的項目,萬一哪天框架不維護了,也不要成爲用戶的累贅。
02.其次,我說一個我今天看一個框架的感覺,是一個相似微信選擇多張照片的框架,框架對外提供的接口不夠我用,因此我只能去框架內部改,可是當我找一個功能的時候,框架文檔沒有說明,我在那些代碼應該放的位置也沒有找到,需求就是改字體和顏色,我找了一上午,終於在一個不可能猜到的位置找到了那幾行代碼。這裏就有幾個問題點:
- 咱們對外提供的接口儘可能讓使用者夠用,若是沒有考慮到,那用戶就可能會來框架裏改。
- 咱們的框架類的命名,方法的命名都應該遵照蘋果的那套標準,由於你們每天在用的都是蘋果 API,若是徹底不遵照蘋果那套,那用戶來到框架裏就是一頭霧水,這裏有一個溝通成本的問題,看懂代碼以前還要先熟悉咱們特有的標準。就像去美國,要和美國人說話,要先學英語。
- 文檔必定要詳實,每一個人水平都不同,代碼可能看不懂,可是文字誰都認識,這是做者和用戶溝通的基礎。
維護框架其實也是很花時間的一件事情,1.0 版本的時候,就常常有用戶給我留言,發QQ消息和我溝通實現的細節,還要他們但願下個版本但願加進去的一些功能。
當時不少功能的代碼都混在一個類裏,第一就是這個類上千行代碼,我本身要改一個東西都須要用搜索功能才能找到,各個方法之間相互調用的時候跳來跳去,頭暈眼花。
如今每一個模塊劃分完功能之後,每一個功能的核心代碼都高度集中在對應的類裏,隱藏實現的細節,屏蔽了外部的干擾,只對外提供必要的接口。如今調試問題的時候,分析到出現問題可能的模塊之後,能快速定位到對應類的對應方法裏,只須要在當前類裏專一當前的問題就能夠了,不須要考慮外部的影響。這個效率的提高仍是蠻明顯的。
因此從做者的角度,這個架構的好處就是,第一,方便我後期的維護,提升效率;第二,方便和用戶的溝通,減小溝通成本;第三,當有新功能的時候,我能快速的把代碼寫到對應的類別裏。
前段時間看 BBC 的 「Planet Earth」 紀錄片,裏面說螞蟻巢穴裏有幾千萬只螞蟻,可是卻分工明確,秩序盡然。原來,螞蟻分爲四類:
咱們的代碼或許也能夠仿照大天然,先劃分功能,再列出幾個類,將功能點挨個集中到類裏,武裝出類,就是所謂的對象。這就是我理解的框架應該有的美。
2017.04.04 更新.
2017.05.31 更新:
2017.05.02 更新. 有些朋友反應有些視頻沒法邊下邊播, 具體解決思路請參考 這篇博文 。