FFmpeg实现RTSP推拉流
RTSPReal Time Streaming Protocol推流与拉流的实现核心在于建立符合RTSP/RTP/RTCP协议栈的客户端与服务器。以下是基于不同场景和工具的实现方法。一、 使用现成服务器与工具快速验证这是最快捷的方式适用于功能验证和简单应用。1. 推流实现推流指将本地视频源文件、摄像头、屏幕发布到RTSP服务器。工具/组件推流命令/方法示例说明FFmpegffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://server_ip:port/live/stream将本地文件以原始编码-c copy推流到RTSP服务器。-re表示按输入文件速率读取。FFmpeg (摄像头)ffmpeg -f dshow -i videoUSB Camera -vcodec libx264 -f rtsp rtsp://server_ip:port/live/stream(Windows)ffmpeg -f v4l2 -i /dev/video0 -vcodec libx264 -f rtsp rtsp://server_ip:port/live/stream(Linux)捕获USB摄像头视频编码为H.264后推流。GStreamergst-launch-1.0 v4l2src ! videoconvert ! x264enc ! rtspclientsink locationrtsp://server_ip:port/live/stream使用GStreamer管道从V4L2设备采集、编码并推流。OpenCV VideoWriterpythonout cv2.VideoWriter(appsrc ! videoconvert ! x264enc ! rtspclientsink locationrtsp://...,cv2.CAP_GSTREAMER, 0, fps, (width, height))#### 2. 拉流实现 拉流指从RTSP服务器获取并播放或处理视频流。 | 工具/组件 | 拉流命令/方法示例 | 说明 | | :--- | :--- | :--- | | **FFplay (FFmpeg)** | ffplay rtsp://server_ip:port/live/stream | 最简单的拉流播放工具。 | | **VLC Media Player** | 媒体 - 打开网络串流 - 输入RTSP URL | 图形化工具支持拉流播放。 | | **OpenCV VideoCapture** | pythonbrcap cv2.VideoCapture(rtsp://server_ip:port/live/stream)brwhile cap.isOpened():br ret, frame cap.read()br # 处理framebr | 在Python中拉流并获取每一帧图像进行处理。 | | **GStreamer** | gst-launch-1.0 rtspsrc locationrtsp://server_ip:port/live/stream ! decodebin ! autovideosink | 使用GStreamer管道拉流并解码显示。 | #### 3. 轻量级RTSP服务器 进行推拉流测试需要一个RTSP服务器。**mediamtx**原rtsp-simple-server是一个极简的选择。 1. **下载并启动服务器** bash # 从 https://github.com/bluenviron/mediamtx/releases 下载对应平台版本 ./mediamtx 服务器默认在 :8554 端口监听。 2. **推流到服务器** bash ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://localhost:8554/mystream 3. **从服务器拉流** bash ffplay rtsp://localhost:8554/mystream ### 二、 编程实现C/C示例 对于嵌入式或需要深度集成的场景需要编程实现RTSP客户端/服务器。 #### 1. RTSP推流客户端实现要点 一个基本的RTSP推流客户端需要完成以下步骤 c // 伪代码流程1. 建立TCP连接至RTSP服务器默认端口554。 2. 发送DESCRIBE请求获取媒体描述SDP。 3. 发送SETUP请求为音视频流建立传输通道RTP/RTCP端口。 4. 发送PLAY请求开始播放。 // 对于推流ANNOUNCE, RECORD服务器需支持相关方法。 5. 在SETUP建立的UDP或TCP套接字上按照RTP协议封装并发送音视频数据。 将H.264 NALU封装为RTP包。一个NALU可能被分片FU-A或打包成单个RTP包。 RTP头需设置序列号、时间戳、负载类型等。 6. 周期性发送RTCP接收报告RR或发送报告SR。关键代码片段RTP封装H.264 NALU// 假设有一个H.264 NALU (nal_data, nal_len)需要封装为RTP包 void send_rtp_h264_packet(int rtp_sock, struct sockaddr_in *dest_addr, const uint8_t *nal_data, int nal_len, uint16_t *seq_num, uint32_t *timestamp) { uint8_t rtp_packet[1500]; // MTU大小 int rtp_header_len 12; // 1. 构建RTP头 (RFC 3550) rtp_packet[0] 0x80; // V2, P0, X0, CC0 rtp_packet[1] 96; // PT96 (动态负载类型H.264常用) rtp_packet[2] (*seq_num 8) 0xFF; rtp_packet[3] *seq_num 0xFF; (*seq_num); // 设置时间戳 (根据时钟频率递增H.264视频通常为90000 Hz) rtp_packet[4] (*timestamp 24) 0xFF; rtp_packet[5] (*timestamp 16) 0xFF; rtp_packet[6] (*timestamp 8) 0xFF; rtp_packet[7] *timestamp 0xFF; // SSRC等字段省略... // 2. 封装H.264负载 (根据RFC 6184) if (nal_len 1400) { // 单包模式 (Single NALU) memcpy(rtp_packet rtp_header_len, nal_data, nal_len); send_packet(rtp_sock, dest_addr, rtp_packet, rtp_header_len nal_len); } else { // 分片模式 (FU-A) // FU indicator rtp_packet[rtp_header_len] (nal_data[0] 0xE0) | 28; // FU-A type28 // FU header (S|E|R) NALU type int offset 1; // 跳过NALU头 int remaining nal_len - offset; int max_payload_size 1400; int start 1; while (remaining 0) { int payload_size (remaining max_payload_size) ? max_payload_size : remaining; rtp_packet[rtp_header_len 1] (start ? 0x80 : 0x00) | // Start bit ((remaining payload_size 0) ? 0x40 : 0x00) | // End bit (nal_data[0] 0x1F); // NALU type memcpy(rtp_packet rtp_header_len 2, nal_data offset, payload_size); send_packet(rtp_sock, dest_addr, rtp_packet, rtp_header_len 2 payload_size); offset payload_size; remaining - payload_size; start 0; } } }2. RTSP拉流客户端实现要点拉流客户端与推流客户端步骤1-4类似区别在于第5步是接收并解析RTP包重组H.264 NALU。// 伪代码流程 (接收端) 14. 同推流客户端建立RTSP会话。 5. 在SETUP建立的UDP或TCP套接字上循环接收RTP包。 6. 解析RTP头获取序列号、时间戳、负载类型。 7. 根据RFC 6184解析H.264负载 单包模式直接提取NALU。 - FU-A分片模式缓存分片根据起始和结束标记重组完整的NALU。 8. 将重组后的NALU送入解码器如FFmpeg、硬件解码器或进行其他处理。关键代码片段解析RTP并重组H.264typedef struct { uint8_t buffer[MAX_NALU_SIZE]; int size; uint16_t seq; // 期望的下一个序列号 uint32_t timestamp; int fu_a_started; } NaluAssembler; void process_rtp_packet(NaluAssembler *assembler, const uint8_t *rtp_packet, int packet_len) { // 解析RTP头 int payload_type rtp_packet[1] 0x7F; uint16_t seq_num (rtp_packet[2] 8) | rtp_packet[3]; uint32_t timestamp (rtp_packet[4] 24) | (rtp_packet[5] 16) | (rtp_packet[6] 8) | rtp_packet[7]; const uint8_t *payload rtp_packet 12; // 假设无CSRC int payload_size packet_len - 12; if (payload_type ! 96) return; // 非H.264负载 uint8_t nal_unit_type payload[0] 0x1F; if (nal_unit_type 1 nal_unit_type 23) { // 单包NALU deliver_nalu(payload, payload_size, timestamp); } else if (nal_unit_type 28) { // FU-A uint8_t fu_header payload[1]; int start_bit (fu_header 7) 1; int end_bit (fu_header 6) 1; uint8_t reconstructed_nal_type fu_header 0x1F; if (start_bit) { // 开始分片 assembler-size 0; assembler-timestamp timestamp; assembler-fu_a_started 1; // 重组NALU头 assembler-buffer[0] (payload[0] 0xE0) | reconstructed_nal_type; assembler-size 1; } if (assembler-fu_a_started assembler-timestamp timestamp) { // 追加分片数据 memcpy(assembler-buffer assembler-size, payload 2, payload_size2); assembler-size (payload_size - 2); } if (end_bit assembler-fu_a_started assembler-timestamp timestamp) { // 分片结束交付完整NALU deliver_nalu(assembler-buffer, assembler-size, timestamp); assembler-fu_a_started 0; } } // 处理其他类型如STAP-A, MTAP16等 }三、 特定平台实现Android屏幕推流在Android上实现屏幕推流到RTSP服务器涉及屏幕捕获、编码和网络传输。// 核心步骤摘要 // 1. 获取MediaProjection权限创建VirtualDisplay捕获屏幕 MediaProjectionManager projectionManager (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); Intent captureIntent projectionManager.createScreenCaptureIntent(); startActivityForResult(captureIntent, REQUEST_CODE); // 在onActivityResult中 MediaProjection mediaProjection projectionManager.getMediaProjection(resultCode, data); // 配置视频尺寸、DPI等 VirtualDisplay virtualDisplay mediaProjection.createVirtualDisplay(ScreenCapture, width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, surface, null, null); // 2. 配置MediaCodec进行硬件编码H.264 MediaFormat format MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height); format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate); format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval); format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); MediaCodec encoder MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC); encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); Surface inputSurface encoder.createInputSurface(); encoder.start(); // 将VirtualDisplay的surface设置为编码器的inputSurface // virtualDisplay mediaProjection.createVirtualDisplay(..., inputSurface, ...); // 3. 从MediaCodec输出缓冲区获取编码后的H.264数据 MediaCodec.BufferInfo bufferInfo new MediaCodec.BufferInfo(); int outputBufferId encoder.dequeueOutputBuffer(bufferInfo, timeoutUs); if (outputBufferId 0) { ByteBuffer outputBuffer encoder.getOutputBuffer(outputBufferId); byte[] encodedData new byte[bufferInfo.size]; outputBuffer.get(encodedData); // 4. 将encodedDataH.264 NALU通过RTP协议发送至RTSP服务器 //需要实现RTSP客户端协议栈及RTP打包逻辑如第二部分所述 sendRtpPacket(encodedData, bufferInfo.presentationTimeUs); encoder.releaseOutputBuffer(outputBufferId, false); }四、 推拉流与AI处理结合常见场景是拉流-AI推理-推流。import cv2 import subprocess import threading # 1. RTSP拉流 rtsp_pull_url rtsp://server_ip:port/input_stream cap cv2.VideoCapture(rtsp_pull_url) # 2. 准备RTSP推流管道 (使用FFmpeg) rtsp_push_url rtsp://server_ip:port/output_stream 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, rtsp, rtsp_push_url] p subprocess.Popen(command, stdinsubprocess.PIPE) while cap.isOpened(): ret, frame cap.read() if not ret: break # 3. AI推理处理 (例如YOLOv8) # results model(frame) # processed_frame plot_boxes(frame, results) processed_frame frame # 此处省略推理步骤 # 4.将处理后的帧推流 p.stdin.write(processed_frame.tobytes()) cap.release() p.stdin.close() p.wait()实现关键点总结协议理解必须理解RTSP信令控制、RTP数据传输、RTCP传输控制协议交互过程。数据封装视频编码数据如H.264 NALU需要按照RFC 6184规范封装成RTP包。注意NALU分片FU-A与组合。格式兼容确保推流端输出的H.264码流格式AVCC或Annex-B与接收端或服务器期望的格式匹配。例如某些解码器可能只支持Annex-B格式。网络适应处理网络抖动、丢包。使用RTCP进行QoS反馈必要时实现丢包重传或前向纠错。性能优化对于高帧率、高分辨率视频采用硬件编解码、多线程处理、零拷贝等技术降低延迟和CPU占用。参考来源h264 NAL解析代码实现rtsp推流拉流的方法(自己总结)Windows、linux一台电脑rtsp推流另一台拉流显示RTMP推流组件EasyRTMP实现内网摄像头RTSP拉流转码RTMP推流到RTMP服务器之Android版屏幕推流方法及其注意点RTMP推流组件EasyRTMP实现内网摄像头RTSP拉流转码RTMP推流到RTMP服务器之Android版屏幕推流方法及其注意点rtsp拉流yolov8推理rtsp推流

相关新闻

python项目管理器uv的安装和基本命令使用合集 - python的管理与使用

python项目管理器uv的安装和基本命令使用合集 - python的管理与使用

python项目管理器uv的安装和基本命令使用合集 - python的管理与使用1. 首先安装uv2.识别uv命令3.切换到另一版本4.总结1.python项目管理器uv的安装和基本命令使用1. 首先安装uv 终端中执行 powershell -ExecutionPolicy ByPass -c “irm https://astral.sh/uv/install.ps1 | i…

2026/10/4 11:38:30 阅读更多 →
智能优化算法改进策略:从通用工具到工程难题的精准求解

智能优化算法改进策略:从通用工具到工程难题的精准求解

1. 项目概述:从“能用”到“好用”的智能优化算法进阶之路 在工业设计、工程优化和复杂系统求解的领域里,我们常常会遇到一些“硬骨头”问题:比如如何设计一个散热效率最高的异形散热片结构,或者如何为一个形状极其复杂的铸件找到…

2026/10/3 12:22:51 阅读更多 →
CNN-LSTM模型在煤矿瓦斯浓度预测中的实战应用

CNN-LSTM模型在煤矿瓦斯浓度预测中的实战应用

1. 项目概述:当深度学习遇上煤矿安全 在煤矿、隧道等地下工程领域,瓦斯浓度监测是保障安全生产的生命线。传统的监测方式依赖于固定传感器,数据是孤立的点,预警往往滞后。这几年,我一直在琢磨,能不能用更“…

2026/9/29 23:45:43 阅读更多 →

最新新闻

Docker 一键启动服务合集:Redis、MySQL、Kafka、MinIO、Prometheus 等(网盘转存防失效)

Docker 一键启动服务合集:Redis、MySQL、Kafka、MinIO、Prometheus 等(网盘转存防失效)

0. 网盘链接速览(请先转存)⚠️ 重要提示:网盘链接可能随时失效,请先点击下方链接转存到自己网盘,再下载,防止链接失效后无法获取。服务网盘链接提取码redis-dockerhttps://pan.baidu.com/s/1nP2CNyaxdRRKB…

2026/10/12 3:54:21 阅读更多 →
Vim编辑器从入门到精通:模式、快捷键、配置、插件

Vim编辑器从入门到精通:模式、快捷键、配置、插件

SSH 到一台服务器上改配置,手头没有 VS Code,能用的编辑器基本就 Nano 和 Vim。Nano 上手快,但改大型项目源码时效率差 Vim 一大截。这一篇把 Vim 的模式、常用快捷键、基础配置和插件入门讲清楚,目标是看完就能独立改文件&#x…

2026/10/12 3:54:21 阅读更多 →
【C++ 基于微服务的即时通讯系统】基建三件套:gflags + gtest + spdlog 源码编译安装与实战入门

【C++ 基于微服务的即时通讯系统】基建三件套:gflags + gtest + spdlog 源码编译安装与实战入门

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C知识分享》 《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 前言: 做 C 高性能后端开发这么多年…

2026/10/12 3:54:21 阅读更多 →
C语言预处理机制详解:宏定义、条件编译与头文件包含避坑指南

C语言预处理机制详解:宏定义、条件编译与头文件包含避坑指南

1. 预处理在编译流程中的位置很多刚开始学C语言的人,会把注意力全放在语法、指针、结构体这些“看得见”的部分上,但真正到了项目里,第一个让你摔跟头的往往不是语法,而是预处理指令。它不参与具体的逻辑计算,却在编译…

2026/10/12 3:54:21 阅读更多 →
AI工程师不加班成长指南:把工作变训练场的高效学习法

AI工程师不加班成长指南:把工作变训练场的高效学习法

晚上十一点,我刚把一个数据管线的 bug 处理完,打开收藏夹里积压了两个月的论文列表,脑子已经完全转不动了。这种情景在过去两年里反复出现:白天被会议、需求评审、调试代码塞满,晚上想学点新东西却连打开文档的力气都没…

2026/10/12 3:54:21 阅读更多 →
Z-Gly-Gly-Arg-ΒNA;17278-97-6

Z-Gly-Gly-Arg-ΒNA;17278-97-6

基本性质中文名称:苄氧羰基 - 甘氨酰 - 甘氨酰 - 精氨酸 -β- 萘胺,蛋白酶体胰蛋白酶样活性荧光底物CAS 号:17278-97-6单字母序列:Z-G-G-R-βNA三字母序列:Z-Gly-Gly-Arg-βNA分子式:C₂₈H₃₃N₇O₅分子量…

2026/10/12 3:53:20 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →