架设RTMP流媒体服务器并使用python进行推流
Published on
1、服务器架设
服务器不一定要安装在推流程序所在的机器上,也可以安装在发送、接收双方均可访问到的第三台机器上。
安装方式可以使用docker镜像或直接编译安装。
使用docker镜像
github地址:https://github.com/alfg/docker-nginx-rtmp
安装并运行:
docker pull alfg/nginx-rtmp
docker run -it -p 1935:1935 -p 8080:80 --rm alfg/nginx-rtmp
之后即可推流至:
rtmp://<server ip>:1935/stream/$STREAM_NAME
自行编译安装
# 安装依赖库
sudo apt install -y libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev
# 下载nginx源码并解压
wget http://nginx.org/download/nginx-1.17.8.tar.gz
tar -xf nginx-1.17.8.tar.gz
# 下载nginx-rtmp-module模块源码
git clone https://github.com/arut/nginx-rtmp-module.git
# 编译并安装带nginx-rtmp-module模块的nginx
cd nginx-1.17.8
./configure --add-module=../nginx-rtmp-module
sudo make install
配置nginx,配置文件地址为:/usr/local/nginx/conf/nginx.conf。由于目前浏览器已经禁止使用Flash,不能直接播放rtmp流,因此可以选择添加hls配置。
worker_processes 1;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
chunk_size 4096;
application stream {
live on;
record off;
# hls配置
hls on;
hls_path /var/www/hls;
hls_fragment 3;
hls_playlist_length 60;
}
}
}
http {
server {
listen 80;
# hls配置
location /hls {
# Disable cache
add_header Cache-Control no-cache;
# CORS setup
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
# allow CORS preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /var/www;
}
}
}
运行nginx:
sudo /usr/local/nginx/sbin/nginx
之后即可推流至:
rtmp://<server ip>:1935/stream/$STREAM_NAME
可以直接播放上面的rtmp流,也可以播放hls流:
http://<server ip>/hls/$STREAM_NAME
停止nginx:
sudo /usr/local/nginx/sbin/nginx -s stop
2、使用python推流
python可以使用ffmpeg命令进行推流,有两种方式:直接调用ffmpeg命令,或使用ffmpeg-python库。
安装ffmpeg:
sudo apt install -y ffmpeg
直接调用ffmpeg命令
使用subprocess开启ffmpeg子进程,在python中读取每一帧并进行处理,之后通过管道将图像交给子进程进行推流。
import cv2
import subprocess
# 设置视频文件与推流地址
filename = 'test.mp4'
push_url = 'rtmp://localhost:1935/stream/test'
# 读取视频属性
cap = cv2.VideoCapture(filename)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# ffmpeg命令
command = ['ffmpeg',
'-y',
'-f', 'rawvideo',
'-vcodec', 'rawvideo',
'-pix_fmt', 'bgr24',
'-s', "{}x{}".format(width, height),
'-r', str(fps),
'-i', '-',
'-c:v', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-f', 'flv',
push_url]
# 开启子进程
process = subprocess.Popen(command, stdin=subprocess.PIPE)
while True:
# 读取每一帧
ret, frame = cap.read()
if not ret:
break
# 处理
# frame = handle(frame)
# 交给子进程推流
process.stdin.write(frame.tobytes())
使用ffmpeg-python库
ffmpeg-python库将ffmpeg命令进行封装,实际仍会启动ffmpeg子进程,但是代码更加简洁。
github地址:https://github.com/kkroening/ffmpeg-python
安装
pip install ffmpeg-python
使用
import cv2
import ffmpeg
# 设置视频文件与推流地址
filename = 'test.mp4'
push_url = 'rtmp://localhost:1935/stream/test'
# 读取视频属性
cap = cv2.VideoCapture(filename)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 开启ffmpeg子进程
process = (
ffmpeg
.input('pipe:', format='rawvideo', pix_fmt='bgr24', s='{}x{}'.format(width, height), r=fps)
.output(push_url, vcodec='libx264', pix_fmt='yuv420p', preset='ultrafast', format='flv')
.run_async(pipe_stdin=True)
)
while True:
# 读取每一帧
ret, frame = cap.read()
if not ret:
break
# 处理
# frame = handle(frame)
# 交给子进程推流
process.stdin.write(frame.tobytes())
# 关闭子进程输入并等待结束
process.stdin.close()
process.wait()