Windows 直播推流 SDK 开发指南

1 开发准备

开始前请确保下述前提条件已准备就绪:

解压后 SDK 包的 libs 文件夹中,包含了 dll 库文件和头文件,文件列表如下:

libs
├── base.dll
├── cos.dll
├── engine.dll
├── itrd.dll
├── libeay32.dll
├── libfdk-aac-0.dll
├── libgcc_s_dw2-1.dll
├── libiconv-2.dll
├── libopenh264.dll
├── librtmp.dll
├── libstdc++-6.dll
├── livestream.dll
├── LSMediaCapture.dll
├── LSMediaCapture.lib
├── ssleay32.dll
├── zlib1.dll
├── include
│   ├── nlss_api.h
│   ├── nMediaCaptureApi.h
│   ├── nMediaLiveStreamingDefs.h
└──

总体接口约定 SDK 提供的API C类型接口,分别提供 win32 的动态库 LSMediaCapture.dll 及其对应的导入库 LSMediaCapture.lib 方便开发者动态加载或者加载 SDK 库文件。 App 开发者只需要引用 SDK 包里 sdk\include 目录下的定义头文件 nlss_api.h nlss_define.h nlss_type.h 即可。关于API类或者函数的定义,可以查看API 文档。

2 集成 SDK

本文是根据官网的直播推流 Demo 来介绍 SDK 的集成,可在网易视频云官网下载最新的直播推流 Windows Demo,来查看更多的实现细节。

将SDK 相关的dll 文件(sdk\runtime\)放到App 的运行目录下。SDK 基于vs2013 开发,如果App 没有对应的运行时库文件(msvcp120.dll和msvcr120.dll),请将其放到App 的运行目录下。准备工作完成后,可以选择动态加载或者静态加载的模式调用LSMediaCapture.dll。

2.1 获取音视频设备列表

先通过调用 Nlss_GetFreeDevicesNum(NLSS_OUT int iVideoDeviceNum, NLSS_OUT int iAudioDeviceNum) 获取当前摄像头/麦克风的个数,根据个数,初始化结构体 ST_NLSS_INDEVICE_INF 数组,并将此数组作为参数传递给Nlss_GetFreeDeviceInf(NLSS_OUT ST_NLSS_INDEVICE_INF pstVideoDevices, NLSS_OUT ST_NLSS_INDEVICE_INF pstAudioDevices) 接口,进而获取当前所有摄像头/麦克风,下面以 Demo/SimpleDemo/TestCppAPI 以及 TestCapi 分别简单介绍,如何调用这两个接口

    NLSS_RET  Nlss_GetFreeDevicesNum(NLSS_OUT int *iVideoDeviceNum, NLSS_OUT int *iAudioDeviceNum);
    NLSS_RET  Nlss_GetFreeDeviceInf(NLSS_OUT ST_NLSS_INDEVICE_INF *pstVideoDevices, NLSS_OUT ST_NLSS_INDEVICE_INF* pstAudioDevices);

示例代码

void foo()
{
    int iVideoDeviceNum = 0;
    int iAudioDeviceNum = 0;
    Nlss_GetFreeDevicesNum(&iVideoDeviceNum, &iAudioDeviceNum);
    ST_NLSS_INDEVICE_INF* pstDeviceVideoInfo = (ST_NLSS_INDEVICE_INF*)malloc(sizeof(ST_NLSS_INDEVICE_INF)*iVideoDeviceNum);
    ST_NLSS_INDEVICE_INF* pstDeviceAudioInfo = (ST_NLSS_INDEVICE_INF*)malloc(sizeof(ST_NLSS_INDEVICE_INF)*iAudioDeviceNum);
    for (int i = 0; i < iVideoDeviceNum; i++)
    {
        pstDeviceVideoInfo[i].paPath = (char*)malloc(1024);
        pstDeviceVideoInfo[i].paFriendlyName = (char*)malloc(1024);
    }
    for (int i = 0; i < iAudioDeviceNum; i++)
    {
        pstDeviceAudioInfo[i].paPath = (char*)malloc(1024);
        pstDeviceAudioInfo[i].paFriendlyName = (char*)malloc(1024);
    }

    Nlss_GetFreeDeviceInf(pstDeviceVideoInfo, pstDeviceAudioInfo);
}

2.2 初始化音视频直播

SDK的主要功能就是提供音视频的直播功能,包括了音视频的采集,编码,以及发送。 采集编码发送的方式,协议有很多,目前实现的是:采集用Dshow方式获取视频,Dsound方式获取音频,默认支持WIN7平台,编码采用H264,AAC两种最通用的格式,发送遵照RTMP标准协议;接下来SDK将提供更多格式的音视频直播流。

如上面所说,使用直播推流服务时,需要首先创建一个直播推流服务句柄,多次推流可以使用同一个该句柄,只需要参数。我们需要创建通过 Nlss_Create 创建它,在不需要使用直播时,通过 Nlss_Destroy 销毁它

 NLSS_RET  Nlss_Create(const char *paLogpath, NLSS_OUT _HNLSSERVICE *phNLSService);
 void      Nlss_Destroy(_HNLSSERVICE hNLSService);

直播推流参数设置

在直播类/结构体创建好之后,需要初始化直播推流各参数,初始化接口为:

NLSS_RET   Nlss_InitParam(_HNLSSERVICE hNLSService, ST_NLSS_PARAM *pstParam);

上述上个接口都需要初始化 ST_NLSS_PARAM 结构体,包括推流地址,音/视频设备名,音视频的各种推流参数,详情见ST_NLSS_PARAM 结构体。为了方便设置,SDk建议你先通过 Nlss_GetDefaultParam 获取部分默认参数,然后再个性化设置一些参数,再调用 Nlss_InitParam,实现直播推流参数初始化。

NLSS_RET   Nlss_GetDefaultParam(_HNLSSERVICE hNLSService, NLSS_OUT ST_NLSS_PARAM *pstParam);

注:在设置视频的帧率(iOutFps)时,目标码率(iOutBitrate)几个关键值时,为了保障流畅的体验效果,关键是推流端和拉流端的带宽。我们的建议如下:

 iOutFps:主播生活直播场景设为15,共享桌面在线教育场景设为4-8;
 iOutBitrate:我们在DEMO层做了指导函数,可参考demo代码
 #define  NLSS_720P_BITRATE 800000
 //获取建议的输出目标码率供开发者使用,请关注
 int getOutBitrate(int iWidth, int iHeight, int iFps)
 {
      if (iWidth == 0 || iHeight == 0 || iFps == 0)
      {
          return  NLSS_720P_BITRATE; //1280*720 15fps ,设置的码率
      }
      int iOutBitrate = NLSS_720P_BITRATE / 1280 * iWidth;
      iOutBitrate = iOutBitrate / 720 * iHeight;
      if (iFps >= 15)
      {
         iOutBitrate = iOutBitrate / 15 * iFps;
      }
      return iOutBitrate;
}

2.3 实现直播推流

推流初始化直播推流参数之后,就可以开始直播了。一般情况下,我们会先打开视频预览,了解当前推流视频状况,确认是否要要推流,设置具体推流的类型:音频/视频/音视频流,音视频推流过程中,SDK提供暂停,恢复,以及单独暂停其中音频或视频的功能。除此以外,SDK提供直播过程中各种统计信息,并提供直播状态的回调,让开发者对直播各种健康状况更加明朗。以下将逐一介绍围绕直播的一些功能

设置视频采集帧回调 SDK提供设置采集视频回调接口,当SDK采集到一帧视频时,判断此回调是否设置,如设置,则返回帧数据,以ARGB32格式

typedef  void(*PFN_NLSS_VIDEOSAMPLER_CB)(ST_NLSS_VIDEO_SAMPLER *pstSampler);
void     Nlss_SetVideoSamplerCB(_HNLSSERVICE hNLSService, PFN_NLSS_VIDEOSAMPLER_CB pFunVideoSamplerCB);

视频预览 打开/停止,暂停/恢复配套使用,暂停与停止功能的区别是资源是否释放,如当前正在直播,则同时打开/停止了视频直播功能,音频直播照常。结合上述的视频数据回调接口,可以呈现SDK捕获的视频。

NLSS_RET  Nlss_StartVideoPreview(_HNLSSERVICE hNLSService);    
void      Nlss_PauseVideoPreview(_HNLSSERVICE hNLSService);
void      Nlss_ResumeVideoPreview(_HNLSSERVICE hNLSService);    
void      Nlss_StopVideoPreview(_HNLSSERVICE hNLSService);

设置直播状态回调 开启直播之前,设置直播状态回调。有如下几个状态请关注 直播成功开始状态是 EN_NLSS_STATUS_START,可以及时的显示; 直播过程出错状态是 EN_NLSS_STATUS_ERR(当直播过程中发生头信息发送不出去,或者数据流发送失败时)回调给上层做进一步处理,一般情况下,请调用停止直播接口

typedef void(*PFN_NLSS_STATUS_NTY)(EN_NLSS_STATUS enStatus, EN_NLSS_ERRCODE enErrCode);
void     Nlss_SetStatusCB(_HNLSSERVICE hNLSService, PFN_NLSS_STATUS_NTY pFunStatusNty);

获取直播统计信息 SDK 提供直播推流过程中一些音视频相关信息的方法,让调用者对直播流健康状况有个更好的了解。调用者可以定时去获取统计信息,具体的统计信息请参考API 文档中 ST_NLSS_STATS 结构体描述

NLSS_RET   Nlss_GetStaticInfo(_HNLSSERVICE hNLSService, NLSS_OUT ST_NLSS_STATS *pstStats);

设置直播流内容 在初始化音视频推流参数中,可以根据具体需要,设置直播流的内容,是只推视频流,音频流,还是音视频流,设置的字段如下:

ST_NLSS_PARAM.enOutContent = EN_NLSS_OUTCONTENT_**;

设置直播流画面尺寸 在开始直播前,可以根据具体需要,设置视频推流显示比例。不调用是原屏比例,如设为宽屏,则入参为16,9,恢复原屏幕,入参为0,0 即可:

void     Nlss_SetVideoDisplayRatio(_HNLSSERVICE hNLSService, int iWideUnit, int iHeightUnit);

设置水印 在开始直播前,可以根据具体需要,设置视频是否添加水印。可以设置png图像和添加位置,不调用该函数或者水平参数设为空,不产生水印:

void     Nlss_SetVideoWaterMark(_HNLSSERVICE hNLSService, ST_NLSS_VIDEO_WATER_PARAM *pstWaterParam);

直播操作 启动直播,停止直播。

NLSS_RET   Nlss_StartLiveStream(_HNLSSERVICE hNLSService);    
void       Nlss_StopLiveStream(_HNLSSERVICE hNLSService);

视频流操作 当打开的是音视频流推流功能时,在推流过程中,SDK提供单独暂停,恢复音视频中的视频流的直播。

void       Nlss_PauseVideoLiveStream(_HNLSSERVICE hNLSService);    
void       Nlss_ResumeVideoLiveStream(_HNLSSERVICE hNLSService);    

音频流操作 当打开的是音视频流推流功能时,在推流过程中,SDK提供单独暂停,恢复音视频中的音频流的直播。

void       Nlss_PauseAudioLiveStream(_HNLSSERVICE hNLSService);
void       Nlss_ResumeAudioLiveStream(_HNLSSERVICE hNLSService);    

获取当前SDK版本号

void Nlss_GetVersionNo(NLSS_OUT char **ppaVersion);

2.4 SDK提供裸流直播接口

以上的方式直播推流是黑盒化的,采集和编码发送都是sdk内部做的,开发者或者用户提供裸流(例如:yuv420 或者 pcm 数据),SDK 负责编码和传输;给开发者增加了定制方式。 (1)首先在初始化将 ST_NLSS_PARAM 如下音视频输入流 stVideoParam.enInType,stAudioParam.enInType 分别设为EN_NLSS_VIDEOIN_RAWDATA,EN_NLSS_AUDIOIN_RAWDATA;

同时如下音视频输入参数请按照输入流的格式填写,便于sdk进行正确的音视频数据处理
typedef struct struct_NLSS_PARAM
{
   ST_NLSS_VIDEO_PARAM       stVideoParam;       //!< 推流视频相关参数.
   ST_NLSS_AUDIO_PARAM       stAudioParam;       //!< 推流音频相关参数.
} ST_NLSS_PARAM;

(2)在 Nlss_StartLiveStream 之后,就可以调用如下接口进行传输你的音视频流

NLSS_RET    Nlss_SendCustomVideoData(_HNLSSERVICE hNLSService, char *pcVideoData, int iLen, NLSS_OUT EN_NLSS_ERRCODE *penErrCode);
NLSS_RET   Nlss_SendCustomAudioData(_HNLSSERVICE hNLSService, char *pcAudioData, int iLen, int iSampleRate, NLSS_OUT EN_NLSS_ERRCODE *penErrCode);

3 SDK 打包说明

开发者在打包自己的应用时,应确保将以下 SDK 相关文件打包进去。

4 API说明

有关API的详细说明,可参见SDK包中docs,打开index.html查看,或者打开下面的在线文档。

网易视频云直播推流LiveStreaming Windows SDK API详细文档