如何用GStreamer读取Socket传来的H264帧并发布RTSP流?
解决方案:将Socket接收的H264帧发布到RTSP服务器
GStreamer 优化方案(优先推荐)
1. 命令行版本(简化高效)
当前命令的核心问题是做了不必要的解码-重编码流程,直接复用原始H264流推送到RTSP服务器即可,大幅降低CPU开销:
gst-launch-1.0 -e fdsrc fd=0 ! h264parse ! rtph264pay config-interval=1 pt=96 ! rtspclientsink location=rtsp://你的RTSP服务器地址:端口/流名称
- 关键优化点:
- 移除
avdec_h264、videoconvert等解码/转换步骤,直接处理原始H264流 - 使用
rtph264pay将H264帧打包为RTP格式(RTSP标准传输格式) - 通过
rtspclientsink直接推流到自有RTSP服务器
- 移除
2. C#进程内嵌入方案(最佳实践)
如果需要在C#进程内处理(避免外部进程开销),推荐使用GStreamer Sharp绑定,通过appsrc元素直接将Socket接收的帧数据注入GStreamer管道,无需标准输入通信:
步骤:
- 通过NuGet安装
GStreamerSharp包 - 编写核心代码示例:
using Gst; using Gst.App; // 初始化GStreamer Application.Init(); // 创建管道 var pipeline = new Pipeline("h264-rtsp-pipeline"); // 创建元素 var appsrc = ElementFactory.Make("appsrc", "frame-source"); var h264parse = ElementFactory.Make("h264parse", "h264-parser"); var rtph264pay = ElementFactory.Make("rtph264pay", "rtp-payloader"); var rtspSink = ElementFactory.Make("rtspclientsink", "rtsp-sink"); // 配置RTSP服务器地址 rtspSink.SetProperty("location", "rtsp://你的RTSP服务器地址:554/stream-path"); // 配置appsrc的格式(根据实际H264流参数调整,比如分辨率、帧率) var caps = Caps.FromString("video/x-h264, stream-format=byte-stream, width=1920, height=1080, framerate=25/1"); appsrc.SetProperty("caps", caps); appsrc.SetProperty("format", Format.Time); // 链接所有元素 pipeline.AddMany(appsrc, h264parse, rtph264pay, rtspSink); Element.LinkMany(appsrc, h264parse, rtph264pay, rtspSink); // 启动管道 pipeline.SetState(State.Playing); // 模拟Socket接收帧并推送(替换为实际Socket读取逻辑) long frameCount = 0; var frameRate = 25; while (true) { byte[] h264Frame = ReceiveFrameFromSocket(); // 自定义Socket读取方法 if (h264Frame == null || h264Frame.Length == 0) break; // 创建GStreamer缓冲区并写入帧数据 using var buffer = new Buffer(h264Frame.Length); using var map = buffer.Map(MapFlags.Write); System.Buffer.BlockCopy(h264Frame, 0, map.Data, 0, h264Frame.Length); // 设置时间戳(保证RTSP流的时序正确) buffer.Pts = Clock.TimeFromFrames(frameCount, frameRate); buffer.Dts = buffer.Pts; buffer.Duration = Clock.TimeFromFrames(1, frameRate); // 推送缓冲区到appsrc var src = (AppSrc)appsrc; src.PushBuffer(buffer); frameCount++; } // 停止并清理管道 pipeline.SetState(State.Null); Application.Deinit();
- 优势:完全进程内处理,无跨进程通信开销,便于集成到C#项目中,可控性更强。
FFmpeg 备选方案
如果需要用FFmpeg命令行实现,同样可以直接复用原始H264流推流:
ffmpeg -f h264 -i pipe:0 -c:v copy -f rtsp rtsp://你的RTSP服务器地址:端口/流名称
-f h264:指定输入为H264原始流-c:v copy:直接复制视频流,不重新编码-f rtsp:输出RTSP流到目标服务器
内容的提问来源于stack exchange,提问作者Alvan Rahimli
相关产品推荐
相关产品推荐

