VDK — Video Development Kit

纯 Go 流媒体开发工具包 — 协议接入、编解码、转码、录制、集群,一站式搞定。
| 类别 | 支持项 |
|---|
| 传输协议 | RTSP/RTSPS, RTMP/RTMPS, SRT, RIST, HLS, WebRTC (WHIP/WHEP), GB/T 28181, NDI(需外部SDK), DVR-IP |
| 容器格式 | MP4, fMP4, FLV, MPEG-TS, MKV, HLS, AAC, MSE, RAW |
| 视频编码 | H.264, H.265/HEVC, AVS2, VP9, AV1, VVC/H.266, MJPEG |
| 音频编码 | AAC, Opus, MP3, FLAC, AC-3/E-AC-3, G.726, PCM (μ-law/A-law) |
| 图片编码 | WebP, AVIF, HEIF |
| 硬件加速 | NVENC, QSV, AMF, VAAPI, VideoToolbox, V4L2M2M, RKMPP |
| 高级功能 | ABR 多码率阶梯, AI 增强 (超分/降噪/插帧), 字幕 (SRT/ASS/WebVTT/CEA-608/708), 分段录制 (Local/S3/GCS), 集群负载均衡, OpenTelemetry 追踪, Prometheus 指标 |
go get cnb.cool/svn/vdk@latest
go install cnb.cool/svn/vdk/cmd/vdk@latest
vdk probe rtsp://example.com/live/stream
vdk transcode -i input.mp4 -o output.flv
vdk serve -c config.yaml
vdk benchmark
package main
import (
"context"
"time"
"cnb.cool/svn/vdk/format"
"cnb.cool/svn/vdk/stream"
)
func main() {
format.RegisterAll()
s, err := stream.New().
Name("cam-01").
Input("rtsp://admin:pass@192.168.1.100/live").
WithTimeout(10 * time.Second).
LowLatency().
Output("rtmp://cdn.example.com/live/cam-01").
WithTimeout(5 * time.Second).
Done().
Output("srt://backup.example.com:9000").
SRTConfig(120*time.Millisecond, "secret", "live/cam-01").
Done().
Build()
if err != nil {
panic(err)
}
s.OnEvent(func(e stream.EventData) {
switch e.Event {
case stream.EventReconnecting:
println("重连中...")
case stream.EventError:
println("错误:", e.Error.Error())
}
})
if err := s.Run(context.Background()); err != nil {
panic(err)
}
}
s, err := stream.New().
Input("rtsp://camera.local/stream").
Transcode().
Video(stream.VideoH265).
Resolution(1920, 1080).
BitrateM(4).
Preset(stream.PresetFast).
Done().
Audio(stream.AudioAAC).
Done().
Done().
Output("/recordings/output.mp4").Done().
Build()
package main
import (
"cnb.cool/svn/vdk/av/avutil"
"cnb.cool/svn/vdk/format"
)
func main() {
format.RegisterAll()
demuxer, err := avutil.Open("rtsp://example.com/live")
if err != nil {
panic(err)
}
defer demuxer.Close()
muxer, err := avutil.Create("output.mp4")
if err != nil {
panic(err)
}
defer muxer.Close()
streams, _ := demuxer.Streams()
muxer.WriteHeader(streams)
avutil.CopyPackets(muxer, demuxer)
muxer.WriteTrailer()
}
av/event 包提供协议传输层的通用事件机制,14 种事件类型覆盖连接全生命周期。
package main
import (
"fmt"
"cnb.cool/svn/vdk/av/event"
"cnb.cool/svn/vdk/format/srt"
)
func main() {
conn, err := srt.Dial("srt://relay.example.com:9000?streamid=live/test")
if err != nil {
panic(err)
}
defer conn.Close()
conn.EventBus = event.NewBus()
conn.EventBus.On(event.Connected, func(d event.Data) {
fmt.Printf("[%s] 已连接: %s\n", d.Protocol, d.URL)
})
conn.EventBus.On(event.StreamReady, func(d event.Data) {
fmt.Printf("流就绪, codec 数量: %d\n", len(d.Codec))
})
conn.EventBus.On(event.Stats, func(d event.Data) {
if stats, ok := d.Stats.(srt.Stats); ok {
fmt.Printf("RTT: %dms, 丢包率: %.2f%%\n",
stats.RTT.Milliseconds(), stats.PacketLossRate*100)
}
})
conn.EventBus.On(event.Error, func(d event.Data) {
fmt.Printf("错误: %v\n", d.Error)
})
conn.EventBus.OnAll(func(d event.Data) {
fmt.Printf("[%s] %s @ %s\n", d.Protocol, d.Event, d.Time.Format("15:04:05"))
})
}
import "cnb.cool/svn/vdk/av/event"
hooked := event.WrapDemuxer(demuxer,
event.WithProtocol("rtsp"),
event.WithURL("rtsp://example.com/live"),
event.WithDirection("subscribe"),
)
hooked.On(event.StreamReady, func(d event.Data) {
fmt.Println("codec 就绪:", d.Codec)
})
streams, err := hooked.Streams()
| 事件 | 说明 |
|---|
Connecting | 正在连接 |
Connected | 连接成功 |
Handshaking | 正在握手 |
Handshaked | 握手完成 |
StreamReady | 流就绪 (codec 已获取) |
PacketRead | 读取数据包 |
PacketWrite | 写入数据包 |
CodecChange | 编码变更 |
Error | 错误 |
Disconnecting | 正在断开 |
Disconnected | 已断开 |
Reconnecting | 正在重连 |
Reconnected | 重连成功 |
Stats | 统计信息更新 |
vdk/
├── av/ # 核心抽象层
│ ├── av.go # Muxer, Demuxer, CodecData, Packet 接口
│ ├── event/ # 事件系统 (Bus, HookDemuxer, HookMuxer)
│ ├── pktque/ # 包队列与 Filter (WaitKeyFrame, FixTime)
│ ├── pubsub/ # 发布/订阅 Queue (fan-out)
│ ├── avutil/ # Handler 注册, Open/Create 辅助函数
│ ├── avconv/ # 格式转换辅助
│ └── transcode/ # 转码器包装
├── codec/ # 编解码器
│ ├── h264parser/ # H.264 解析 (SplitNALUs, SPS, CodecData)
│ ├── h265parser/ # H.265/HEVC 解析
│ ├── aacparser/ # AAC 解析
│ ├── opusparser/ # Opus 解析
│ ├── vp9parser/ # VP9 解析
│ ├── av1parser/ # AV1 解析
│ ├── vvc/ # VVC/H.266
│ ├── flac/ # FLAC
│ ├── mp3/ # MP3
│ ├── ac3/ # AC-3
│ ├── mjpeg/ # MJPEG
│ ├── webp/, avif/, heif/ # 图片格式
│ └── fake/ # 测试用假编码器
├── format/ # 协议与容器
│ ├── rtmp/ # RTMP (Dial, Server, Conn + EventBus)
│ ├── rtsp/ # RTSP Client + EventBus
│ ├── rtspv2/ # RTSPv2 Client, ProxyConn, Server + EventBus
│ ├── srt/ # SRT (Dial/DialContext/DialConfig, Config, Stats + EventBus)
│ ├── rist/ # RIST (Sender, FEC, Stats, BridgeEvents)
│ ├── webrtc/ # WebRTC Muxer, WebRTCPusher (WHIP/BatchV2), WHEPPuller
│ ├── webrtcv3/ # WebRTC v3 兼容层
│ ├── gb28181/ # GB/T 28181 SIP + PS 解封装
│ ├── ndi/ # NDI 协议框架
│ ├── dvrip/ # DVR-IP Client + EventBus
│ ├── hls/ # HLS Muxer
│ ├── flv/ # FLV Muxer, Demuxer, Prober
│ ├── mp4/ # MP4 Muxer, Demuxer
│ ├── mp4f/ # fMP4 Muxer (fragmented)
│ ├── mp4m/ # MP4 Muxer, Demuxer (扩展)
│ ├── fmp4/ # fMP4 MovieFragmenter
│ ├── mkv/ # MKV Demuxer
│ ├── ts/ # MPEG-TS Muxer, Demuxer
│ ├── nvr/ # NVR 录制 Muxer
│ ├── aac/ # AAC 文件
│ ├── raw/ # RAW 裸流
│ └── mse/ # Media Source Extensions
├── stream/ # 高级 Builder API
│ ├── builder.go # New(), Input(), Output(), Transcode(), Build()
│ ├── stream.go # Stream (Start/Stop/Pause/Resume/Run/Wait)
│ └── enums.go # Protocol, VideoCodec, AudioCodec, Container, Preset...
├── pkg/ # 功能模块
│ ├── manager/ # 流生命周期 Manager (状态机, 健康检查, 资源限制)
│ ├── streammgr/ # 批量会话 Manager (熔断, 健康监控, 集群)
│ ├── abr/ # ABR 自适应码率 (Ladder, Rendition, Transcoder)
│ ├── ai/ # AI 增强 (超分/降噪/插帧/色彩/防抖/去隔行)
│ ├── audio/ # 音频处理
│ ├── subtitle/ # 字幕 (SRT/ASS/WebVTT/CEA-608/708)
│ ├── recording/ # 分段录制 (Local/S3/GCS, 时移回放)
│ ├── cluster/ # 集群 (负载均衡, 服务发现, 流路由)
│ ├── metrics/ # Prometheus 指标收集
│ ├── tracing/ # OpenTelemetry 分布式追踪
│ ├── config/ # 配置管理
│ └── scene/ # 场景模板
├── cgo/ # FFmpeg CGO 绑定
│ ├── codec/ # 编解码
│ ├── filter/ # 滤镜
│ ├── pipeline/ # 处理管线
│ └── sdk/ # SDK 封装
├── cmd/vdk/ # CLI 工具 (probe, transcode, serve, benchmark)
├── example/ # 示例程序
└── utils/ # 通用工具
| 模块 | 路径 | 说明 |
|---|
| 核心接口 | av/ | Muxer, Demuxer, CodecData, Packet |
| 事件系统 | av/event/ | Bus, HookDemuxer, HookMuxer |
| 包队列 | av/pktque/ | Filter, WaitKeyFrame, FixTime |
| 发布订阅 | av/pubsub/ | Queue fan-out |
| 工具函数 | av/avutil/ | Open, Create, CopyPackets |
| H.264 解析 | codec/h264parser/ | SplitNALUs, SPS/PPS, CodecData |
| H.265 解析 | codec/h265parser/ | SplitNALUs, VPS/SPS/PPS |
| RTMP | format/rtmp/ | Dial, Server, Conn |
| RTSP | format/rtsp/ | Client |
| RTSPv2 | format/rtspv2/ | RTSPClient(主路径), ProxyConn/Server(轻量骨架) |
| SRT | format/srt/ | Dial, Config, Stats |
| RIST | format/rist/ | Sender, FEC, Config |
| WebRTC | format/webrtc/ | Muxer, WHIP/WHEP Pusher/Puller |
| GB/T 28181 | format/gb28181/ | SIP 注册/鉴权, PS 解封装 |
| Builder API | stream/ | New, Build, Stream |
| 流管理器 | pkg/manager/ | 生命周期管理 |
| 会话管理 | pkg/streammgr/ | 批量会话, 熔断, 健康监控 |
| ABR | pkg/abr/ | 自适应码率阶梯 |
| AI 增强 | pkg/ai/ | 超分/降噪/插帧 |
| 字幕 | pkg/subtitle/ | SRT/ASS/WebVTT/CEA-608/708 |
| 录制 | pkg/recording/ | 分段录制, 多存储后端 |
| 集群 | pkg/cluster/ | 负载均衡, 服务发现 |
| 指标 | pkg/metrics/ | Prometheus Collector |
| 追踪 | pkg/tracing/ | OpenTelemetry |
| CLI | cmd/vdk/ | probe, transcode, serve, benchmark |
| CGO 绑定 | cgo/ | FFmpeg codec/filter/pipeline |
| 示例 | example/ | 完整示例程序 |
| 版本 | 状态 | 重点 |
|---|
| v2.1 | 当前 | Builder API, 事件系统, SRT/RIST/WebRTC, GB/T 28181, AI 增强, 集群 |
| v2.2 | 规划中 | DASH 输出, SRT Bonding, RIST Main Profile 完善, CMAF |
| v3.0 | 规划中 | 全链路 zero-copy, io_uring 传输, QUIC 协议, WebTransport |
本项目基于 joy4 演进,感谢原作者的开创性工作。
MIT License | 最后更新: 2026-02-11