前言:
该部分比较麻烦,闹腾了好久(ffmpeg推拉流没学过,事实证明依葫芦画瓢是不行滴,后面有时间再学吧),后来借助chatGPT勉强解决,但不是很懂。因个人能力有限,只复述操作过程,欢迎佬指导。
准备工作:
- 搭建好了docker
- 下载好nginx-rtmp镜像
- 网络摄像头
Step1:
测试网络摄像头可用,python代码获取到的视频流如下:
Step2:
在流媒体服务器中创建一个文件夹,然后里面添加nginx.conf文件,写此文时内容变成如下(这个是最后比较好的推流的时候自动生成的):
daemon off;error_log /dev/stdout info;events {worker_connections 1024;
}rtmp {server {listen 1935;chunk_size 4000;application stream {live on;exec ffmpeg -i rtmp://localhost:1935/stream/$name-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 2500k -f flv -g 30 -r 30 -s 1280x720 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_720p2628kbs-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 1000k -f flv -g 30 -r 30 -s 854x480 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_480p1128kbs-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 750k -f flv -g 30 -r 30 -s 640x360 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_360p878kbs-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 400k -f flv -g 30 -r 30 -s 426x240 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_240p528kbs-c:a libfdk_aac -b:a 64k -c:v libx264 -b:v 200k -f flv -g 15 -r 15 -s 426x240 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_240p264kbs;}application hls {live on;hls on;hls_fragment_naming system;hls_fragment 5;hls_playlist_length 10;hls_path /opt/data/hls;hls_nested on;hls_variant _720p2628kbs BANDWIDTH=2628000,RESOLUTION=1280x720;hls_variant _480p1128kbs BANDWIDTH=1128000,RESOLUTION=854x480;hls_variant _360p878kbs BANDWIDTH=878000,RESOLUTION=640x360;hls_variant _240p528kbs BANDWIDTH=528000,RESOLUTION=426x240;hls_variant _240p264kbs BANDWIDTH=264000,RESOLUTION=426x240;}}
}http {root /www/static;sendfile off;tcp_nopush on;server_tokens off;access_log /dev/stdout combined;# Uncomment these lines to enable SSL.# ssl_protocols TLSv1.2 TLSv1.3;# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;# ssl_prefer_server_ciphers off;# ssl_session_cache shared:SSL:10m;# ssl_session_timeout 1d;server {listen 80;# Uncomment these lines to enable SSL.# Update the ssl paths with your own certificate and private key.# listen 443 ssl;# ssl_certificate /opt/certs/example.com.crt;# ssl_certificate_key /opt/certs/example.com.key;location /hls {types {application/vnd.apple.mpegurl m3u8;video/mp2t ts;}root /opt/data;add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin *;}location /live {alias /opt/data/hls;types {application/vnd.apple.mpegurl m3u8;video/mp2t ts;}add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin *;}location /stat {rtmp_stat all;rtmp_stat_stylesheet stat.xsl;}location /stat.xsl {root /www/static;}location /crossdomain.xml {default_type text/xml;expires 24h;}
我的原先版本借鉴了正点原子的文档(我太菜没搞好):
Step3:
创建一个容器,此处运行命令与上一篇不同:
docker run -it -p 1935:1935 -p 8080:80 --name my-nginx-rtmp-test -v /nginx/nginx.conf:/etc/nginx/nginx.conf -d alfg/nginx-rtmp
-
docker run
:这是运行 Docker 容器的命令。 -
it
:这两个选项结合了两个标志:i
:保持 STDIN 开启,即使未连接。t
:分配一个伪终端(tty)。
它们一起允许你与容器进行交互,使容器在前台运行。
-
p 1935:1935
:此标志将主机的端口 1935 映射到容器中的端口 1935。通常用于 RTMP(实时消息传递协议)流媒体。 -
p 8080:80
:此标志将主机的端口 8080 映射到容器中的端口 80。通常用于提供 HTTP 流量服务。 -
-name my-nginx-rtmp-test
:此标志为容器指定一个名称,这里是 “my-nginx-rtmp-test”。 -
v /nginx/nginx.conf:/etc/nginx/nginx.conf
:此标志将本地文件/nginx/nginx.conf
挂载到容器的路径/etc/nginx/nginx.conf
。这用于提供自定义的 Nginx 配置。 -
d
:此标志以后台模式(detached mode)运行容器。 -
alfg/nginx-rtmp
:这是用于创建容器的 Docker 镜像的名称。在这种情况下,它是一个配置了 RTMP 支持的 Nginx 服务器镜像。
至此,流媒体服务器创建成功:
Step4:
推流(这才是难点啊),在推流尝试中出现过如下问题:
- 视频流是HEVC编码,而FLV格式不支持HEVC编码
- HEVC找不到参考帧:
- RTSP流延迟和数据包丢失
- FLV头更新失败
…
解决:
在控制台先推流一段时间,看看报了那些错误,然后根据这些错误提示去搜索解决的办法(确实不懂ffmpeg),然后一个个尝试,然后比较好点的推流解决方法建议是:使用 -use_wallclock_as_timestamps 1
选项,该选项可以将系统时钟作为时间戳,而不是依赖于从 RTSP 流中提取的时间戳。这有时可以解决时间戳问题。
推流命令如下:
ffmpeg -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i rtsp://admin:admin@ip -c:v libx264 -b:v 1000k -c:a aac -ar 44100 -f flv rtmp://ip:1935/stream/example
use_wallclock_as_timestamps 1
:使用 wallclock 作为时间戳。rtsp_transport tcp
:使用 TCP 作为 RTSP 传输协议。i rtsp://admin:admin@ip
:输入源是一个 RTSP 地址,包括用户名和密码,以及相应的 IP 地址。c:v libx264
:设置视频编码器为 libx264。b:v 1000k
:设置视频比特率为 1000k(1000 kbps)。c:a aac
:设置音频编码器为 AAC。ar 44100
:设置音频采样率为 44100 Hz。f flv
:指定输出格式为 FLV。rtmp://ip:1935/stream/example
:指定输出的 RTMP 地址,包括服务器的 IP 地址和端口,以及流的名称为 “example”。
效果:
上面的图是python中测试的,下图是在局域网下其他电脑上拉取流的情况,有延迟!!!后面再琢磨吧,欢迎佬指导。