頁視頻播放器選型與實戰(zhàn):ckplay多格式播放代碼拆解)
簡介這是一款面向網(wǎng)頁開發(fā)者的輕量級視頻播放組件基于ckplayer構(gòu)建主打免費、小巧與高度可定制適合需要在網(wǎng)站中嵌入點播、直播或直播回看功能的開發(fā)者使用。壓縮包共27個文件約3.47MB包含9個html示例頁、4個js腳本、4個xml配置、3個png圖片以及swf、srt、vtt、json等資源分別用于頁面演示、播放邏輯、界面與語言配置、字幕與廣告數(shù)據(jù)。功能上支持m3u8、mp4、flv、f4v、swf及jpg、png、gif等圖片格式播放PC端內(nèi)置m3u8普通加密與私有加密播放并支持清晰度自動列表、彈幕、字幕、自定義按鈕與JavaScript交互。廣告體系覆蓋前置、暫停、插入、結(jié)尾及角標(biāo)橫幅等多種類型。目前已有2140人學(xué)習(xí)下載讀者可借助示例頁面快速理解調(diào)用方式按需定制界面風(fēng)格與加密策略搭建完整的網(wǎng)頁視頻播放方案。1. 網(wǎng)頁視頻播放器選型為什么 ckplay 這類方案值得拆一遍做在線教育、短視頻站或者企業(yè)內(nèi)訓(xùn)平臺的朋友大概率都遇到過同一個需求網(wǎng)頁里要能播 m3u8也要能播 mp4偶爾還得兼容 flv、f4v 這些老格式圖片資源 jpg、png、gif 甚至 swf 也得能預(yù)覽。瀏覽器原生video標(biāo)簽只認(rèn) mp4、webm、ogg 這幾種遇到 m3u8 切片流直接罷工flv 更是碰都不碰。這時候要么上商業(yè)播放器 SDK要么自己拼一套開源方案。ckplay 這類網(wǎng)頁視頻播放軟件代碼就是沖著這個場景來的——一份前端代碼包把多種格式的播放能力封裝好拿過來改改配置就能嵌進自己的頁面。它適合誰適合不想從零造輪子、又不想被商業(yè)授權(quán)綁死的中小團隊前端也適合想研究播放器內(nèi)核怎么處理多格式切換的開發(fā)者。下面我按實際拆包復(fù)現(xiàn)的順序把這份代碼的用法、參數(shù)和坑講清楚。2. 拆開代碼包目錄結(jié)構(gòu)、依賴與格式支持邊界2.1 先看目錄別急著改代碼拿到一份網(wǎng)頁播放器代碼第一件事不是打開 index.html 就改而是先摸清目錄結(jié)構(gòu)。常見的 ckplay 類代碼包根目錄下一般會有這么幾塊目錄/文件作用是否要改index.html演示入口含播放器容器和初始化腳本參考不直接用于生產(chǎn)js/ckplay.js播放器核心邏輯格式判斷與調(diào)度核心謹(jǐn)慎改js/hls.min.jsm3u8 解析依賴一般不動js/flv.min.jsflv/f4v 解析依賴一般不動css/ckplay.css播放器皮膚與控制條樣式按需改demo/各格式示例頁面測試用這個結(jié)構(gòu)說明一件事m3u8 和 flv 不是播放器自己實現(xiàn)的而是靠 hls.js 和 flv.js 這兩個庫兜底。ckplay 的價值在于把「根據(jù)擴展名或 MIME 自動選內(nèi)核」這件事封裝了你不用自己寫一堆 if-else 去判斷該加載哪個庫。2.2 格式支持的真實邊界標(biāo)題里列了 m3u8、mp4、flv、jpg、jpeg、png、gif、swf、f4v 一大串但它們的支持程度完全不是一個級別拆之前心里要有數(shù)mp4瀏覽器原生支持走video直接播最穩(wěn)。m3u8靠 hls.js需要瀏覽器支持 MediaSource Extensions現(xiàn)代瀏覽器基本都行但 Safari 原生就支持 m3u8反而不用 hls.js代碼里通常要做分支。flv / f4v靠 flv.js同樣依賴 MSE且 flv.js 對編碼有要求必須是 H.264 AAC遇到 H.265 的 flv 直接黑屏。jpg / jpeg / png / gif這些是圖片播放器里通常是當(dāng)「圖片預(yù)覽」處理用img渲染不是視頻解碼。swfFlash 已經(jīng)徹底退出歷史舞臺現(xiàn)代瀏覽器不再支持。代碼里保留 swf 多半是歷史遺留實際跑起來會提示不支持別在這上面浪費時間。提示如果你的源站 flv 是 H.265 編碼別指望 flv.js 能救轉(zhuǎn)碼成 H.264 或者換 fmp4 才是正路。2.3 依賴加載順序不能亂hls.js 和 flv.js 必須在 ckplay.js 之前加載否則初始化時會報Hls is not defined或flvjs is not defined。常見做法是在head里按順序引入!-- 先加載解析庫再加載播放器核心 -- script srcjs/hls.min.js/script script srcjs/flv.min.js/script script srcjs/ckplay.js/script順序反了播放器初始化時找不到全局對象控制臺直接拋錯頁面一片空白。這個坑我見過不止一次尤其是用打包工具動態(tài) import 的時候容易把順序打亂。3. 初始化與參數(shù)配置把播放器嵌進自己的頁面3.1 最小可用初始化ckplay 類播放器一般提供一個全局構(gòu)造函數(shù)傳入容器選擇器和配置對象。最小可用寫法大概是這樣// 容器必須先在 DOM 里存在 var player new CkPlayer({ container: #videoBox, // 播放器掛載的容器選擇器 url: ./media/demo.m3u8, // 視頻地址支持相對或絕對路徑 autoplay: false, // 是否自動播放建議 false muted: false, // 是否靜音自動播放時通常要 true loop: false, // 是否循環(huán) poster: ./images/cover.jpg,// 封面圖 width: 100%, // 播放器寬度 height: 480px, // 播放器高度 controls: true // 是否顯示控制條 });邏輯說明構(gòu)造函數(shù)內(nèi)部會根據(jù)url的擴展名判斷走哪條解碼路徑。.m3u8走 hls.js.flv/.f4v走 flv.js.mp4直接賦給video的 src圖片格式則替換成img渲染。參數(shù)里autoplay和muted是一對現(xiàn)代瀏覽器策略要求自動播放必須靜音所以如果你要自動播放兩個都得配合設(shè)置。3.2 關(guān)鍵參數(shù)逐個說參數(shù)類型默認(rèn)值說明containerstring無必填容器選擇器urlstring無必填媒體地址autoplaybooleanfalse自動播放受瀏覽器策略限制mutedbooleanfalse靜音自動播放時建議 trueloopbooleanfalse循環(huán)播放posterstring封面圖地址width/heightstring100% / auto尺寸建議用 CSS 控制controlsbooleantrue是否顯示控制條typestringauto強制指定格式auto 為自動判斷type這個參數(shù)容易被忽略。自動判斷靠擴展名但如果你的 URL 帶查詢參數(shù)比如video.m3u8?tokenxxx擴展名解析可能失敗這時候手動指定type: m3u8更穩(wěn)妥。3.3 動態(tài)切換視頻源實際項目里經(jīng)常要在不刷新頁面的情況下?lián)Q視頻播放器一般提供switchUrl或load方法// 切換前先銷毀舊實例避免內(nèi)存泄漏 player.switchUrl(./media/next.flv, flv);邏輯說明切換時內(nèi)部會先停掉當(dāng)前解碼器釋放 MSE 的 SourceBuffer再根據(jù)新格式重新初始化。如果不先停舊實例多個解碼器同時占用資源頁面會越來越卡這是血淚經(jīng)驗。參數(shù)第二個是格式類型不傳則自動判斷。4. 多格式播放的坑m3u8 跨域、flv 編碼與圖片預(yù)覽4.1 m3u8 跨域與 CORSm3u8 本質(zhì)是一系列 ts 切片瀏覽器通過 XHR 拉取。如果 m3u8 和 ts 文件不在同源服務(wù)端必須返回正確的 CORS 頭# Nginx 配置示例給 m3u8 和 ts 加上跨域頭 location ~* \.(m3u8|ts)$ { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET, OPTIONS; add_header Access-Control-Allow-Headers Range; }邏輯說明hls.js 拉取切片時會帶 Range 頭做分段請求所以Access-Control-Allow-Headers里必須包含 Range否則預(yù)檢請求失敗播放器報CORS error但控制臺不一定給明確提示容易誤判成網(wǎng)絡(luò)問題。4.2 flv 編碼不匹配的黑屏flv.js 只支持 H.264 視頻 AAC 音頻。如果源站 flv 是 H.265 或者音頻是 MP3播放器會加載成功但畫面黑屏、無聲音。排查方法是看 flv.js 的日志// 開啟 flv.js 調(diào)試日志 flvjs.LoggingControl.enableAll true;邏輯說明開啟后控制臺會打印媒體信息能看到實際的編碼格式。如果 codec 不是 avc1 開頭基本可以判定編碼不支持需要服務(wù)端轉(zhuǎn)碼。4.3 圖片格式的預(yù)覽處理jpg、png、gif 這些在播放器里不是「播放」而是「展示」。代碼內(nèi)部通常判斷擴展名后把video替換成img。這里有個坑gif 動圖如果被當(dāng)成視頻處理會只顯示第一幀。正確做法是識別到 gif 直接走img讓瀏覽器自己處理動畫。注意swf 格式在現(xiàn)代瀏覽器已經(jīng)無法播放代碼里即便保留分支實際也會走 fallback 提示。如果你的資源里有 swf建議提前轉(zhuǎn)成 mp4 或 gif。5. 避坑與排查五個真實翻車記錄5.1 現(xiàn)象m3u8 能播但一直卡頓原因切片時長過短或碼率過高h(yuǎn)ls.js 緩沖跟不上。常見于把 2 秒切片配 4Mbps 碼率的場景。解決服務(wù)端把切片時長調(diào)到 6 到 10 秒碼率按目標(biāo)分辨率控制在合理范圍1080p 建議 3 到 5 Mbps。5.2 現(xiàn)象flv 播放幾秒后卡死原因flv.js 的 MSE 緩沖區(qū)滿了沒有及時清理多見于直播流場景。解決在配置里開啟enableStashBuffer: false或者監(jiān)聽statistics_info事件手動控制緩沖。5.3 現(xiàn)象自動播放沒反應(yīng)原因瀏覽器自動播放策略要求靜音autoplay: true但muted: false會被攔截。解決兩個參數(shù)同時設(shè)置或者監(jiān)聽用戶交互后再調(diào)用play()。5.4 現(xiàn)象切換視頻后舊聲音還在原因舊實例沒有銷毀音頻軌道仍在播放。解決切換前調(diào)用player.destroy()或player.pause()確認(rèn)舊實例釋放后再加載新源。5.5 現(xiàn)象移動端全屏按鈕失效原因iOS Safari 對全屏 API 支持有限r(nóng)equestFullscreen在 iPhone 上不生效。解決iOS 上依賴原生video的全屏行為不要自己實現(xiàn)全屏按鈕或者用webkitEnterFullscreen做兼容。6. 進階技巧自定義控制條與格式探測6.1 用 canPlayType 做格式預(yù)判在初始化之前可以先探測瀏覽器能力避免加載了庫卻播不了// 探測瀏覽器對特定格式的支持 var video document.createElement(video); var canMp4 video.canPlayType(video/mp4; codecsavc1.42E01E); var canHls video.canPlayType(application/vnd.apple.mpegurl); console.log(mp4:, canMp4, hls native:, canHls);邏輯說明canPlayType返回probably、maybe或空字符串。如果 hls 原生支持Safari就不用加載 hls.js直接給 video.src 賦值 m3u8 地址即可省一個庫的加載。這個判斷在移動端尤其有用能減少不必要的資源請求。6.2 自定義控制條的事件綁定ckplay 默認(rèn)控制條夠用但品牌定制往往要換。自定義控制條的核心是綁定播放器的狀態(tài)事件事件名觸發(fā)時機常用場景play開始播放切換按鈕圖標(biāo)pause暫停切換按鈕圖標(biāo)timeupdate播放進度變化更新進度條ended播放結(jié)束顯示重播按鈕error出錯展示錯誤提示綁定方式// 監(jiān)聽播放器事件驅(qū)動自定義 UI player.on(timeupdate, function(data) { // data.currentTime 當(dāng)前時間data.duration 總時長 var percent (data.currentTime / data.duration) * 100; document.querySelector(.progress-bar).style.width percent %; });邏輯說明timeupdate觸發(fā)頻率約每秒 4 次足夠驅(qū)動進度條但不要在里面做重計算否則影響播放流暢度。進度條拖動則調(diào)用player.seek(seconds)。6.3 一個我踩過的坑早期我圖省事把 hls.js 和 flv.js 都用 CDN 引入結(jié)果某次 CDN 抽風(fēng)播放器直接白屏用戶投訴一片。從那以后我每次集成播放器都強制把依賴庫下載到本地并且在初始化前加一段能力探測確認(rèn)庫加載成功再 new 播放器。這個習(xí)慣幫我省了至少三次線上事故。希望幫到你。本文還有配套的精品資源點擊獲取