Python抓取直播视频利用FFmpeg推送直播流到SRS,并通过Nginx开放WebRTC接口,给前端显示播放直播视频
本文介绍如何使用Ubuntu、Docker、SRS、Python、FFmpeg和Nginx搭建低延迟直播系统。Python负责推流,SRS负责把RTMP转换成WebRTC,Nginx负责HTTPS、反向代理和对外接口,前端通过接口获取播放地址并显示直播画面。
一、系统原理
完整链路如下:
RTSP摄像头、USB摄像头或本地视频
↓
Python启动FFmpeg
↓
H.264/AAC编码
↓
RTMP推送到SRS 1935端口
↓
SRS转换成WebRTC
↓
Nginx代理WHEP信令和Python开放接口
↓
前端浏览器播放
Nginx只代理HTTPS接口和WebRTC信令,不负责WebRTC媒体编码。浏览器通过Nginx访问WHEP接口获得SDP信息后,视频数据仍然通过SRS的8000/UDP端口传输,因此该UDP端口必须对外开放。
SRS支持通过WHEP播放WebRTC流,其接口使用POST /rtc/v1/whep/,请求内容为SDP,成功时返回HTTP 201和SDP Answer。SRS官方也说明可以使用Nginx提供HTTPS代理。
二、服务器环境
建议环境:
操作系统:Ubuntu 22.04或24.04
服务器配置:2核CPU、2GB内存以上
域名:live.example.com
需要开放:
80/TCP Nginx HTTP
443/TCP Nginx HTTPS
1935/TCP RTMP推流
8000/UDP WebRTC媒体传输
1985、8080和Python接口端口只监听本机,不直接向公网开放。
安装基础环境:
sudo apt update
sudo apt install -y docker.io nginx python3 python3-venv ffmpeg
sudo systemctl enable --now docker nginx
三、配置SRS服务器
创建配置文件: #这个配置文件很重要,如果配置错误会影响推送的视频卡顿,延迟,和推送失败等问题
sudo mkdir -p /opt/srs/conf
sudo nano /opt/srs/conf/rtmp2rtc.conf
写入:
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
http_api {
enabled on;
listen 1985;
}
stats {
network 0;
}
rtc_server {
enabled on;
listen 8000;
candidate $CANDIDATE;
}
vhost __defaultVhost__ {
rtc {
enabled on;
# RTMP推流转换为WebRTC
rtmp_to_rtc on;
rtc_to_rtmp off;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
}
其中最重要的是:
rtmp_to_rtc on;
如果设置为off,RTMP虽然能够正常推送到SRS,但前端无法通过WebRTC播放。
启动SRS,将公网IP替换为服务器真实IPv4地址:
docker run -d \
--name srs \
--restart unless-stopped \
-e CANDIDATE=服务器公网IP \
-p 1935:1935 \
-p 127.0.0.1:1985:1985 \
-p 127.0.0.1:8080:8080 \
-p 8000:8000/udp \
-v /opt/srs/conf/rtmp2rtc.conf:/usr/local/srs/conf/rtmp2rtc.conf:ro \
ossrs/srs:6 \
./objs/srs -c conf/rtmp2rtc.conf
查看运行状态:
docker ps
docker logs -f srs
SRS的candidate必须是浏览器能够访问的公网IP,否则SDP中可能返回错误地址,造成有推流记录但播放黑屏。
四、Python推送直播流
创建push_stream.py:
import os
import subprocess
import time
input_url= 视频地址
headers_str = 请求视频的请求头(字符串类型)
srs_host = "服务器公网IP
stream_name =推送地址名称
rtmp_url= f"rtmp://{srs_host}:1935/live/{stream_name}"
command= ['ffmpeg', '-hide_banner', '-loglevel', 'warning', '-nostdin',
'-rw_timeout', '15000000', '-reconnect', '1', '-reconnect_streamed', '1', '-reconnect_delay_max', '5',
'-headers', headers_str, '-f', 'live_flv', '-i', input_url,
'-map', '0:v:0', '-map', '0:a:0?', '-dn', '-sn',
'-c:v', 'copy', '-c:a', 'copy',
'-flvflags', 'no_duration_filesize', '-f', 'flv', rtmp_url, ]
while True:
try:
print("正在推流:", input_url)
subprocess.run(command, check=True)
except KeyboardInterrupt:
print("推流已停止")
break
except subprocess.CalledProcessError:
print("推流中断,3秒后重新连接")
time.sleep(3)
最终推流地址为:
```text
rtmp://服务器公网IP:1935/live/camera1
创建配置:
sudo nano /etc/nginx/sites-available/live.conf
写入:
server {
listen 80;
server_name live.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name live.example.com;
ssl_certificate /etc/letsencrypt/live/live.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/live.example.com/privkey.pem;
root /var/www/live;
index index.html;
# 前端直播接口
location /api/live/ {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebRTC WHEP信令接口
location /rtc/ {
proxy_pass http://127.0.0.1:1985;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
}
# HTTP-FLV备用播放地址
location /live/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
add_header Cache-Control "no-cache";
}
# 前端页面
location / {
try_files $uri $uri/ /index.html;
}
}
Nginx的proxy_pass可以把外部HTTP请求转发到内部服务,直播响应还应关闭代理缓冲,避免Nginx缓存媒体数据。
启用配置:
sudo ln -s /etc/nginx/sites-available/live.conf \
/etc/nginx/sites-enabled/live.conf
sudo nginx -t
sudo systemctl reload nginx
七、前端调用接口播放WebRTC
浏览器打开搭建视频直播前端,利用flv或者webRTC播放方式搭建前端的:
然后建立WebRTC连接。视频默认静音以满足浏览器自动播放规则,用户可以在播放器中手动打开声音。
确认Python正在推送:
ffplay rtmp://服务器公网IP:1935/live/camera1
也可以测试HTTP-FLV:
https://live.example.com/live/camera1.flv
浏览器不能直接使用原生video标签播放FLV,需要配合flv.js播放器。
公网部署安全
示例接口允许公开访问。正式系统还应增加:
- JWT或签名鉴权;
- 播放地址有效期;
- 推流密钥;
- Nginx访问频率限制;
- HTTPS证书;
- 用户权限检查;
- 直播流名称白名单。
总结
最终架构并不是使用Nginx代替SRS,而是让Nginx作为统一公网入口:
Python和FFmpeg:采集、编码、推流
SRS:接收RTMP并转换WebRTC
Nginx:HTTPS、反向代理、前端页面
浏览器:调用接口并播放WebRTC
requirements.txt安装的环境模块
spider_qie_video.py,代码样例
ubuntu_install_srs.sh ubuntu服务器安装srs流服务器的命令
评论交流
还没有公开评论。