大牛直播SDK(SmartMediaKit)Windows平台RTMP推流、轻量级RTSP服务SDK集成说明(C++版)
本文详细介绍大牛直播SDK(SmartMediaKit)在Windows平台的C++集成方案,重点阐述RTMP直播推流与轻量级RTSP服务模块的实现方法。SDK提供音视频采集、编码、推流和局域网分发能力,支持MFC/Win32等开发框架,适用于桌面客户端、工控系统等场景。文章从SDK初始化、推流实例创建、音视频采集配置、编码参数设置等核心流程展开说明,并详细讲解RTMP推流至服务器和内置RTSP服
文档概述
本文介绍大牛直播SDK(SmartMediaKit)在 Windows 平台下 C++ 版 RTMP 直播推流模块与轻量级 RTSP 服务模块的集成方法,适用于 MFC、Win32、C++ 桌面客户端、行业终端软件、工控机应用、局域网音视频分发系统等场景。
本文以 Windows C++ 推流 Demo 为基础,围绕 SDK 初始化、推流实例创建、音视频采集源选择、视频编码参数配置、RTMP 推流、内置轻量级 RTSP 服务、事件回调、本地预览、录像与截图等关键流程进行说明。Demo 底层通过 SmartPublisherSDK.dll 提供 C 接口能力,上层 C++ 工程通过 NT_SmartPublisherSDKAPI 函数表完成统一调用。上传的 SDK 头文件中也明确提供了 Init、UnInit、Open、Close、SetEventCallBack 等基础接口。
RTMP 推流模块面向实时音视频应用,可将本地采集或外部输入的音视频数据推送至 RTMP 服务器、CDN 或业务直播平台;轻量级 RTSP 服务模块则以内置服务方式,在无需单独部署流媒体服务器的情况下,对外生成可拉流访问的 RTSP URL。官网资料也将轻量级 RTSP 服务定义为推送端 SDK 内置的 RTSP 服务模块,可用于摄像头、麦克风、屏幕采集和外部编码数据等本地音视频输入场景。
1. 产品定位
大牛直播SDK(SmartMediaKit)Windows 推流 SDK 主要面向低延迟、稳定性和工程可控性要求较高的实时音视频系统。它不是单一的“摄像头推流工具”,而是一个可嵌入业务系统的音视频采集、编码、推流和局域网分发能力模块。
在 Windows 平台下,RTMP 推流模块主要解决“采集端到服务器端”的实时推送问题;轻量级 RTSP 服务模块主要解决“本机生成 RTSP URL,供局域网客户端直接拉流”的问题。两者可以独立使用,也可以在同一个推流实例中组合使用。

轻量级 RTSP 服务适合内网低并发、低延迟实时分发场景,官网资料明确提到其可用于安防监控、智慧教室、无纸化会议、工业生产、医疗健康、智能物联网等局域网音视频应用。
2. 适用场景
| 场景 | 说明 |
|---|---|
| Windows 摄像头 RTMP 推流 | 采集本机摄像头和麦克风,将音视频推送到 RTMP Server、CDN 或业务平台 |
| Windows 屏幕采集推流 | 采集桌面画面,可用于会议同屏、电子教室、远程协助、工控画面回传 |
| 窗口采集推流 | 对指定窗口进行采集,适合特定业务窗口画面输出 |
| 摄像头 + 屏幕合成 | 支持桌面与摄像头叠加、切换、画中画等多层合成场景 |
| 局域网 RTSP 分发 | 不部署独立流媒体服务器,由 SDK 内置 RTSP 服务直接输出 RTSP URL |
| RTMP + RTSP 同时输出 | 同一路采集数据同时推送 RTMP,并通过本地 RTSP 服务给局域网客户端播放 |
| 本地录像与截图 | 推流或预览过程中可按需扩展本地录像、截图能力 |
| 低延迟行业应用 | 适用于安防监控、工业视觉、应急指挥、远程巡检、智慧教室等实时性要求较高的场景 |
3. 开发环境与工程依赖
3.1 推荐环境
| 项目 | 说明 |
|---|---|
| 操作系统 | Windows 7 及以上 |
| 开发语言 | C++ |
| UI 框架 | MFC / Win32,Demo 以 MFC Dialog 为例 |
| SDK 库 | SmartPublisherSDK.dll / SmartPublisherSDK.lib |
| 核心头文件 | nt_smart_publisher_sdk.h、nt_smart_publisher_define.h、nt_common_media_define.h |
| 平台架构 | x86 / x64 需与 SDK 库架构保持一致 |
RTMP 推流官网资料中,Windows 平台能力包括 H.264/H.265 视频编码、AAC/Speex 音频编码、RTMP 推流、纯音频/纯视频/音视频推送、屏幕/摄像头采集、DXGI 采集、推送端预览、静音、状态回调、窗口采集、动态水印、快照、外部音视频数据接入、录像扩展等。发布文档中建议只写当前 Demo 或当前授权包实际开放的能力,避免把跨平台能力混写到 Windows C++ 集成说明中。

3.2 工程文件说明
| 文件 / 模块 | 说明 |
|---|---|
SmartPublisherDemoDlg.cpp/.h |
Demo 主对话框,负责 UI 控制、SDK 初始化、推流、RTSP 服务、录像、预览和事件分发 |
nt_smart_publisher_sdk.h |
SDK C 接口函数表、回调类型、核心 API 声明 |
nt_smart_publisher_define.h |
推流事件、视频源、音频源、图像格式、图层类型等定义 |
nt_common_media_define.h |
媒体类型和 Codec ID 定义,如 H.264、H.265、AAC、Speex 等 |
nt_rtsp_server_config_dlg.cpp/.h |
RTSP 服务配置对话框,负责端口、鉴权、组播、会话数等配置 |
nt_pb_ui_preview_wnd.cpp/.h |
推流端预览窗口,接收 RGB32 图像并绘制 |
nt_smart_publisher_dlg.cpp/.h |
视频合成相关配置,如屏幕层、摄像头层、图片层等 |
4. 推荐工程分层
建议业务工程不要直接把所有 SDK 调用堆在 UI 事件中,而是按以下方式分层:

这种分层方式的好处是:UI 层只处理业务状态和用户交互,SDK 调用集中管理,后续如果要封装成业务 SDK、服务进程或无界面采集程序,也更容易迁移。
5. SDK 初始化与生命周期管理
5.1 获取 SDK API 函数表
Windows C++ Demo 通过 NT_GetSmartPublisherSDKAPI() 获取 NT_SmartPublisherSDKAPI 函数表。获取成功后,所有 SDK 能力均通过该结构体中的函数指针调用。
NT_SmartPublisherSDKAPI publisher_api_;
NT_HANDLE publisher_handle_ = nullptr;
bool InitPublisherSDK()
{
memset(&publisher_api_, 0, sizeof(publisher_api_));
if (NT_ERC_OK != NT_GetSmartPublisherSDKAPI(&publisher_api_))
{
// SDK 加载失败,检查 DLL、运行库和平台架构是否匹配
return false;
}
if (NT_ERC_OK != publisher_api_.Init(0, nullptr))
{
return false;
}
return true;
}
Init() 属于进程级初始化,通常在程序启动时调用一次;UnInit() 应在所有推流实例、RTSP 服务实例、录像和预览资源释放后再调用。上传文档也明确建议区分进程级 Init/UnInit 与实例级 Open/Close。
6. 创建推流实例
6.1 视频源与音频源选择
调用 Open() 创建推流实例时,需要指定视频源和音频源。SDK 头文件中定义的视频源包括:无视频、屏幕采集、摄像头采集、视频合成、外部编码视频数据和窗口采集;音频源包括:无音频、麦克风、扬声器、麦克风与扬声器混音、外部编码音频、外部 PCM 等。
常见组合如下:
| 业务场景 | video_option | audio_option |
|---|---|---|
| 纯屏幕推流 | NT_PB_E_VIDEO_OPTION_SCREEN |
按需选择麦克风、扬声器或无音频 |
| 摄像头推流 | NT_PB_E_VIDEO_OPTION_CAMERA |
NT_PB_E_AUDIO_OPTION_CAPTURE_MIC |
| 屏幕 + 摄像头合成 | NT_PB_E_VIDEO_OPTION_LAYER |
麦克风 / 扬声器 / 混音 |
| 指定窗口采集 | NT_PB_E_VIDEO_OPTION_WINDOW |
按需选择 |
| 外部编码视频输入 | NT_PB_E_VIDEO_OPTION_ENCODED_DATA |
按实际音频源选择 |
示例代码:
bool OpenPublisherHandle()
{
if (publisher_handle_ != nullptr)
return true;
NT_UINT32 video_option = NT_PB_E_VIDEO_OPTION_SCREEN;
NT_UINT32 audio_option = NT_PB_E_AUDIO_OPTION_CAPTURE_MIC;
NT_UINT32 ret = publisher_api_.Open(
&publisher_handle_,
video_option,
audio_option,
0,
nullptr);
if (NT_ERC_OK != ret || publisher_handle_ == nullptr)
{
return false;
}
publisher_api_.SetEventCallBack(
publisher_handle_,
reinterpret_cast<NT_PVOID>(GetSafeHwnd()),
NT_PB_SDKPublisherEventHandle);
return true;
}
Demo 中也是先根据 UI 选择确定 video_option 和 audio_option,再调用 Open() 创建 publisher_handle_,随后注册事件回调。
7. 视频采集配置

7.1 屏幕采集
屏幕采集适合桌面同屏、课件演示、工控画面输出等场景。可根据业务需要设置采集区域、帧率、码率和 DXGI 采集方式。
publisher_api_.SetScreenClip(
publisher_handle_,
left,
top,
width,
height);
publisher_api_.SetFrameRate(publisher_handle_, 15);
// Windows 8 及以上可按需启用 DXGI 屏幕采集
publisher_api_.EnableDXGIScreenCapturer(publisher_handle_, 1);
注意:屏幕裁剪宽高应按 SDK 要求进行对齐处理,避免编码器或采集模块出现异常。
7.2 摄像头采集
摄像头采集流程通常包括:枚举摄像头、选择设备、选择分辨率和帧率,然后设置摄像头基础参数。
publisher_api_.SetVideoCaptureDeviceBaseParameter(
publisher_handle_,
camera_id_utf8,
width,
height);
publisher_api_.SetFrameRate(publisher_handle_, frame_rate);
// 可选:摄像头翻转和旋转
publisher_api_.FlipVerticalCamera(publisher_handle_, is_flip_vertical);
publisher_api_.FlipHorizontalCamera(publisher_handle_, is_flip_horizontal);
publisher_api_.RotateCamera(publisher_handle_, degrees);
Demo 中摄像头采集会根据当前选择的摄像头、分辨率和帧率调用 SetVideoCaptureDeviceBaseParameter()、SetFrameRate(),并支持摄像头垂直翻转、水平翻转和旋转设置。
7.3 窗口采集
窗口采集适合只输出某个业务窗口内容的场景。使用前需要先选择目标窗口,并确认窗口句柄有效。
publisher_api_.SetCaptureWindow(publisher_handle_, target_hwnd);
publisher_api_.SetCaptureWindowWay(publisher_handle_, 1); // 1=GDI DC,2=WR,按系统支持情况选择
对于窗口大小可能动态变化的场景,建议结合码率组或动态码率策略,避免窗口变大后画质明显下降。
7.4 视频合成
当需要实现“屏幕 + 摄像头”“摄像头 + 图片水印”“窗口 + 图层叠加”等效果时,可使用 NT_PB_E_VIDEO_OPTION_LAYER 模式,并通过 SetLayersConfig() 配置多层画面。
SDK 头文件中定义的视频合成层包括屏幕层、摄像头层、RGBA 矩形层、图片层、外部视频帧层和窗口层。
// 示例:屏幕作为底层,摄像头作为右下角叠加层
NT_PB_ScreenLayerConfig screen_layer = {};
screen_layer.base_.type_ = NT_PB_E_LAYER_TYPE_SCREEN;
screen_layer.base_.index_ = 0;
screen_layer.base_.enable_ = 1;
screen_layer.base_.region_.x_ = 0;
screen_layer.base_.region_.y_ = 0;
screen_layer.base_.region_.width_ = output_width;
screen_layer.base_.region_.height_ = output_height;
NT_PB_CameraLayerConfig camera_layer = {};
camera_layer.base_.type_ = NT_PB_E_LAYER_TYPE_CAMERA;
camera_layer.base_.index_ = 1;
camera_layer.base_.enable_ = 1;
camera_layer.base_.region_.x_ = output_width - 320;
camera_layer.base_.region_.y_ = output_height - 240;
camera_layer.base_.region_.width_ = 320;
camera_layer.base_.region_.height_ = 240;
strncpy(camera_layer.device_unique_id_utf8_, camera_id_utf8, sizeof(camera_layer.device_unique_id_utf8_) - 1);
const NT_PB_LayerBaseConfig* layers[] = {
&screen_layer.base_,
&camera_layer.base_
};
publisher_api_.SetLayersConfig(publisher_handle_, 0, layers, 2, 0, nullptr);
SetLayersConfig() 通常应在启动推流、启动 RTSP 流或启动录像前完成。运行过程中,如需启用/禁用某一层或调整层位置,可使用 EnableLayer()、UpdateLayerRegion() 等接口。SDK 头文件中也对这些图层配置与动态更新接口进行了定义。
8. 视频编码参数配置

视频编码参数通常在 Open() 成功后、StartPublisher() 或 StartRtspStream() 之前设置。
8.1 编码类型
Windows C++ Demo 可根据实际环境选择 H.264 或 H.265,并支持软编码或硬编码方式。SDK 头文件中 SetVideoEncoder() 用于设置软硬编码类型、编码器 ID、Codec ID 和 GPU 参数;其中 H.264 可使用默认软编码器或 OpenH264,硬编码能力则取决于本机硬件和驱动环境。
NT_UINT32 codec_id = NT_MEDIA_CODEC_ID_H264;
// type: 0=软编码,1=硬编码
// encoder_id: 软编码 H.264 下 0=默认编码器,1=OpenH264;硬编码按 SDK 返回能力选择
// param1: 硬编码 GPU index,-1 表示 SDK 自动选择
publisher_api_.SetVideoEncoder(
publisher_handle_,
0,
0,
codec_id,
0);
建议发布文档中不要笼统承诺“所有机器均支持硬编 H.265”。更准确的写法是:SDK 提供 H.264/H.265 编码能力,H.265 和硬编码支持情况与 SDK 版本、系统架构、显卡硬件及驱动环境有关,应以实际测试结果为准。
8.2 码率、质量和 GOP
常用参数包括帧率、平均码率、最大码率、质量参数、关键帧间隔、H.264 Profile 和编码速度。
publisher_api_.SetFrameRate(publisher_handle_, 15);
publisher_api_.SetVideoBitRate(publisher_handle_, 1500); // kbps
publisher_api_.SetVideoMaxBitRate(publisher_handle_, 2000); // kbps
// 质量值范围 [1, 50],值越小质量越好,码率越高
publisher_api_.SetVideoQualityV2(publisher_handle_, 23);
// GOP,单位为帧。例如 15fps 下设置 15,约 1 秒一个关键帧
publisher_api_.SetVideoKeyFrameInterval(publisher_handle_, 15);
// H.264 Profile:1=Baseline,2=Main,3=High
publisher_api_.SetVideoEncoderProfile(publisher_handle_, 1);
// 编码速度,具体建议以 SDK 文档和实测效果为准
publisher_api_.SetVideoEncoderSpeed(publisher_handle_, 4);
SDK 头文件中说明了两类码率控制思路:SetVideoQualityV2 + SetVideoMaxBitRate,或 SetVideoMaxBitRate + SetVideoBitRate。其中 OpenH264 场景需要重点关注固定码率相关配置。
9. 音频采集与处理
9.1 音频源选择
Windows C++ Demo 支持以下常见音频源:
| 音频模式 | 说明 |
|---|---|
| 无音频 | 纯视频推流 |
| 麦克风采集 | 采集本机麦克风 |
| 扬声器采集 | 采集系统播放声音 |
| 麦克风 + 扬声器混音 | 适合会议、教学、同屏讲解等场景 |
| 外部 PCM | 应用层采集 PCM 后送入 SDK |
上传头文件中也定义了麦克风、扬声器、麦克风扬声器混音、外部编码音频、外部 PCM 数据等音频源选项。
9.2 音频编码与音量控制
// 1=AAC,2=Speex,具体取值以 SDK 头文件和当前版本说明为准
publisher_api_.SetPublisherAudioCodecType(publisher_handle_, 1);
// 静音 / 取消静音
publisher_api_.SetMute(publisher_handle_, 1);
publisher_api_.SetMute(publisher_handle_, 0);
// 音量调节,1.0 表示原始音量
publisher_api_.SetInputAudioVolume(publisher_handle_, 0, 1.0f);
如业务场景需要,可按需启用回声消除、噪声抑制、自动增益等音频处理能力。Demo 中也包含音频输入设备枚举、麦克风/扬声器可用性判断、音量默认值和 Speex 质量参数等初始化逻辑。
10. RTMP 推流集成

10.1 基本流程
RTMP 推流的核心流程如下:
Init
↓
Open
↓
SetEventCallBack
↓
设置采集源和编码参数
↓
SetURL
↓
StartPublisher
↓
事件回调处理
↓
StopPublisher
↓
Close
↓
UnInit
10.2 设置推流地址并启动

bool StartRTMPPublisher(const std::string& rtmp_url)
{
if (!OpenPublisherHandle())
return false;
SetCommonOptionToPublisherSDK();
if (NT_ERC_OK != publisher_api_.SetURL(
publisher_handle_,
rtmp_url.c_str(),
nullptr))
{
return false;
}
NT_UINT32 ret = publisher_api_.StartPublisher(
publisher_handle_,
nullptr);
return NT_ERC_OK == ret;
}
Demo 中支持设置一路或多路 RTMP 推流地址,并在启动前调用 SetURL(),随后调用 StartPublisher()。上传代码中还可以看到 Demo 会维护推流 URL 列表,并在调用 StartPublisher() 前完成 URL 设置和用户数据队列配置。
10.3 停止推流
void StopRTMPPublisher()
{
if (publisher_handle_ != nullptr)
{
publisher_api_.StopPublisher(publisher_handle_);
}
}
如果 RTMP 推流、RTSP 流输出、录像和预览共用同一个 publisher_handle_,建议通过引用计数或状态机管理句柄生命周期。不要在仅停止 RTMP 推流时立即 Close() 句柄,否则可能影响正在运行的 RTSP 输出或录像任务。
11. 轻量级 RTSP 服务集成

轻量级 RTSP 服务模块以内置服务方式工作,典型流程如下:
OpenRtspServer
↓
SetRtspServerPort
↓
可选:SetRtspServerUserNamePassword
↓
可选:SetRtspServerMulticast / SetRtspServerMulticastAddress
↓
StartRtspServer
↓
SetRtspStreamName
↓
AddRtspStreamServer
↓
StartRtspStream
↓
通过事件回调获取 RTSP URL
SDK 头文件中明确提供了 OpenRtspServer、SetRtspServerPort、SetRtspServerUserNamePassword、SetRtspServerMulticast、SetRtspServerMulticastAddress 等 RTSP Server 操作接口。
11.1 创建并启动 RTSP Server
NT_HANDLE rtsp_server_handle = nullptr;
bool StartRtspServer(int port)
{
if (NT_ERC_OK != publisher_api_.OpenRtspServer(&rtsp_server_handle, 0))
return false;
if (rtsp_server_handle == nullptr)
return false;
if (NT_ERC_OK != publisher_api_.SetRtspServerPort(rtsp_server_handle, port))
{
publisher_api_.CloseRtspServer(rtsp_server_handle);
rtsp_server_handle = nullptr;
return false;
}
// 可选:设置用户名密码,用户名和密码建议使用英文字符
publisher_api_.SetRtspServerUserNamePassword(
rtsp_server_handle,
"admin",
"123456");
if (NT_ERC_OK != publisher_api_.StartRtspServer(rtsp_server_handle, 0))
{
publisher_api_.CloseRtspServer(rtsp_server_handle);
rtsp_server_handle = nullptr;
return false;
}
return true;
}
Demo 中 RTSP Server 配置窗口支持多路服务实例配置,并可设置端口、用户名、密码、单播/组播、SSM 组播地址和会话数查询。
11.2 绑定推流实例并启动 RTSP 流

RTSP Server 启动后,需要把当前推流实例绑定到 RTSP Server,并设置流名称。
bool StartRtspStream()
{
if (!OpenPublisherHandle())
return false;
SetCommonOptionToPublisherSDK();
// URL 路径名,例如最终可能形如:rtsp://本机IP:554/live
publisher_api_.SetRtspStreamName(publisher_handle_, "live");
publisher_api_.AddRtspStreamServer(
publisher_handle_,
rtsp_server_handle,
0);
NT_UINT32 ret = publisher_api_.StartRtspStream(
publisher_handle_,
0);
return NT_ERC_OK == ret;
}
SDK 头文件中说明,一个推流实例可以发布到多个 RTSP Server 上;SetRtspStreamName() 用于设置流名称,AddRtspStreamServer() 用于将推流实例绑定到 RTSP Server,StartRtspStream() 用于启动 RTSP 流输出。
11.3 获取 RTSP URL
RTSP 流启动后,SDK 会通过事件回调通知可播放的 RTSP URL。事件 ID 为:
NT_PB_E_EVENT_ID_RTSP_URL
事件回调中的 param5 表示 RTSP URL。上传的事件定义和 Demo 代码均体现了该事件语义。
case NT_PB_E_EVENT_ID_RTSP_URL:
{
if (param5 != nullptr)
{
std::string rtsp_url = param5;
// 将 rtsp_url 显示到 UI,或下发给局域网客户端
}
break;
}
11.4 查询 RTSP 客户端会话数
RTSP 服务运行过程中,可以查询当前客户端连接会话数,用于业务侧展示或运行状态监控。
NT_INT32 session_count = 0;
publisher_api_.GetRtspServerClientSessionNumbers(
rtsp_server_handle,
&session_count);
官网资料也明确提到轻量级 RTSP 服务支持会话连接数查询,便于上层监控服务负载和访问情况。
11.5 停止 RTSP 流与 RTSP Server
void StopRtsp()
{
if (publisher_handle_ != nullptr)
{
publisher_api_.StopRtspStream(publisher_handle_);
publisher_api_.ClearRtspStreamServer(publisher_handle_);
}
if (rtsp_server_handle != nullptr)
{
publisher_api_.StopRtspServer(rtsp_server_handle);
publisher_api_.CloseRtspServer(rtsp_server_handle);
rtsp_server_handle = nullptr;
}
}
RTSP 流输出和 RTSP Server 是两个层面的资源:StopRtspStream() 停止当前推流实例的 RTSP 输出;StopRtspServer() 和 CloseRtspServer() 用于停止并释放 RTSP Server 实例。
12. RTMP 与 RTSP 同时输出
在实际项目中,常见需求是同一路 Windows 摄像头或屏幕数据,既推送到远端 RTMP 服务器,又通过本地 RTSP URL 给局域网客户端实时播放。该场景可以复用同一个 publisher_handle_:
bool StartRTMPAndRTSP()
{
if (!OpenPublisherHandle())
return false;
SetCommonOptionToPublisherSDK();
// 1. 启动 RTSP Server
if (!StartRtspServer(554))
return false;
// 2. 启动 RTSP 流输出
publisher_api_.SetRtspStreamName(publisher_handle_, "live");
publisher_api_.AddRtspStreamServer(publisher_handle_, rtsp_server_handle, 0);
if (NT_ERC_OK != publisher_api_.StartRtspStream(publisher_handle_, 0))
return false;
// 3. 启动 RTMP 推流
publisher_api_.SetURL(
publisher_handle_,
"rtmp://your-server/live/stream",
nullptr);
if (NT_ERC_OK != publisher_api_.StartPublisher(publisher_handle_, nullptr))
return false;
return true;
}
上传文档中的示例也采用了类似流程:先创建并启动 RTSP Server,再设置 RTSP Stream Name、绑定 RTSP Server、启动 RTSP 流,随后再设置 RTMP URL 并启动 RTMP 推流。
13. 推流端预览
推流端预览适合在业务界面中显示当前采集或合成后的画面,便于用户确认画面内容、摄像头位置、水印叠加和窗口采集区域。

核心流程如下:
publisher_api_.SetVideoPreviewImageCallBack(
publisher_handle_,
NT_PB_E_IMAGE_FORMAT_RGB32,
reinterpret_cast<NT_PVOID>(GetSafeHwnd()),
NT_PB_SDKVideoPreviewImageHandle);
publisher_api_.StartPreview(publisher_handle_, 0, nullptr);
停止预览:
publisher_api_.StopPreview(publisher_handle_);
上传的 Demo 中,预览流程会先确保 publisher_handle_ 已创建,再设置 RGB32 图像回调并调用 StartPreview(),随后由预览窗口完成图像绘制。
14. 本地录像与截图
虽然本文重点是 RTMP 推流和轻量级 RTSP 服务,但 Windows C++ Demo 也包含录像与截图能力,可作为实际项目中的扩展功能使用。
14.1 本地录像
publisher_api_.SetRecorderDirectoryW(
publisher_handle_,
L"D:\\Recordings\\",
nullptr);
publisher_api_.SetRecorderFileMaxSize(
publisher_handle_,
200 * 1024); // KB
NT_PB_RecorderFileNameRuler ruler = {};
ruler.file_name_prefix_ = "smartpublisher";
ruler.append_date_ = 1;
ruler.append_time_ = 1;
publisher_api_.SetRecorderFileNameRuler(
publisher_handle_,
&ruler);
publisher_api_.StartRecorder(
publisher_handle_,
nullptr);
停止录像:
publisher_api_.StopRecorder(publisher_handle_);
SDK 头文件中定义了 SetRecorderDirectoryW()、SetRecorderFileMaxSize()、SetRecorderFileNameRuler()、StartRecorder()、PauseRecorder() 和 StopRecorder() 等录像接口。
14.2 截图
publisher_api_.CaptureImage(
publisher_handle_,
"D:\\snapshot.png",
nullptr,
NT_PB_SDKCaptureImageHandle);
截图通常是异步操作,应通过回调获取结果。发布说明中建议写清楚:截图能力依赖当前是否有可用视频帧,通常应在预览、推流、RTSP 输出或录像运行过程中调用。
15. 事件回调处理
SDK 事件回调是业务侧判断推流状态、RTSP URL、录像文件状态和异常情况的重要入口。常见事件包括:
| 事件 ID | 说明 | param5 |
|---|---|---|
NT_PB_E_EVENT_ID_CONNECTING |
正在连接 RTMP 推流服务器 | 推流 URL |
NT_PB_E_EVENT_ID_CONNECTED |
推流连接成功 | 推流 URL |
NT_PB_E_EVENT_ID_CONNECTION_FAILED |
推流连接失败 | 推流 URL |
NT_PB_E_EVENT_ID_DISCONNECTED |
推流连接断开 | 推流 URL |
NT_PB_E_EVENT_ID_RECORDER_START_NEW_FILE |
开始写入新的录像文件 | 文件路径 |
NT_PB_E_EVENT_ID_ONE_RECORDER_FILE_FINISHED |
一个录像文件完成 | 文件路径 |
NT_PB_E_EVENT_ID_CAPTURE_WINDOW_INVALID |
窗口采集句柄无效 | — |
NT_PB_E_EVENT_ID_RTSP_URL |
RTSP URL 已生成 | RTSP URL |
上述事件 ID 在 SDK 头文件中有明确枚举定义,Demo 中也通过事件回调将连接状态、录像文件、RTSP URL 等信息转发到 UI 线程处理。
建议不要在 SDK 回调线程中直接操作 UI 控件。推荐通过 PostMessage() 把事件派发到主线程:
extern "C" NT_VOID NT_CALLBACK NT_PB_SDKPublisherEventHandle(
NT_HANDLE handle,
NT_PVOID user_data,
NT_UINT32 event_id,
NT_INT64 param1,
NT_INT64 param2,
NT_UINT64 param3,
NT_UINT64 param4,
NT_PCSTR param5,
NT_PCSTR param6,
NT_PVOID param7)
{
HWND hwnd = reinterpret_cast<HWND>(user_data);
if (hwnd == nullptr || !::IsWindow(hwnd))
return;
switch (event_id)
{
case NT_PB_E_EVENT_ID_CONNECTING:
case NT_PB_E_EVENT_ID_CONNECTED:
case NT_PB_E_EVENT_ID_CONNECTION_FAILED:
case NT_PB_E_EVENT_ID_DISCONNECTED:
// 建议 PostMessage 到 UI 线程后再更新状态
break;
case NT_PB_E_EVENT_ID_RTSP_URL:
// param5 为可播放 RTSP URL
break;
default:
break;
}
}
Demo 中就是采用 PostMessage() 方式,把连接事件、RTSP URL、录像文件事件等从 SDK 回调线程派发到窗口线程。
16. 资源释放顺序
建议按以下顺序释放资源:
StopPublisher
↓
StopRtspStream
↓
StopRecorder
↓
StopPreview
↓
ClearRtspStreamServer
↓
StopRtspServer / CloseRtspServer
↓
Close publisher_handle
↓
UnInit
示例:
void ReleasePublisher()
{
if (publisher_handle_ != nullptr)
{
publisher_api_.StopPublisher(publisher_handle_);
publisher_api_.StopRtspStream(publisher_handle_);
publisher_api_.StopRecorder(publisher_handle_);
publisher_api_.StopPreview(publisher_handle_);
publisher_api_.ClearRtspStreamServer(publisher_handle_);
publisher_api_.Close(publisher_handle_);
publisher_handle_ = nullptr;
}
if (rtsp_server_handle != nullptr)
{
publisher_api_.StopRtspServer(rtsp_server_handle);
publisher_api_.CloseRtspServer(rtsp_server_handle);
rtsp_server_handle = nullptr;
}
publisher_api_.UnInit();
}
如果业务中 RTMP、RTSP、录像、预览可能独立启停,建议不要简单地在每个“停止按钮”里直接 Close() 句柄,而应通过状态变量或引用计数判断当前是否仍有模块在使用该 publisher_handle_。
17. 常见问题
17.1 StartPublisher 失败
建议检查:
- RTMP URL 是否合法,通常应以
rtmp://开头; - RTMP Server 是否可访问;
- 防火墙、端口、DNS、网络代理是否影响连接;
- 是否已经成功调用
Open(); - 是否已经配置必要的视频源、音频源和编码参数。
17.2 RTSP URL 无法播放
建议检查:
- RTSP Server 是否成功启动;
- 端口是否被占用;
- Windows 防火墙是否放行对应端口;
- 是否调用了
SetRtspStreamName()、AddRtspStreamServer()和StartRtspStream(); - 是否通过
NT_PB_E_EVENT_ID_RTSP_URL获取到了正确 URL; - 播放器是否与当前编码格式兼容。
17.3 摄像头无画面
建议检查:
- 摄像头是否被其他程序占用;
- 摄像头 ID 是否正确;
- 分辨率和帧率是否为摄像头实际支持的组合;
- 是否调用了
SetVideoCaptureDeviceBaseParameter(); - 是否有安全软件拦截摄像头访问。
17.4 屏幕采集画面异常
建议检查:
- 屏幕裁剪区域宽高是否符合对齐要求;
- Windows 版本是否适合启用 DXGI;
- Win7 下是否需要处理 Aero 相关设置;
- 是否采集了分层窗口或特殊渲染窗口。
18. 集成建议
在生产项目中,建议按以下原则集成:
- 先跑通最小链路
先完成“屏幕或摄像头采集 → H.264 编码 → RTMP 推流”或“屏幕/摄像头采集 → RTSP URL 输出”的最小链路,再逐步增加混音、合成、录像、截图等能力。 - 参数配置前置
采集源、编码参数、图层配置、RTSP Server 绑定等操作,尽量在启动推流或启动 RTSP 流前完成。 - 事件回调线程隔离
SDK 回调中不要直接操作 UI,统一通过消息机制切回主线程处理。 - 句柄生命周期统一管理
RTMP 推流、RTSP 流、录像、预览可能共用同一个 publisher handle,建议使用状态机或引用计数管理,避免提前释放。 - 能力说明以实际版本为准
H.265、硬编码、窗口采集、组播、外部数据接入等能力,建议在客户交付前结合 SDK 授权包、系统环境和目标硬件进行实测验证。
总结
大牛直播SDK(SmartMediaKit)Windows C++ 推流 SDK 通过统一的 C 接口函数表,为业务系统提供 RTMP 推流、轻量级 RTSP 服务、本地采集、音视频编码、视频合成、预览、录像和事件回调等能力。RTMP 推流适合对接中心服务器、CDN 或直播平台;轻量级 RTSP 服务适合在局域网内快速生成可拉流访问的实时视频服务,两者组合后,可覆盖“远端平台分发 + 本地实时查看”的典型行业需求。
对于 Windows 端实时音视频系统而言,该方案的核心价值在于:无需从零实现采集、编码、封装、推流和 RTSP 服务能力,开发者只需围绕业务场景配置采集源、编码参数和输出方式,即可快速构建稳定、低延迟、可扩展的音视频推流与局域网分发能力。
📎 CSDN官方博客:音视频牛哥-CSDN博客
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)