go2rtc 的 RTMP / FLV 流接入、推流与转发实战指南【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtcgo2rtc 内置了完整的 RTMPReal-Time Messaging Protocol支持模块既能以客户端身份从 RTMP 服务器拉流也能以服务器身份对外提供 RTMP 输出、接收 RTMP 推流同时还提供基于 HTTP 的 FLV 流输出与接入能力。读完本文你将掌握 go2rtc 中 RTMP 客户端、RTMP 服务器与 FLV 服务器的完整配置方法与实测用法并能理解其底层协议实现握手、Chunk、AMF 命令在源码中的落点。模块能力总览根据 internal/rtmp/README.md该模块围绕 RTMP 协议提供三大能力能力方向格式说明RTMP Client拉流输入rtmp从外部 RTMP 服务器获取流例如 Nginx nginx-rtmp-module 搭建的服务器RTMP Server输出 / 接入rtmp对外提供 RTMP 地址支持播放输出与推流接入FLV Server输出 / 接入flv基于 HTTP 的stream.flv接口输出与接入 FLV 流在 main.go 中rtmp.Init()作为独立模块被注册真正的事件入口位于 internal/rtmp/rtmp.go它完成三件事注册rtmp、rtmps、rtmpx三种 scheme 的拉流处理器streams.HandleFunc注册rtmp、rtmps、rtmpx三种 scheme 的推流消费者处理器streams.HandleConsumerFunc注册api/stream.flvHTTP 接口api.HandleFunc。RTMP 客户端从 RTMP 服务器拉流RTMP 客户端用于从外部 RTMP 服务器读取直播流例如 Nginx 配合 nginx-rtmp-module 模块搭建的推流服务器。客户端配置在go2rtc.yaml的streams段中将流的源地址写成rtmp://即可streams: rtmp_stream: rtmp://192.168.1.123/live/camera1URL 的路径解析规则可从源码确认在 pkg/rtmp/client.go 中URL 路径被拆分为App第一段与Stream第二段且会拼接上原始查询参数if args : strings.Split(u.Path, /); len(args) 2 { c.App args[1] if len(args) 3 { c.Stream args[2] if u.RawQuery ! { c.Stream ? u.RawQuery } } }因此形如rtmp://host/live/camera1?tokenabc的地址中live是 App、camera1?tokenabc是 Stream 名查询参数会完整保留可用于带认证信息的推流地址。客户端实现链路拉流入口streamsHandle直接调用rtmp.DialPlay(url)见 internal/rtmp/rtmp.go。DialPlay的实现位于 pkg/rtmp/client.go先解析 URL 并建立 TCP 连接随后NewClient完成握手与SetPacketSize协商再依次执行writeConnect→writeCreateStream→writePlay三个 AMF 命令对应connect、createStream、play最终返回一个flv.Producer。也就是说RTMP 拉流在 go2rtc 内部会被统一解封装为 FLV 数据流再进入统一的 streams 管理框架从而可以再以任意协议WebRTC、HLS、MJPEG 等转发出去。值得注意的兼容性细节writePlay的响应等待逻辑针对不同厂商做了适配——注释明确写到 Reolink response with ID0, other software respose with ID5pkg/rtmp/conn.go即不同服务器对onStatus响应的事务 ID 不同代码对此做了容错。RTMP 服务器输出与推流接入RTMP 服务器功能自 v1.8.0 起加入。默认情况下该服务器是禁用的需要显式配置监听地址。服务器配置rtmp: listen: :1935 # 默认关闭disabled当listen为空时Init会直接返回、不启动任何监听见 internal/rtmp/rtmp.go配置后则通过net.Listen(tcp, address)监听并为每个连接启动一个 goroutine 处理。输出以 rtmp 格式播放流任何已存在的流来自streams配置、WebRTC 发布或其他来源都可以通过 RTMP 地址播放ffplay rtmp://localhost:1935/camera1这里camera1是 go2rtc 中已注册的流名。服务端收到play命令后tcpHandle会走到CommandPlay分支internal/rtmp/rtmp.go通过streams.Get(rtmpConn.App)按 App 名即流名找到流创建一个flv.NewConsumer()订阅该流然后向客户端回写NetStream.Play.Start状态WriteStart见 pkg/rtmp/server.go最后把 FLV 数据通过 RTMP 连接写出。接入接收 RTMP 推流将任意 RTMP 推流源FFmpeg、OBS 等推到 go2rtcffmpeg -re -i BigBuckBunny.mp4 -c copy -f flv rtmp://localhost:1935/camera1服务端收到publish命令后tcpHandle走到CommandPublish分支internal/rtmp/rtmp.go同样按 App 名找到目标流可以是streams里预先定义的空流如后文tmp:配置回写NetStream.Publish.Start然后将rtmpConn.Producer()作为生产者挂接到该流上并启动。服务端命令处理服务端在握手后调用ReadCommands循环读取消息pkg/rtmp/server.go依次响应connect、releaseStream、FCPublish、createStream、publish/play等 AMF 命令acceptCommandpkg/rtmp/server.go。其中connect会校验并返回NetConnection.Connect.Successpublish/play会记录Intent后交由上层tcpHandle分发——这是理解 RTMP 服务器拉流播放与推流接入两条路径分工的关键。FLV 服务器基于 HTTP 的输出与接入FLV 服务器依托 HTTP 接口实现无需额外配置独立的监听端口复用 Web 服务的默认端口如示例中的 1984是向浏览器等 HTTP 客户端分发 FLV 流的最简单方式。输出HTTP FLV 拉流ffplay http://localhost:1984/stream.flv?srccamera1src参数指定要读取的流名。对应实现outputFLVinternal/rtmp/rtmp.go取src找到流、创建flv.NewConsumer()订阅设置响应头Content-Type: video/x-flv随后把 FLV 数据持续写入 HTTP 响应。请求方式为 GET非 POST。接入HTTP FLV 推流ffmpeg -re -i BigBuckBunny.mp4 -c copy -f flv http://localhost:1984/api/stream.flv?dstcamera1dst参数指定接收流的名称且必须使用 POST 方式。对应实现inputFLVinternal/rtmp/rtmp.go通过flv.Open(r.Body)将 HTTP 请求体解析为 FLV 生产者再挂接到目标流上启动。接口的路由分发逻辑在apiHandle中按请求方法区分POST 走接入input否则走输出outputinternal/rtmp/rtmp.go。FLV 编解码实现FLV 方向的底层实现在 pkg/flv 包中输出方向pkg/flv/muxer.go 负责生成 FLV 头、onMetaData元数据标签以及 H.264AVC sequence header与 AACAudioSpecificConfig的初始化标签GetPayloader将 RTP 包重新封装为 FLV Tag并处理关键帧标记AVC keyframe/composition time。接入方向pkg/flv/producer.go 的probe会对输入流做探测兼容不同厂商的非标准行为——注释中明确列出 Reolink音视频 flag 为空、AAC 缺 stereo 键、OpenIPC 旧固件无 MetaData、视频包 3 秒后才到与 Dahua不发videocodecid等特殊情形这正是该模块实测兼容性广泛的原因。实测兼容性与完整配置已测客户端go2rtc 作为 RTMP 客户端拉流来源目标备注go2rtcReolink RLC-520A fw. v3.1.0.801OK对应的go2rtc.yaml注意 Reolink 地址可携带?channel/stream/user/password查询参数streams: rtmp-reolink1: rtmp://192.168.10.92/bcs/channel0_main.bcs?channel0stream0useradminpasswordpassword rtmp-reolink2: rtmp://192.168.10.92/bcs/channel0_sub.bcs?channel0stream1useradminpasswordpassword rtmp-reolink3: rtmp://192.168.10.92/bcs/channel0_ext.bcs?channel0stream1useradminpasswordpassword已测服务器向 go2rtc 推流接入来源目标备注OBS 31.0.2go2rtcOKOpenIPC 2.5.03.02-litego2rtcOKFFmpeg 6.1go2rtcOKGoPro Black 12go2rtcOK1080p5000kbps接入测试的基础配置先定义一个空流tmp作为推流目标并开启 RTMP 监听rtmp: listen: :1935 streams: tmp:OBS 推流设置Settings StreamServiceCustomServerrtmp://192.168.10.101/tmpStream Keyempty留空Use authdisabled关闭OpenIPC 推流设置WebUI Majestic Settings OutgoingEnable 开启Addressrtmp://192.168.10.101/tmpSave 保存Restart 重启设备FFmpeg 推流命令ffmpeg -re -i bbb.mp4 -c copy -f flv rtmp://192.168.10.101/tmpGoPro在 GoPro Quik 应用中通过 Camera Translation Other 路径将画面推送到 go2rtc。从 pkg/rtmp/conn.go 的消息类型常量可以看到实现覆盖了完整的 RTMP 消息体系TypeAudio(8)、TypeVideo(9)、TypeData(18)、TypeCommand(20) 以及带宽/包大小协商TypeSetPacketSize、TypeServerBandwidth、TypeClientBandwidth。握手方面客户端采用简化握手clienHandshakepkg/rtmp/client.go服务端则实现了完整的 C0/C1/S0/S1/S2/C2 四次交换并设置握手超时serverHandshakepkg/rtmp/server.go为上述多种推流端设备的兼容性提供了底层保障。小结go2rtc 的 RTMP 模块在协议层面同时覆盖拉流客户端、RTMP 服务器、HTTP FLV 服务器三种角色streams配置中的rtmp://地址用于拉流rtmp.listen配置开启 RTMP 输出与接入stream.flv/api/stream.flvHTTP 接口用于 FLV 输出与接入。所有路径最终都汇入统一的 streams 流管理框架因此拉进来的 RTMP/FLV 流可以无缝转发为 WebRTC、HLS、MJPEG 等其他输出格式是搭建多协议视频汇聚网关时非常实用的组成部分。【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考