GB28181 media 支持RTMP/HTTP-FLV/RTSP/WebRTC/HLS

GbMediaServer 是一个高性能的流媒体服务器,支持多种流媒体协议和格式。它主要用于接收GB28181设备的视频流,并提供多种输出格式(WebRTC、FLV、HLS等)供客户端播放。该系统实现了低延迟的实时流媒体传输、多协议转换和多路分发功能。
┌─────────────────────────────────────────────────────────────┐
│ GbMediaServer 系统架构 │
└─────────────────────────────────────────────────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ GB28181设备 │ │ WebRTC客户端 │
│ │ │ │
│ RTP/PS流 │ │ 推流/拉流 │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ │
▼ ▼
┌──────────────────────────────────────────────┐
│ GbMediaService (核心服务) │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ RtcService │ │ WebService │ │
│ │ (WebRTC管理) │ │ (HTTP API) │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Session │ │ Stream │ │
│ │ (会话管理) │ │ (流管理) │ │
│ └──────────────┘ └──────────────┘ │
└──────────────────────────────────────────────┘
│ │
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Producer │ │ Consumer │
│ (生产者) │ │ (消费者) │
│ │ │ │
│ - GB28181 │ │ - WebRTC │
│ - WebRTC │ │ - HTTP-FLV │
│ - RTSP │ │ - HLS │
│ - RTMP │ │ - RTSP │
└──────────────────┘ └──────────────────┘
GBServer/
├── GbMediaServer/ # 主程序模块
│ ├── main.cpp # 程序入口
│ ├── server/ # 服务器模块
│ │ ├── gb_media_service.h/cpp # 核心服务类
│ │ ├── rtc_service.h/cpp # RTC服务
│ │ ├── web_service.h/cpp # Web服务
│ │ ├── session.h/cpp # 会话管理
│ │ └── stream.h/cpp # 流管理
│ ├── producer/ # 生产者模块
│ │ ├── producer.h/cpp # 生产者基类
│ │ ├── gb28181_producer.h/cpp # GB28181生产者
│ │ ├── rtc_producer.h/cpp # WebRTC生产者
│ │ ├── crtsp_producer.h/cpp # RTSP生产者
│ │ └── crtmp_producer.h/cpp # RTMP生产者
│ ├── consumer/ # 消费者模块
│ │ ├── consumer.h/cpp # 消费者基类
│ │ ├── rtc_consumer.h/cpp # WebRTC消费者
│ │ ├── flv_consumer.h/cpp # FLV消费者
│ │ ├── crtsp_consumer.h/cpp # RTSP消费者
│ │ └── crtmp_consumer.h/cpp # RTMP消费者
│ ├── share/ # 共享资源模块
│ │ ├── rtc_interface.h/cpp # RTC接口
│ │ └── share_resource.h/cpp # 共享资源
│ └── utils/ # 工具模块
│ ├── yaml_config.h/cpp # YAML配置解析
│ └── string_utils.h/cpp # 字符串工具
└── README.md # 项目文档
git clone https://github.com/chensongpoixs/GBServer.git
cd GBServer
mkdir build
cd build
cmake .. -DWebRTC_ROOT=/path/to/webrtc
cmake --build . --config Release
./GbMediaServer/gbmedia_server.exe gbmedia_server.yaml
创建配置文件 gbmedia_server.yaml:
# HTTP服务器配置
http:
port: 8001
# RTC服务器配置
rtc:
ips:
- 192.168.1.100
udp:
port: 10001
tcp:
port: 20001
cert: fullchain.pem
key: privkey.pem
# RTP端口配置
rtp:
tcp:
min_port: 20000
max_port: 30000
udp:
min_port: 20000
max_port: 30000
curl -X POST http://localhost:8001/api/openRtpServer \
-H "Content-Type: application/json" \
-d '{
"port": 5060,
"tcpmode": 1,
"streamid": "34020000001320000001"
}'
http://localhost:8001/rtc/play?streamurl=live/34020000001320000001http://localhost:8001/live/34020000001320000001.flvhttp://localhost:8001/live/34020000001320000001.m3u8// 客户端代码示例
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:localhost:10001' }]
});
// 添加本地媒体流
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
stream.getTracks().forEach(track => pc.addTrack(track, stream));
return pc.createOffer();
})
.then(offer => {
return pc.setLocalDescription(offer);
})
.then(() => {
// 发送SDP Offer到服务器
return fetch('http://localhost:8001/rtc/push?streamurl=live/stream1', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
streamurl: 'live/stream1',
sdp: pc.localDescription.sdp,
type: 'offer'
})
});
})
.then(response => response.json())
.then(answer => {
return pc.setRemoteDescription(new RTCSessionDescription(answer));
});
<!-- 使用flv.js播放HTTP-FLV流 -->
<script src="https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js"></script>
<video id="videoElement" controls></video>
<script>
if (flvjs.isSupported()) {
const videoElement = document.getElementById('videoElement');
const flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'http://localhost:8001/live/stream1.flv'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
</script>
配置文件采用YAML格式,默认文件名为 gbmedia_server.yaml。
port:HTTP服务器监听端口,默认8001ips:RTC服务器绑定的IP地址列表udp.port:UDP端口,用于STUN、DTLS、RTP/RTCPtcp.port:TCP端口,用于TCP模式的RTC连接cert:DTLS证书文件路径(公钥)key:DTLS证书文件路径(私钥)tcp.min_port / tcp.max_port:TCP RTP端口范围udp.min_port / udp.max_port:UDP RTP端口范围接口: POST /rtc/push
请求参数:
streamurl:流地址,格式为 app/stream(如:live/stream1)sdp:SDP Offer(JSON格式)请求示例:
POST /rtc/push?streamurl=live/stream1
Content-Type: application/json
{
"sdp": "v=0\r\no=- 123456789 123456789 IN IP4 127.0.0.1\r\n...",
"type": "offer"
}
响应示例:
{
"sdp": "v=0\r\no=- 987654321 987654321 IN IP4 127.0.0.1\r\n...",
"type": "answer"
}
接口: POST /rtc/play
请求参数:
streamurl:流地址,格式为 app/streamsdp:SDP Offer(JSON格式)请求和响应格式与推流相同
接口: GET /{app}/{stream}.flv
请求示例:
GET /live/stream1.flv
响应:
video/x-flv接口: GET /{app}/{stream}.m3u8
请求示例:
GET /live/stream1.m3u8
响应:
接口: GET /{app}/{stream}/{fragment}.ts
请求示例:
GET /live/stream1/segment_001.ts
响应:
接口: POST /api/openRtpServer
功能说明:
请求参数(JSON):
{
"port": 5060,
"tcpmode": 1,
"streamid": "34020000001320000001"
}
参数说明:
port:RTP端口(可选,实际使用配置的端口范围)tcpmode:传输模式(0=UDP, 1=TCP)streamid:流ID,用于标识GB28181设备响应示例:
{
"code": 0,
"tcpmode": 1,
"streamid": "34020000001320000001",
"port": 20000
}
接口: POST /api/closeRtpServer
功能说明:
请求参数(JSON):
{
"streamid": "34020000001320000001"
}
响应示例:
{
"code": 0,
"streamid": "34020000001320000001"
}
app/stream)kProducerTypeGB28181:GB28181协议推流kProducerTypeRtc:WebRTC协议推流kProducerTypeRtsp:RTSP协议推流kProducerTypeRtmp:RTMP协议推流kConsumerTypeRtc:WebRTC协议拉流kConsumerTypeFlv:HTTP-FLV协议拉流kConsumerTypeHls:HLS协议拉流kConsumerTypeRtsp:RTSP协议拉流kConsumerTypeRtmp:RTMP协议拉流GB28181设备
|
| RTP/PS流
v
RTP服务器 (TcpServer)
|
| 原始RTP包
v
Gb28181Producer
|
| PS解析 -> H.264/AAC
v
Session
|
| 音视频帧
v
Stream (HLS Muxer)
|
+---> RtcConsumer (WebRTC)
| |
| v
| 客户端 (浏览器)
|
+---> FlvConsumer (HTTP-FLV)
| |
| v
| 客户端 (flv.js)
|
+---> HLS (M3U8/TS)
|
v
客户端 (HLS播放器)
std::shared_ptr、std::unique_ptr)管理对象生命周期std::move)减少拷贝rtc::CopyOnWriteBuffer优化缓冲区管理问题:启动时提示端口被占用
解决方案:
netstat 或 lsof 查看端口占用情况问题:WebRTC连接时DTLS握手失败
解决方案:
问题:GB28181设备推流后无法播放
解决方案:
问题:HTTP-FLV播放延迟较高
解决方案:
问题:HLS播放列表(M3U8)不更新或分片文件缺失
解决方案:
// 1. 继承Producer基类
class MyProducer : public Producer {
public:
MyProducer(const std::shared_ptr<Stream>& stream,
const std::shared_ptr<Session>& session);
virtual ~MyProducer();
// 实现纯虚函数
virtual ShareResourceType ShareResouceType() const override;
virtual void OnVideoFrame(const libmedia_codec::EncodedImage& frame) override;
virtual void OnAudioFrame(const rtc::CopyOnWriteBuffer& frame, int64_t pts) override;
};
// 2. 在Session::CreateProducer中添加新类型
std::shared_ptr<Producer> Session::CreateProducer(...) {
switch(type) {
case ShareResourceType::kProducerTypeMy:
return std::make_shared<MyProducer>(stream_, shared_from_this());
// ...
}
}
// 1. 继承Consumer基类
class MyConsumer : public Consumer {
public:
MyConsumer(libmedia_transfer_protocol::libnetwork::Connection* conn,
const std::shared_ptr<Stream>& stream,
const std::shared_ptr<Session>& session);
virtual ~MyConsumer();
// 实现纯虚函数
virtual ShareResourceType ShareResouceType() const override;
virtual void OnVideoFrame(const libmedia_codec::EncodedImage& frame) override;
virtual void OnAudioFrame(const rtc::CopyOnWriteBuffer& frame, int64_t pts) override;
};
// 2. 在WebService中添加HTTP处理器
void WebService::HandlerMyConsumer(...) {
// 创建MyConsumer并添加到Session
}
// 使用GBMEDIASERVER_LOG宏记录日志
GBMEDIASERVER_LOG(LS_INFO) << "Session created: " << session_name;
GBMEDIASERVER_LOG(LS_WARNING) << "Failed to create producer";
GBMEDIASERVER_LOG(LS_ERROR) << "Critical error occurred";
日志级别:
LS_VERBOSE:详细调试信息LS_INFO:一般信息LS_WARNING:警告信息LS_ERROR:错误信息LS_NONE:不输出日志本项目采用BSD许可证,详见LICENSE文件。
如果遇到问题或有建议,请通过以下方式反馈:
注意:本文档会持续更新,请关注项目最新版本。
最后更新:2025-10-14
版本:1.0.0