rtsp推流技术方法总结

1,361 阅读3分钟

rtsp是比较常用的视频流,nvr和网络摄像头基本上都支持rtsp,它是视频流中的牛鼻子,搞定了rtsp,就成功了一半。废话不多说,直接上干货。

准备条件

  • 安装ffmpeg
  • rtsp服务器,本地可以使用easyDarwin

正文

1.最原始的方式——使用ffmpeg命令直接推流

#简单将本地一个mp4视频无限循环推流
ffmpeg -re -stream_loop -1 -i 路径\xxx.mp4 -b:v 1000k -bufsize 1000k -maxrate 1500k -profile:v baseline -g 50 -vf  -vcodec h264 -f rtsp  rtsp://127.0.0.1:554/test


#光有画面不够,想加点文字
ffmpeg -re -stream_loop -1 -i 路径\xxx.mp4 -b:v 1000k -bufsize 1000k -maxrate 1500k -profile:v baseline -g 50 -vf 
"drawtext=fontfile={自定义字体路径}/simsun.ttf: text='想要添加的文字 ':fontsize=40:fontcolor=yellow:x=10:y=10" 
 -vcodec h264 -f rtsp  rtsp://127.0.0.1:554/test
 
 #光有静态文字不够,加上动态的时间戳,只要修改一下参数 
"drawtext=fontfile={自定义字体路径}/simsun.ttf: text='%{localtime:%Y-%m-%d %H-%M-%S}':fontsize=40:fontcolor=yellow:x=10:y=10" 

关于命令中的那些参数,自己可以多尝试,比如码率和buffer区大小,以自己项目中效果最佳为合适。至于编码方式,鉴于通用性,我推荐使用h264。 下面是推流之后使用vlc播放的画面 image.png

2. 最灵活的一种方式——python调用ffmpeg

不管是node还是python,都可以通过子进程调用其它语言命令。这里以python为例

import cv2
import subprocess

'''拉流url地址,指定 从哪拉流'''

pull_url = 'rtsp://127.0.01:554/test' # "rtsp_address"

# 这里看需要,基本你想要的cv2基本都能帮你满足
video_capture = cv2.VideoCapture(pull_url) # 调用摄像头的rtsp协议流
# video_capture = cv2.VideoCapture("1.mp4") # 读取文件的话
# video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 如果想要自己摄像头的画面

#获取画面宽高
width = int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT))

'''推流url地址,指定 用opencv把各种处理后的流(视频帧) 推到 哪里'''
push_url = "rtsp://127.0.0.1:554/test2"

fps = 15
command = ['ffmpeg', # linux不用指定
    '-y', '-an',
    '-f', 'rawvideo',
    '-vcodec','rawvideo',
    '-pix_fmt', 'bgr24', #像素格式
    '-s', "{}x{}".format(width, height),
    '-r', str(fps), # 自己的摄像头的fps是0,若用自己的notebook摄像头,设置为15、20、25都可。 
    '-i', '-',
    '-c:v', 'libx264',  # 视频编码方式
    # '-b:v', '1000k',
    '-bufsize', '1000k',
    '-maxrate', '1000k',
    '-pix_fmt', 'yuv420p',
    '-preset', 'ultrafast',
    '-f', 'rtsp', #  flv rtsp
    '-rtsp_transport', 'udp',  # 使用TCP推流,linux中一定要有这行
    push_url] # rtsp rtmp  
pipe = subprocess.Popen(command, shell=False, stdin=subprocess.PIPE)


while True:
    ret, frame = video_capture.read()
   
    # Hit 'q' on the keyboard to quit!
    if cv2.waitKey(delay=100) & 0xFF == ord('q'): #  delay=100ms为0.1s .若dealy时间太长,比如1000ms,则无法成功推流!
        break
    # 存入管道用于直播
    pipe.stdin.write(frame.tostring())
    # pipe.stdin.write(frame.tobytes())
    #out.write(frame)    #同时 存入视频文件 记录直播帧数据
video_capture.release()
cv2.destroyAllWindows()
pipe.terminate()

以上代码是通过管道的方式进行的rtsp推流,为什么说是最灵活的呢,因为这种方式就是针对每一帧图像,cv2负责采集每一帧画面,比如摄像头或者视频文件之类的,接下来将这一帧图像存入管道,而子进程可以通过管道源源不断获取到新的画面,这样就省去了中间文件的转储,非常实用。

3.其它现成的工具

还有很多开源工具诸如obs,vlc等都可以实现。obs默认的是推流成rtmp,只要去下载一个rtsp推流插件安装一下即可。vlc串流成rtsp即可。

image.png

image.png

以上是我学习中参考各家之长后的总结学习,便于今后参照。