前端视频直播技术总结及video.js在h5页面中的应用
全手打原創,轉載請標明出處:https://www.cnblogs.com/dreamsqin/p/12557070.html,多謝,=。=~
(如果對你有幫助的話請幫我點個贊啦)
目前有一個需求是在移動端上內嵌h5實現點位的視頻直播,直播項目采用Vue編寫,后端主要輸出 RTMP 和 HLS 協議的直播流,本文主要總結一下整體開發的技術選型以及開發過程中的思考與學習總結。
流媒體傳輸
我的困惑: 什么是流媒體,以及其傳輸方式是怎樣的?
流媒體
流媒體是指采用流式傳輸方式在 Internet 上播放的媒體格式,例如音頻、視頻等多媒體文件。
流式傳輸方式
流式傳輸方式是將多媒體文件經過特殊壓縮后分成一個個壓縮包,再由服務器向客戶端連續、實時傳送。用戶不必像非流式傳輸那樣等待整個文件全部下載完畢后才能播放,而是只需要經過幾秒鐘或幾十秒的啟動延時即可對壓縮的音視頻文件進行播放,剩余的部分將繼續下載,直至播放完畢。
流媒體傳輸協議
常用的流媒體傳輸協議主要有HTTP漸進式下載和實時流媒體協議兩類。
HTTP漸進式下載:僅能傳輸完整的音視頻文件,在給定時刻,用戶只能觀看已下載的那部分,而不能跳到還未下載的部分。HTTP邊下載邊播放,嚴格意義上講,不是直播協議。他的原理是先下載文件的基本信息,音頻視頻的時間戳,再下載音視頻數據,以播放mp4為例,先下載文件頭,根據文件頭指引下載文件尾,然后再下載文件的音視頻數據。
實時流媒體協議:可用于實況直播,也可傳輸完整的音視頻文件。例如RTSP/RTP、RTMP、HLS、HTTP-FLV。
RTSP協議
既可以基于UDP傳輸也可以基于TCP傳輸,是純粹的傳輸控制協議,它本身與它負載的媒體數據不相關,RTSP協議需要自定義客戶端向服務器發送RTSP命令。其視頻數據由RTP傳輸,視頻質量由RTCP控制,視頻控制(如播放、暫停等)由RTSP提供。
常用直播流協議
我的困惑: 哪些流媒體傳輸協議用于直播,不同類型之間又有什么區別?
RTMP(Real Time Messaging Protocol)
協議比較全能,既可以用來推送,又可以用來直播。其核心理念是將大塊的視頻幀和音頻幀“剁碎”,然后以小數據包的形式在互聯網上進行傳輸,且支持加密,因此隱私性相對比較理想,但拆包組包的過程比較復雜,所以在海量并發時容易出現一些不可預期的穩定性問題。
HLS(HTTP Live Streaming)
蘋果推出的解決方案,將視頻分成 5-10 秒的視頻小分片,然后用 M3U8 索引表進行管理。由于客戶端下載到的視頻都是 5-10 秒的完整數據,故視頻的流暢性很好,但也同樣引入了很大的延遲(HLS 的一般延遲在 10-30s 左右)。相比于 FLV,HLS 在iPhone 和大部分 Android 手機瀏覽器上的支持非常給力,所以常用于 QQ 和微信朋友圈的 URL 分享。
HTTP-FLV(Flash Video)
由 Adobe 公司主推,格式極其簡單,只是在大塊的視頻幀和音視頻頭部加入一些標記頭信息,由于這種極致的簡潔,在延遲表現和大規模并發方面都很成熟。唯一的不足就是在手機瀏覽器上的支持非常有限,但是用作手機端 APP 直播協議卻異常合適。
RTMP、HLS、HTTP-FLV 協議對比如下圖所示:
直播原理
我的困惑: 想要實現直播,需要經歷怎樣的過程?
如果用一句話描述整體過程,其實就是直播時,主播端將直播流推向服務器,用戶端發起請求從服務器拉視頻流過來解碼播放,流程如下圖所示:
第一部分就是視頻主播端的操作:視頻采集處理后推流到流媒體服務器。
首先從前端采集設備中獲得原始的音頻、視頻數據;
為了增強額外效果,對音頻進行混音、降噪等處理,可為視頻打上時間戳、添加Logo水印或增加濾鏡;
隨后對音頻、視頻進行編碼,通過編碼壓縮滿足其在互聯網上實時傳輸的需求;
編碼后就可以把各種多媒體內容(視頻、音頻、字幕等)盛放在同一個容器里,也就是所謂的封裝,使得不同多媒體內容可同步播放,與此同時還提供了索引;
最后就是通過流傳輸協議將封裝好的內容推送到流媒體服務器上;
第二部分就是流媒體服務器:負責把從第一部分接收到的流進行處理并分發給用戶。
流媒體服務器的主要功能是對流媒體內容進行采集(接收推流)、緩存、調度和傳輸播放(以流式協議實現用戶分發)。
典型的流媒體服務器:
微軟的Windows Media Service(WMS):它采用MMS協議接收、傳輸視頻,采用Windows Media Player(WMP)作為前端播放器;
RealNetworks公司的Helix Server:采用RTSP/RTP協議接收、傳輸視頻,采用Real Player作為播放前端播放器;
Adobe公司的Flash Media Server:采用RTMP(RTMPT/RTMPE/RTMPS)協議接收、傳輸視頻,采用Flash Player作為前端播放器;
第三部分就是用戶:只需要擁有支持對應流媒體傳輸協議的播放器即可。
這一部分其實就是我們前端需要實現的,如何在移動端的內嵌h5頁面中實現直播流的播放。所以我們只需要關注后端是通過什么協議給我們返回直播流以及我們如何有效的播放就可以了~
客戶端直播插件
我的困惑: 除了采用h5原生的<video></<video>標簽,我們還能用什么插件實現視頻直播,不同插件之間有什么區別?
經過我暴風式搜索后找到三款常用并且支持實時流媒體播放的客戶端插件(hls.js、video.js、vue-video-player),下面我們一個個道來。
hls.js
hls.js是一個可以實現HTTP實時流媒體客戶端的js庫,主要依賴于<video></<video>標簽和Media Source ExtensionsAPI。它的工作原理是將MPEG2傳輸流和AAC/MP3流轉換成ISO BMFF (MP4)片段。由于hls.js是基于標準的<video></<video>標簽實現播放,所以它不需要額外的播放器。
優點: 包比較小,很純凈,UI可以根據自己的業務自行擴展,功能可以根據需求進行封裝,比較靈活,而且專業直播HLS協議流。
缺點: 對于常規的通用性播放器沒有封裝好的UI,功能上也需要自己調API實現,協議單一,只支持HLS。
video.js
video.js是一個基于h5的網絡視頻播放器,支持h5視頻、現代流媒體格式(MP4、WebM、HLS、DASH等)以及YouTube、Vimeo,甚至連flash也支持(通過插件實現,后面會詳細說明),可在桌面端或移動端實現視頻播放。
優點: 支持多種格式的流媒體播放,瀏覽器不支持時可實現優雅降級;專門有一套針對直播流的UI;插件機制強大,目前社區已有數百個皮膚和插件供下載;兼容性好,幾乎支持所有桌面及移動端的瀏覽器。
缺點: 包比較大,實現hls直播的時候其實是內嵌了hls.js的代碼,由于封裝好UI和功能,使其不夠靈活,修改UI時需要通過插件實現。
vue-video-player
vue-video-player其實就是將video.js集成到了Vue中,在Vue項目中使用起來會更方便。
移動端內嵌h5實現視頻直播
1、技術選型:
傳輸協議——由于后端支持同時返回HLS協議和RTMP協議的直播流,結合考慮HLS協議的高延時問題和RTMP協議的兼容性問題,本項目決定采用向下兼容的方式實現,默認使用RTMP協議直播,當瀏覽器不支持時降級使用HLS協議播放。
直播插件——本項目基于Vue實現,并且業務邏輯為常規直播操作,無特殊需求,從開發效率、穩定性及兼容性出發,決定采用vue-video-player插件實現。
2、vue-video-player安裝與引入:
CDN:
<link rel="stylesheet" href="path/to/video.js/dist/video-js.css"/>
<script type="text/javascript" src="path/to/video.min.js"></script>
<script type="text/javascript" src="path/to/vue.min.js"></script>
<script type="text/javascript" src="path/to/dist/vue-video-player.js"></script>
<script type="text/javascript">
Vue.use(window.VueVideoPlayer)
</script>
NPM(支持全局/按需引入):npm install vue-video-player --save
全局引入
import Vue from 'vue'
import VueVideoPlayer from 'vue-video-player'
// 引入videojs樣式
import 'video.js/dist/video-js.css'
// 自定義樣式引入,并為<video-player>添加對應類名即可,例如vjs-custom-skin
// import 'vue-video-player/src/custom-theme.css'
Vue.use(VueVideoPlayer, /* {
options: 全局默認配置,
events: 全局videojs事件
} */)
按需引入
// 引入videojs樣式
import 'video.js/dist/video-js.css'
import { videoPlayer } from 'vue-video-player'
export default {
components: {
videoPlayer
}
}
3、video.js插件擴展: 當已有插件(video.js插件集合:https://videojs.com/plugins/)無法滿足需求時可對已有插件進行擴展或自行開發video.js插件
import videojs from 'video.js'
// videojs plugin
const Plugin = videojs.getPlugin('plugin')
class ExamplePlugin extends Plugin {
// something...
}
videojs.registerPlugin('examplePlugin', ExamplePlugin)
// videojs language
videojs.addLanguage('es', {
Pause: 'Pausa',
// something...
})
// more videojs api...
// vue component...
具體實現方式可參見:https://github.com/videojs/video.js/blob/master/docs/guides/plugins.md
4、視頻直播關鍵代碼:
options:video.js options
playsinline:設置播放器在移動設備上不全屏[ Boolean, default: false ]
customEventName:自定義狀態變更時的事件名[ String, default: 'statechanged' ]
<template>
<video-player
class="video-player-box"
ref="videoPlayer"
:options="playerOptions"
:playsinline="true"
customEventName="customstatechangedeventname"
@play="onPlayerPlay($event)"
@pause="onPlayerPause($event)"
@ended="onPlayerEnded($event)"
@waiting="onPlayerWaiting($event)"
@playing="onPlayerPlaying($event)"
@loadeddata="onPlayerLoadeddata($event)"
@timeupdate="onPlayerTimeupdate($event)"
@canplay="onPlayerCanplay($event)"
@canplaythrough="onPlayerCanplaythrough($event)"
@statechanged="playerStateChanged($event)"
@ready="playerReadied">
</video-player>
</template>
export default {
data() {
return {
playerOptions: {
// 是否關閉音頻
muted: true,
// 初始語言,默認為英語,code參見:https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
language: 'zh-CN',
// 播放速度,指定后Video.js將顯示一個控件(vjs-playback-rate類的控件),允許用戶從選項數組中選擇播放速度
playbackRates: [0.5, 1.0, 1.5, 2.0],
// 將播放器置于流暢模式,并在計算播放器的動態大小時使用該值,表示長寬比例
aspectRatio: '4:3',
// 等同于原生<video>標簽中的一組<source>子標簽,可實現優雅降級;type 屬性規定媒體資源的 MIME 類型,標準類型可參見:https://www.iana.org/assignments/media-types/media-types.xhtml;
sources: [{
type: "rtmp/flv",
src: "rtmp://58.200.131.2:1935/livetv/hunantv"
}, {
type: "application/x-mpegURL",
src: "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8"
}],
// 兼容順序,默認值是['html5'],這意味著html5技術是首選,其他已注冊的技術將按其注冊的順序在該技術之后添加。
techOrder: ['flash'],
// 在視頻開始播放之前顯示的圖像的URL(封面),這通常是一個視頻幀或自定義標題屏幕,一旦用戶點擊“播放”,圖像就會消失。
poster: require('../assets/test.jpg'),
}
}
},
mounted() {
console.log('this is current player instance object', this.player)
},
computed: {
player() {
return this.$refs.videoPlayer.player
}
},
methods: {
// 各個事件監聽
onPlayerPlay(player) {
// console.log('播放器播放!', player)
},
onPlayerPause(player) {
// console.log('播放器暫停!', player)
},
// ...(此處省略多個事件監聽函數)
// 狀態監聽
playerStateChanged(playerCurrentState) {
// console.log('播放器當前狀態更新', playerCurrentState)
},
// 監聽播放器是否就緒
playerReadied(player) {
console.log('播放器已就緒', player)
// 就緒后就可以調用播放器的一些方法
}
}
}
踩坑小tips:
播放 HLS 協議流,需要videojs-contrib-hls插件,但是直接引用即可,因為在安裝vue-video-player插件時,videojs-contrib-hls是一并安裝的;如果需要播放RTMP協議流,需要videojs-flash插件,也是直接引用就可以了(flash插件需要在hls之前引用)
import 'videojs-flash'
import 'videojs-contrib-hls'
5、效果展示:
封面
rtmp
hls
總結
本文首先闡述了流媒體、流媒體傳輸方式、流媒體傳輸協議以及RTSP協議的概念;接著基于項目直播需求引出三種常用直播流協議RTMP、HLS、HTTP-FLV,并對三種協議進行了對比分析,為后續技術選型提供參考;然后根據通用直播原理描述了整個直播流數據傳輸的過程,從采集、處理、編碼、封裝到推流、分發與播放,表明前端的重點工作在最后一步即流媒體播放;隨后對常用的三款客戶端直播插件hls.js、video.js、vue-video-player進行說明,并分析了各自的優缺點;最后詳細總結了移動端內嵌h5實現視頻直播的編碼過程,包括技術選型、插件的安裝與引入、插件擴展、視頻直播關鍵代碼及最終的效果展示。
本項目中視頻直播方式的實現大大提高了前端的開發效率,并且保證了桌面端與移動端的兼容性,同時增強了用戶體驗,比傳統只使用一種協議的播放源更靈活,為通用直播需求提供解決方案。
參考資料
1、直播流播放協議:https://help.aliyun.com/knowledge_detail/49785.html
2、流媒體服務器:https://baike.baidu.com/item/%E6%B5%81%E5%AA%92%E4%BD%93%E6%9C%8D%E5%8A%A1%E5%99%A8/9711212?fr=aladdin
3、hls.js:https://github.com/video-dev/hls.js
4、video.js: https://github.com/videojs/video.js
5、vue-video-player:https://github.com/surmon-china/vue-video-player
總結
以上是生活随笔為你收集整理的前端视频直播技术总结及video.js在h5页面中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「经验分享」说一个女孩子心气太高是什么意
- 下一篇: 观音菩萨有哪些重要纪念日