答案:使用C++结合librtmp实现RTMP推流需先建立TCP连接并完成握手,再发送connect命令连接应用,创建流后持续发送符合格式的音视频数据包,最后关闭连接;通过RTMP_SendPacket发送H.264/AAC数据时需正确设置时间戳与数据类型,实际应用中还需处理编码、同步与网络稳定性问题。

实现一个简单的RTMP推流客户端,核心是理解RTMP协议的基本流程,并借助像 librtmp 这样的开源库来简化网络通信和协议封装。C++结合librtmp可以快速搭建出能连接RTMP服务器、发送音视频数据的推流程序。
1. 理解RTMP推流基本流程
RTMP(Real-Time Messaging Protocol)是Adobe开发的用于音视频实时传输的协议,常用于直播推流。推流客户端的基本步骤包括:
- 建立TCP连接到RTMP服务器(如Nginx-rtmp、SRS等)
- 完成RTMP握手过程(发送/接收C0/C1/C2/C3等握手包)
- 发送connect命令连接应用(如live)
- 创建流并发布(publish)
- 持续发送音频、视频数据包(AVC/H.264 + AAC)
- 关闭连接
实际推流时,音视频数据通常来自编码器(如FFmpeg编码后的H.264/AAC),但本文重点在“发送”环节。
2. 使用librtmp库进行开发
librtmp 是 libavformat 中提取出的一个轻量级RTMP实现,广泛用于各种流媒体项目。它支持连接、推流、拉流等操作,接口简洁。
立即学习“C++免费学习笔记(深入)”;
步骤一:安装 librtmp 开发库
在Ubuntu上可使用:
sudo apt-get install librtmp-dev
步骤二:编写C++代码连接并推流
下面是一个简化版的推流客户端示例,模拟发送一段H.264关键帧(不涉及真实编码):
#include#include #include bool PushH264ToRTMP(const char* rtmpUrl) { RTMP* rtmp = RTMP_Alloc(); RTMP_Init(rtmp); if (!RTMP_SetupURL(rtmp, const_cast (rtmpUrl))) { std::cerr << "Failed to setup URL\n"; RTMP_Free(rtmp); return false; } // 设置为推流模式 RTMP_EnableWrite(rtmp); if (!RTMP_Connect(rtmp, nullptr)) { std::cerr << "Failed to connect to server\n"; RTMP_Free(rtmp); return false; } if (!RTMP_ConnectStream(rtmp, 0)) { std::cerr << "Failed to connect stream\n"; RTMP_Close(rtmp); RTMP_Free(rtmp); return false; } std::cout << "Connected to RTMP server successfully.\n"; // 模拟发送一个简单的H.264 SPS/PPS + IDR帧(这里仅示意结构) // 实际应由编码器输出,此处用静态数据占位 uint8_t fake_h264[] = { 0x17, 0x01, 0x00, 0x00, 0x00, // AVCPacketType = 1 (SPS/PPS) 0x00, 0x00, 0x00, 0x01, // start code 0x67, 0x42, 0x00, 0x1E, // SPS example 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x0F, 0x13, // PPS example 0x00, 0x00, 0x00, 0x01, 0x65, // I-frame }; RTMPPacket packet = {0}; RTMPPacket_Reset(&packet); RTMPPacket_Alloc(&packet, sizeof(fake_h264)); memcpy(packet.m_body, fake_h264, sizeof(fake_h264)); packet.m_packetType = RTMP_PACKET_TYPE_VIDEO; packet.m_nBodySize = sizeof(fake_h264); packet.m_nChannel = 0x04; packet.m_nTimeStamp = 0; packet.m_hasAbsTimestamp = 0; packet.m_headerType = RTMP_PACKET_SIZE_LARGE; // 发送数据包 if (RTMP_SendPacket(rtmp, &packet, true)) { std::cout << "Video data sent.\n"; } else { std::cerr << "Failed to send video packet.\n"; } RTMPPacket_Free(&packet); RTMP_Close(rtmp); RTMP_Free(rtmp); return true; } int main() { const char* rtmpUrl = "rtmp://localhost/live/test"; PushH264ToRTMP(rtmpUrl); return 0; }
编译方式:
g++ -o rtmp_push rtmp_push.cpp -lrtmp
3. 关键注意事项
虽然上面代码能连接并发送数据,但要真正稳定推流还需注意:
- 时间戳同步:每个音视频包需设置正确的时间戳(m_nTimeStamp),单位为毫秒,通常从0开始递增
- 数据格式规范:H.264必须以Annex B格式发送,且包含完整的SPS/PPS信息
- 音频支持:可通过设置 packet.m_packetType = RTMP_PACKET_TYPE_AUDIO 发送AAC数据
- 错误处理:网络中断后应尝试重连,生产环境需加入心跳与重传机制
- 线程安全:若多线程推流,需对RTMP结构加锁
4. 扩展方向
简单推流只是起点,后续可:
- 接入FFmpeg进行实时编码(libx264 / aac)
- 捕获摄像头或桌面画面作为输入源
- 支持FLV标签封装,按时间分片发送
- 添加元数据(onMetaData)描述视频分辨率、码率等
基本上就这些。用C++写RTMP推流客户端,librtmp是成熟选择,关键是掌握协议流程和数据封装格式。不复杂但容易忽略细节,比如时间戳和NALU头处理。











