項目上有一個播放實時視頻(直播)的需求,後端童鞋直接傳過來一個相似 https://...️️/live.m3u8
的視頻流地址。讓我自行播放,拿到地址的我一臉懵逼,下面開始個人探索(baidu)之路。git
介紹.m3u8
以前得先介紹一下HLS
技術,HLS
是蘋果公司提出的,官方給出的簡介以下:github
使用Apple的HTTP實時流媒體(HLS)技術,將實時和點播的音頻和視頻發送到iPhone,iPad,Mac,Apple TV和PC。 使用與Web相同的協議,HLS容許您使用普通Web服務器和內容交付網絡部署內容。 HLS旨在提升可靠性,並經過針對可用的有線和無線鏈接速度優化回放來動態適應網絡條件。npm
HLS
將音頻和視頻做爲一系列小文件發送,一般持續時間約爲6秒,稱爲媒體段文件。 索引文件或播放列表提供媒體段文件的URL的有序列表。 HLS
的索引文件保存爲M3U8
播放列表,這是用於MP3播放列表的M3U
格式的擴展名。 客戶端訪問索引文件的URL,而後客戶端按順序請求索引文件。後端
簡而言之,.m3u8
格式的文件是HLS
技術下的產物,它是HLS
的索引文件。若是看到後端童鞋傳給咱們的視頻流連接後綴是.m3u8
,基本就能夠判定直播流採用的是HLS
技術。瀏覽器
出於好奇,我下載了其中一個.m3u8
文件,並用電腦自帶的文本編輯器打開,內容以下:bash
它實際上就是一個普通的文本文件。服務器
#EXT-X-MEDIA-SEQUENCE
:每個媒體文件在 PlayList中的惟一序列號,相鄰之間序號加一。上圖中是序號 303。#EXT-X-TARGETDURATION
:每一份媒體文件的時間, 以秒爲單位。 上圖中是2s。#EXTINF
:格式 #EXTINF <duration>,<title>
。duration
:每一份 媒體文件持續時間;title
:每個媒體文件url地址。上圖中seghik303.ts
就是後綴爲.ts
視頻切片文件的地址,這裏看上去應該是相對路徑。我項目裏是用的hls.js來播放的(以React爲例)。網絡
npm i hls.js
複製代碼
import Hls from 'hls.js';
複製代碼
<video id="hlsVedio"></video>
複製代碼
componentDidMount() {
const video = document.getElementById('hlsVedio');
if (Hls.isSupported()) {
const hls = new Hls();
this.hls = hls;
hls.loadSource('https://.../live.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'https://.../live.m3u8';
video.addEventListener('loadedmetadata', function() {
video.play();
});
}
}
複製代碼
完成上面四步,基本上直播視頻流能夠播放了app
打開瀏覽器的控制檯看一下編輯器
它怎麼忽然穿了品如的衣服,它怎麼一直在發送請求?難道我代碼裏寫死循環了?仍是瀏覽器須要重啓一下?
再回過頭看一下HLS
,發現這項流媒體技術就是會根據.m3u8
的索引文件去不斷請求新的.m3u8
和.ts
視頻文件。因此瀏覽器不斷髮送請求是正常的,不發送纔是不正常的。
銷燬視頻流
componentWillUnmount() {
if (this.hls) {
this.hls.destroy();
}
}
複製代碼
千萬不要忘記在組件銷燬的生命週期裏銷燬建立的hls
對象,否則在SPA
應用裏切換頁面或者切換tab的時候,雖然看不到視頻組件了,但還會一直在發送請求。