本文所包含內(nèi)容:
- 直播的主流協(xié)議
- Video屬性和方法詳解
- 直播源的制作
- H5直播演示
- 微信小程序直播演示
- 常見問題
直播的主流協(xié)議
HLS協(xié)議, RTMP協(xié)議, HTTP-FLV協(xié)議
HLS協(xié)議
<video>獲取M3U8索引文件,文件中包含包含其它M3U8文件和視頻分段
此類文件包含三種類型:動態(tài)列表、靜態(tài)列表和全量列表,后兩者較前者會多一到兩個字段,文件示例
#EXTM3U
#EXT-X-VERSION:6 # 版本號,默認(rèn)是3
#EXT-X-TARGETDURATION:6 # 時長
#EXT-X-MEDIA-SEQUENCE:0 # 序號
#EXT-X-PLAYLIST-TYPE:EVENT # 靜態(tài)列表包含
#EXT-X-PLAYLIST-TYPE:VOD # 全量列表包含
#EXTINF:4.797000,
index0.ts
#EXTINF:4.396000,
index1.ts
#EXTINF:5.297000,
index2.ts
#EXT-X-ENDLIST # 全量列表包含
TS文件解析流程
使用方便,但缺點是在同一個M3U8中分片文件過多時會帶來高延時
RTMP協(xié)議
RTMP(Real Time Messaging Protocol)
RTMP協(xié)議
傳輸文件格式是FLV,基于TCP協(xié)議,需要處理3次握手,因為使用更為復(fù)雜
HTTP-FLV協(xié)議
HTTP-FLV協(xié)議結(jié)合了HLS使用方便和RTMP低延時的特性
相比較RTMP協(xié)議的優(yōu)點:
1、可以在一定程度上避免防火墻的干擾(例如,有的機(jī)房只允許80端口通過)
2、可以很好的兼容HTTP 302跳轉(zhuǎn),做到靈活調(diào)度
3、可以使用HTTPS做加密通道
4、很好地支持移動端(Android, iOS)
Video屬性和方法詳解
相關(guān)工具:Web Server for Chrome(在Chrome上模擬服務(wù)器請求)
下載、全屏隱藏:controlslist: nodownload, nofullscreen
貼圖:poster屬性
自動播放: autoplay
靜音:muted (移動端非靜音視頻不允許自動播放)
循環(huán)播放:loop
預(yù)加載:preload (不同瀏覽器和客戶端表現(xiàn)會存在差異)
音量控制:默認(rèn)音量是1,添加volume屬性通常無法生效,需通過JS代碼來實現(xiàn),如:
<script type="text/javascript">
var v = document.getElementById("my_video");
# 播放音量控制
v.volume = 0.5;
# 播放時間控制(單位:秒)
v.currentTime = 60;
# 視頻地址切換(如切換不同清晰度)
v.src = "xxxx.mp4";
# 時長: duration
</script>
備用地址切換
# 當(dāng)?shù)谝粋€地址出錯時,訪問第二視頻地址
<video id="my_video" width="400" height="225"
controls controlslist="nodownload nofullscreen">
<source src="./video1.mp4" type="video/mp4">
<source src="./video2.mp4" type="video/mp4">
</video>
# 此時通過前述的v.src獲取的地址為空,需使用v.currentSrc
事件
加載開始:loadstart
時長變化:durationchange
視頻元數(shù)據(jù)下載完成:loadedmetadata
沒有足夠的數(shù)據(jù)播放下一幀:loadeddata
正在下載數(shù)據(jù):progress
視頻有幀可以播放:canplay
可以流暢地播放:canplaythrough
播放:play
暫停:pause
點擊進(jìn)度條視頻查找:seeking
視頻查找結(jié)束:seeked
正在準(zhǔn)備數(shù)據(jù):waiting
準(zhǔn)備好數(shù)據(jù)播放:playing
播放時間變化:timeupdate
播放結(jié)束:ended
播放出錯:error
# 加載開始loadstart
v.addEventListener('loadstart', function(e) {
console.log('loadstart');
})
直播源的制作
Nginx安裝
Mac:
brew tap denji/nginx
brew install nginx-full --with-rtmp-module
# 輸入nginx啟動服務(wù),使用http://localhost:8080進(jìn)行驗證
# ngnix -s stop; nginx -s reload
Windows:
http://nginx.org/en/docs/windows.html (按步驟操作需先安裝Git Bash)
FFmpeg安裝
Mac:
brew install ffmpeg
# 輸入ffmpeg進(jìn)行驗證
Windows:
http://ffmpeg.org/download.html
https://ffmpeg.zeranoe.com/builds/
配置Nginx
# Mac配置
cd /usr/local/etc/nginx/
# -a后加atom或其它編輯器名稱打開文件
open nginx.conf -a "Visual Studio Code"
# Windows下找到對應(yīng)文件
# 添加rtmp模塊
rtmp{
server {
listen 1935;
# 分塊大小
chunk_size 4000;
# RTMP 直播流配置
application rtmplive {
live on;
max_connections 1024;
}
# hls 直播流配置
application hls {
live on;
hls on;
# 分片路徑
hls_path /usr/local/var/www/hls;
hls_fragment 5s;
}
}
}
# 配置http版塊
http {
...
server {
...
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /usr/local/var/www;
add_header Cache-Control no-cache;
# 解決跨域請求的問題
add_header Access-Control-Allow-Origin *;
}
}
}
工具準(zhǔn)備:VLC播放器和Safari瀏覽器
RTMP測試:
通過本地視頻模擬推流
ffmpeg -re -i test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/rtmp
VLC播放器中點擊File > Open Network...,然后在URL部分輸入前面定義的地址:
rtmp://localhost:1935/rtmplive/rtmp
HLS測試
模擬HLS推流
ffmpeg -re -i test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/hls/stream
打開Safari瀏覽器中打開http://localhost:8080/hls/stream.m3u8進(jìn)行訪問
TODO:HTTP-FLV的推流方式相對復(fù)雜,后續(xù)進(jìn)行補(bǔ)充
封裝包推流
如果您對Nginx不了解也不想要了解相關(guān)細(xì)節(jié),還可以通過已封裝的包進(jìn)行測試
鏈接: https://pan.baidu.com/s/1jV51FmC0TodGODKiJM4BUg 密碼: qbu9
下載該文件直接運行即可
# 執(zhí)行以下命令推流
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/movie
# 直播地址
# hls
http://127.0.0.1:7002/live/movie.m3u8
# http-flv
http://127.0.0.1:7001/live/movie.flv
# rtmp
rtmp://localhost:1935/live/movie
H5直播演練
# 安裝eslint
npm install eslint -g
# 初始化package.json
npm init
eslint --init
# ? How would you like to configure ESLint? Use a popular style guide
# ? Which style guide do you want to follow? Standard
# ? What format do you want your config file to be in? JavaScript
# 目錄準(zhǔn)備
mkdir source
cd source
mkdir videojs
mkdir hlsjs
mkdir flvjs
HLS視頻直播
Video.js
# VIDEOJS擁有豐富的<a target="_blank">插件</a>
cd videojs
curl -O vjs.zencdn.net/6.7/video-js.min.css
curl -O vjs.zencdn.net/6.7/video.min.js
# 點播測試代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>video.js點播視頻的應(yīng)用</title>
<link rel="stylesheet" href="./video-js.min.css">
<script src="./video.min.js" type="text/javascript"></script>
</head>
<body>
<video
id="my-player"
class="video-js"
controls
preload="auto"
poster="http://vjs.zencdn.net/v/oceans.png">
<source src="../../test.mp4" type="video/mp4"></source>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that supports HTML5 video
</p>
</video>
<script type="text/javascript">
var player = videojs('my-player', {
width: 400,
height: 200
});
</script>
</body>
</html>
# 直播
curl -O https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-hls/5.14.1/videojs-contrib-hls.js
# 示例代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>video.js點播視頻的應(yīng)用</title>
<link rel="stylesheet" href="./video-js.min.css">
<script src="./video.min.js" type="text/javascript"></script>
<script type="text/javascript" src="./videojs-contrib-hls.js"></script>
</head>
<body>
<video id="my-player" class="video-js" controls>
<source src="http://live.streamingfast.net/osmflivech4.m3u8" type="application/x-mpegURL">
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
</p>
</video>
<script type="text/javascript">
var player = videojs('my-player', {
width: 400,
height: 200
});
</script>
</body>
</html>
hls.js
touch index.html
touch index.js
touch index.css
curl -O https://cdn.jsdelivr.net/npm/hls.js@latest
mv hls.js\@latest hls.js
# hls.js好處在于它的輕量,可以在沒有冗余的情況下自定義播放器的樣式,以下是冗長的示例代碼
# index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hls.js演示</title>
<script src="./hls.js" type="text/javascript"></script>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="player pause">
<video id="video"></video>
<em class="btn"></em>
<span class="state">正在直播</span>
</div>
<script src="./index.js" type="text/javascript"></script>
</body>
</html>
# index.js
var video = document.getElementById('video');
var hls_url = "http://localhost:8080/hls/stream.m3u8";
var btn = document.querySelector('.btn');
var player = document.querySelector('.player');
if(Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(hls_url);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
// video.play();
});
}else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = hls_url;
video.addEventListener('loadedmetadata',function() {
// video.play();
});
}
btn.addEventListener('click', function(){
if(video.paused){
video.play();
}else{
video.pause();
}
})
video.addEventListener('click', function() {
if(video.paused){
video.play();
}else{
video.pause();
}
})
video.addEventListener('play',function(){
player.className = 'player';
})
video.addEventListener('pause',function(){
player.className = 'player pause';
})
# index.css
html *, body *{
margin: 0;
padding: 0;
}
.player{
width: 400px;
height: 200px;
position: relative;
}
.player video{
width: 100%;
height: 100%;
}
.player .btn{
display: none;
width: 40px;
height: 40px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
margin: -35px auto auto -35px;
padding: 15px;
background: rgba(255, 255, 255, 0.5);
line-height: 40px;
}
.player .btn:hover{
background: rgba(255, 255, 255, 0.7);
}
.player .btn:before{
border: 20px solid #ddd;
border-top-color: transparent;
border-bottom-color: transparent;
border-right-color: transparent;
content: " ";
display: block;
margin-left: 10px;
width: 0;
height: 0;
}
.player.btn:before:hover{
border-left-color: #fff;
}
.player.pause .btn{
display: block;
}
.player .state{
position: absolute;
bottom: 20px;
left: 20px;
font-size: 14px;
color: #000;
}
.player.pause .state{
display: none;
}
HTTP-FLV視頻直播
flv.js
cd ../flvjs
touch index.html
touch index.js
curl -O http://bilibili.github.io/flv.js/dist/flv.js
# index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>flv.js演示</title>
<script src="./flv.js" charset="utf-8"></script>
</head>
<body>
<video id="videoElement" width="400" height="200" controls></video>
<script src="./index.js" charset="utf-8"></script>
</body>
</html>
# index.js
var flvjs = window.flvjs;
if (flvjs.isSupported()) {
var videoElement = document.getElementById('videoElement');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'http://127.0.0.1:7001/live/movie.flv'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
微信小程序直播演示
需通過小程序開發(fā)工具的遠(yuǎn)程調(diào)試功能在手機(jī)上進(jìn)行調(diào)試,手機(jī)與電腦在同一局域網(wǎng),并且在直播源中使用內(nèi)網(wǎng)地址192.168..
<!--index.wxml-->
<view class="container">
<view>
<live-player src="http://192.168.xxx.xxx:7001/live/movie.flv" mode="live" autoplay bindstatechange="statechange" binderror="error" style="width: 300px; height: 225px;" />
</view>
</view>
//index.js
Page({
statechange(e) {
console.log('live-player code:', e.detail.code)
},
error(e) {
console.error('live-player error:', e.detail.errMsg)
}
})
常見問題
1.Error: homebrew/nginx was deprecated. This tap is now empty as all its formulae were migrated.
brew tap denji/nginx
原文鏈接:Alan Hou 的個人博客