chrome无插件播放实时视频

背景

之前在IE时代,安防播放视频都是采用activeX +rtsp的方式;chrome+firefox 使用npapi的控件 或者chrome、firefox采用flash + rtmp;
但后来chrome去掉了npaip和flash的支持。
这里主要讲解如何在chrome中进行无控件播放实时视频

PC 用flv.js 播放http-flv流

web用video.js 播放http-hls流

相关知识

先阅读以下文章
https://cloud.tencent.com/developer/article/1467813

https://www.cnblogs.com/upyun/p/9881865.html

无控件实时播放就是http+hls 、 http-flv 、webassembly的方式,但hls需要m3u8分片,延时会比flv大

我的需求只要能够在chrome上低延时无控件播放h264码流,简单点所以并没有采用ffmpeg+webAssembly的技术,而是采用http-flv的方式。

基本原理

通过rtsp从ipc引流,经ffmpeg转码为rtmp到nginx-http-flv-module,
前端通过flv.js 进行引流播放,达到低延时、秒开的效果。

环境搭建

http://nginx.org/en/download.html

https://github.com/winshining/nginx-http-flv-module

https://github.com/bilibili/flv.js

https://github.com/FFmpeg/FFmpeg/tree/release/4.3

nginx + http-flv-module 编译

1
2
3
4
yum install gcc-c++ zlib zlib-devel pcre  pcre-devel zlib  zlib-devel openssl openssl-devel -y
./configure --prefix=/usr/local/nginx-1.18 --add-module=/home/install/nginx-http-flv-module-master --with-http_ssl_module

make && make install

ffmpeg 编译

1
2
3
4
5
6
7
8
9
首先安装yasm插件
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar -xvf yasm-1.3.0.tar.gz
cd yasm-1.3.0/
./configure && make && make install

然后
cd ffmpeg-4.3/
./configure && make && make install

flv.js 部署

https://github.com/bilibili/flv.js/tree/master/demo
下载 index.html 和 demo.css ,并修改index.html 中flv.js 路径

通过 http://bilibili.github.io/flv.js/demo/ 查看源代码,并在flv.js/dist 中下载 flv.js

以上三个文件放置在 nginx/html下

nginx conf设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180


#user nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 1024;
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;

rtmp {
out_queue 4096;
out_cork 8;
max_streams 128;
timeout 15s;
drop_idle_publisher 15s;

log_interval 5s; #interval used by log module to log in access.log, it is very useful for debug
log_size 1m; #buffer size used by log module to log in access.log

server {
listen 1935 reuseport;

application live {
live on;
gop_cache on; #open GOP cache for reducing the wating time for the first picture of video
}

application hls {
live on;
hls on;
hls_path /tmp/hls;
}
application dash {
live on;
dash on;
dash_path /tmp/dash;
}
}
}

http {
include mime.types;
default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 8080;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root html;
index index.html index.htm;
}

# 支持http-flv 播放
location /live {
flv_live on; #打开HTTP播放FLV直播流功能
chunked_transfer_encoding on; #支持'Transfer-Encoding: chunked'方式回复

add_header 'Access-Control-Allow-Origin' '*'; #添加额外的HTTP头
add_header 'Access-Control-Allow-Credentials' 'true'; #添加额外的HTTP头
}

location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}

root /tmp;
add_header 'Cache-Control' 'no-cache';
}

location /dash {
root /tmp;
add_header 'Cache-Control' 'no-cache';
}

location /control {
rtmp_control all; #rtmp控制模块的配置
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

# location / {
# root html;
# index index.html index.htm;
# }
#}

}

测试 rtmp、http-flv

启动nginx ,然后执行

1
ffmpeg -re -i yxjx.mp4 -vcodec copy -an -f flv rtmp://localhost:1935/live/steam

打开vlc 网络分别输入:

1
2
3
http://192.168.50.200:8080/live?port=1935&app=live&stream=steam

rtmp://192.168.50.200:1935/live/steam

视频正常播放

打开网站

1
2
3
4
http://192.168.50.200:8080/   输入

http://192.168.50.200:8080/live?port=1935&app=live&stream=steam
去掉音频,播放正常

测试 hls

使用video.js 测试

video.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>videojs视频播放DEMO</title>
</head>
<link href="//vjs.zencdn.net/7.8.2/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/7.8.2/video.min.js"></script>
<body>
<h3>视频播放</h3>
<video id="example_video_1" class="video-js vjs-default-skin" >
<source src="http://192.168.50.200:8080/hls/steam.m3u8" ">
</video>
</body>
</html>
<script>
var player = videojs('example_video_1', {
muted: true,
controls: true,
});
</script>

ffmpeg 地址修改为

1
ffmpeg -re -i yxjx.mp4 -vcodec copy -an -f flv rtmp://localhost:1935/hls/steam

手机打开 http://192.168.50.200:8080/video.html 播放正常

遇到的问题

ffmepg 转码性能

我们对于大部分码流只要转封装即可,不需要进行转码,命令行参数

ffmpeg -i rtsp://admin:admin@192.168.1.10:554/video -vcodec copy -acodec copy -f flv rtmp://localhost:1935/live/steam

ffmepg 转码失败

我遇到音频的问题,ffmepg转码时有错误日志输出,可以查看具体原因;我不需要音频所以就去掉音频;

1
2
3
[flv @ 0x3a1c600] FLV does not support sample rate 48000, choose from (44100, 22050, 11025)
[flv @ 0x3a1c600] Audio codec ac3 not compatible with flv
Could not write header for output file #0 (incorrect codec parameters ?): Function not implemented

1
2
rtsp 转换
ffmpeg -i rtsp://admin:admin@192.168.1.10:554/video -vcodec copy -an -f flv rtmp://localhost:1935/live/steam
1
2
文件,需要 -re 按正常帧率推送
ffmpeg -re -i yxjx.mp4 -vcodec copy -an -f flv rtmp://localhost:1935/live/steam

音频的支持

flv 格式支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0 = Linear PCM, platform endian
1 = ADPCM
2 = MP3
3 = Linear PCM, little endian
4 = Nellymoser 16-kHz mono
5 = Nellymoser 8-kHz mono
6 = Nellymoser
7 = G.711 A-law logarithmic PCM
8 = G.711 mu-law logarithmic PCM 9 = reserved
10 = AAC
11 = Speex
14 = MP3 8-Khz
15 = Device-specific sound

7, 8, 14, and 15:内部保留使用。
flv是不支持g711a的,如果要用,可能要用线性音频。

转码时,就支持声音播放了

1
ffmpeg -re -i yxjx.mp4 -vcodec copy -acodec aac -f flv rtmp://localhost:1935/live/steam

flv.js 延时问题

在创建flv player时,设置参数

1
2
3
4
5
6
7
8
player = flvjs.createPlayer(mediaDataSource,{
type:'flv',
isLive:true,
hasAudio:false,
enableWorker:true,
enableStashBuffer:false,
stashInitialSize:128,
});

视频秒开问题

gop_cache on; 的作用是缓存了一个GOP视频,所以如果IPC的视频GOP设置为50,那么会有2s的延时;
设置了 gop_cache off; 会有最多2s的黑屏。

抓拍功能

我还得继续研究

后续计划

如果有时间,会考虑使用ffmegp+webAssembly的方法,因为这样播放器能实现更多的功能。