ffmpeg推流rtsp vlc拉流 调用yolov5s.onnx人体检测 截取视频
时间: 2025-07-11 20:41:12 浏览: 2
<think>好的,我现在要解决的问题是:如何利用FFmpeg进行RTSP推流,再通过VLC拉流,同时调用YOLOv5s的ONNX模型实现人体检测并截取指定片段。这个问题看起来涉及多个步骤和技术,我需要一步步拆解。
首先,我需要明确每个组件的作用。FFmpeg用于推流,RTSP是流媒体协议,VLC作为播放器拉流,YOLOv5s模型负责检测人体,然后截取视频片段。用户可能希望实时处理视频流,检测到人体后保存相关片段。
第一步,RTSP推流。我记得FFmpeg可以将本地视频或摄像头输入推送到RTSP服务器。比如使用SRS或者Mediamtx这样的服务器。需要确认推流的命令是否正确,比如指定RTSP的URL,编码参数等。可能需要类似这样的命令:ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://server/live.stream。但具体参数可能需要调整,比如编码格式,是否转码等。
接下来,VLC拉流。这部分应该相对简单,用VLC打开网络流,输入RTSP地址即可。但需要确保服务器配置正确,端口开放,防火墙设置没问题。
然后是调用YOLOv5s的ONNX模型进行人体检测。这里的问题是如何在拉流的同时实时处理视频帧。可能需要用Python脚本,使用OpenCV读取视频流,然后对每一帧应用YOLOv5s模型。ONNX模型需要被加载,并进行推理。需要注意的是,YOLO模型通常输出的是检测框和类别,需要过滤出人的类别(比如COCO数据集的类别0是person)。
检测到人体后,需要截取视频片段。这里可能需要记录检测到的时间点,然后从原始流中截取对应时间段的内容。但实时处理中,如何保存指定片段?可能需要持续录制,当检测到人体时,标记开始时间,持续一段时间后结束,或者当人体离开后停止。或者,使用缓冲区保存最近的视频帧,当检测到人体时,保存之前几秒和之后几秒的数据。
整个流程可能需要整合多个步骤:FFmpeg推流到RTSP服务器,VLC或其他工具拉流,但实际处理可能不需要VLC,而是直接用OpenCV读取RTSP流,处理帧,然后显示或保存。用户提到用VLC拉流,可能只是验证流是否正常,实际处理可能在Python脚本中完成。
可能需要分几个部分实现:
1. RTSP服务器的搭建,比如使用Mediamtx(原rtsp-simple-server),配置好RTSP端口。
2. 使用FFmpeg将视频源推流到服务器。
3. 编写Python脚本,使用OpenCV读取RTSP流,逐帧处理,应用YOLOv5s ONNX模型。
4. 当检测到人体时,触发视频片段的保存,可能需要用到FFmpeg或其他库来截取片段。
关于模型推理部分,YOLOv5的ONNX模型需要正确的预处理和后处理。比如,将帧转换为模型输入的尺寸,归一化,运行推理,解析输出,应用NMS,然后筛选出person类别。这需要了解YOLOv5的输入输出结构,以及如何使用ONNX Runtime进行推理。
关于视频截取,可能在检测到人体时开始录制,直到一段时间没有检测到人体后停止。这需要维护一个状态变量,记录是否正在录制,并管理视频写入的过程。可以使用OpenCV的VideoWriter,但需要注意编码格式和帧率匹配。
可能遇到的挑战包括:实时处理的延迟问题,模型推理的速度是否足够快,视频流和处理的同步,以及如何高效截取和保存视频片段。此外,RTSP流的稳定性也可能影响整个流程,需要处理网络中断或流错误的情况。
另外,用户可能希望将检测到的人体片段自动保存,可能需要记录时间戳,或者直接保存检测到人体时的视频帧周围的数据。或者,使用某种缓冲机制,比如在内存中保留最近N秒的视频数据,当检测到人体时,将缓冲区的数据写入文件,并继续记录直到人体消失。
总结步骤可能如下:
1. 设置RTSP服务器(如Mediamtx)。
2. 使用FFmpeg推送视频流到RTSP服务器。
3. Python脚本使用OpenCV读取RTSP流。
4. 对每一帧使用YOLOv5s ONNX模型检测人体。
5. 当检测到人体时,触发录制,保存视频片段。
6. 处理完成后,停止录制并保存文件。
需要具体实现每个步骤的代码,并测试每个环节是否正常工作。例如,确保FFmpeg推流成功,Python脚本能正确拉流并处理帧,模型推理正确,视频截取逻辑正确。</think>以下是分步解决方案:
### 一、RTSP推流与拉流配置
1. **搭建RTSP服务器**
推荐使用轻量级RTSP服务器如[Mediamtx](https://github.com/bluenviron/mediamtx)(原rtsp-simple-server):
```bash
# 下载并解压Mediamtx
wget https://github.com/bluenviron/mediamtx/releases/download/v1.6.0/mediamtx_v1.6.0_linux_amd64.tar.gz
tar -xvf mediamtx_v1.6.0_linux_amd64.tar.gz
./mediamtx
```
2. **使用FFmpeg推流**
将本地视频或摄像头输入推送到RTSP服务器:
```bash
ffmpeg -re -i input.mp4 -c:v libx264 -preset ultrafast -f rtsp rtsp://localhost:8554/live
```
- `-re`:按输入帧率推送
- `-c:v libx264`:使用H.264编码
- `-preset ultrafast`:低延迟编码[^1]
3. **VLC验证拉流**
打开VLC播放器,选择 `媒体 → 打开网络串流`,输入地址 `rtsp://localhost:8554/live`。
---
### 二、人体检测与视频截取实现
1. **Python环境准备**
安装依赖库:
```bash
pip install opencv-python onnxruntime numpy
```
2. **加载YOLOv5s ONNX模型**
```python
import cv2
import onnxruntime as ort
# 加载模型
session = ort.InferenceSession("yolov5s.onnx")
input_name = session.get_inputs()[0].name
```
3. **RTSP拉流与帧处理**
```python
cap = cv2.VideoCapture("rtsp://localhost:8554/live", cv2.CAP_FFMPEG)
while cap.isOpened():
ret, frame = cap.read()
if not ret: break
# 预处理(尺寸调整/归一化)
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (640,640), swapRB=True)
outputs = session.run(None, {input_name: blob})
# 解析检测结果
detections = postprocess(outputs) # 需实现后处理函数
for box, conf, cls in detections:
if cls == 0: # COCO类别0为人
x1,y1,x2,y2 = box
cv2.rectangle(frame, (x1,y1), (x2,y2), (0,255,0), 2)
start_recording() # 触发录制
```
4. **视频截取逻辑**
使用环形缓冲区保存最近N帧:
```python
from collections import deque
buffer = deque(maxlen=300) # 假设保留10秒(30fps)
def start_recording():
global is_recording
if not is_recording:
is_recording = True
writer = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 30, (width,height))
# 写入缓冲区数据和新帧
for buf_frame in buffer:
writer.write(buf_frame)
buffer.clear()
while cap.isOpened():
ret, frame = cap.read()
buffer.append(frame)
# ...检测逻辑...
if is_recording:
writer.write(frame)
```
---
### 三、优化建议
1. **模型加速**
- 使用TensorRT优化ONNX模型
- 设置ONNX Runtime执行提供者为`CUDAExecutionProvider`
2. **多线程处理**
```python
from threading import Thread
class VideoBuffer:
def __init__(self):
self.buffer = []
self.lock = threading.Lock()
def add_frame(self, frame):
with self.lock:
if len(self.buffer) > 300:
self.buffer.pop(0)
self.buffer.append(frame)
```
---
阅读全文
相关推荐















