Windows 视频直播功能实现流程

Windows下视频直播场景主要有单主播直播、多主播(连麦)直播和混流直播等,主要结构及流程如下图所示:
Windows 视频直播功能实现流程_第1张图片
请注意:

本文主要介绍如何使用Zego即构科技 SDK 快速实现Windows下视频直播基本功能的流程,请从 SDK集成指引 下载 SDK并阅读接入说明。除了上图所示基本功能,开发者还可以使用即构科技 SDK 实现更高级的功能,例如混音、音频录制、外部滤镜等(这块本文不再介绍,可以阅读本博客相关文章)。

为了便于开发者更快理解 LiveDemo5 中的逻辑,下述每节会将功能核心源码片段挑出来并加以讲解。开发者亦可直接阅读 LiveDemo5 源码,两者是一致的。

1、单主播直播

单主播直播时,一个房间内仅有一个主播,不支持主播与观众的连麦互动。单主播模式下,发布直播时,需要声明 flag 为 ZEGO_SINGLE_ANCHOR。

1.1 主播推流

主播向观众推送自己的画面,需先推流(即发布直播)。LiveDemo5 中推流相关源码片段演示如下,仅供参考:

ZegoSingleAnchorDialog.cpp  // 此 Dialog 为单主播发布 Dialog,多主播发布逻辑类似

// 执行登录房间操作,成功后将在回调中发布直播
LIVEROOM::LoginRoom(roomID, LIVEROOM::ZegoRoomRole::Anchor, roomName);

//LoginRoom的回调函数OnLoginRoom
void ZegoSingleAnchorDialog::OnLoginRoom(int errorCode, const QString& strRoomID, QVector vStreamList)
{
    if (errorCode != 0)
    {
        QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("登陆房间失败"));
        OnClose();
    }

   ...

   StartPublishStream();

}

//发布直播
void ZegoSingleAnchorDialog::StartPublishStream()
{

    QTime currentTime = QTime::currentTime();
    //获取当前时间的毫秒
    int ms = currentTime.msec();
    QString strStreamId;
    strStreamId = QString(QStringLiteral("s-windows-%1-%2")).arg(m_strCurUserID).arg(ms);
    m_strPublishStreamID = strStreamId;

    StreamPtr pPublishStream(new QZegoStreamModel(m_strPublishStreamID, m_strCurUserID, m_strCurUserName, "", true));

    ...

    if (m_avaliableView.size() > 0)
    {
        int nIndex = takeLeastAvaliableViewIndex();
        pPublishStream->setPlayView(nIndex);

        //配置View
        LIVEROOM::SetPreviewView((void *)AVViews[nIndex]->winId());
        LIVEROOM::SetPreviewViewMode(LIVEROOM::ZegoVideoViewModeScaleAspectFill);
        LIVEROOM::StartPreview();

        QString streamID = m_strPublishStreamID;
        LIVEROOM::StartPublishing(m_pChatRoom->getRoomName().toStdString().c_str(), streamID.toStdString().c_str(), LIVEROOM::ZEGO_SINGLE_ANCHOR, "");
        m_bIsPublishing = true;
    }
}

1.2 观众拉流

观众想看到主播画面,需拉流(即观看直播)。LiveDemo5 中拉流相关源码片段演示如下,仅供参考:

ZegoSingleAudienceDialog.cpp  // 此 Dialog 为单主播模式下,观看直播 Dialog,多主播时拉流逻辑类似

void ZegoSingleAudienceDialog::StartPlayStream(StreamPtr stream)
{
    if (stream == nullptr) { return; }

    ...

    if (m_avaliableView.size() > 0)
    {
        int nIndex = takeLeastAvaliableViewIndex();
        stream->setPlayView(nIndex);

        //配置View
        LIVEROOM::SetViewMode(LIVEROOM::ZegoVideoViewModeScaleAspectFill, stream->getStreamId().toStdString().c_str());
        LIVEROOM::StartPlayingStream(stream->getStreamId().toStdString().c_str(), (void *)AVViews[nIndex]->winId());
    }
}

1.3 API 调用时序图
Windows 视频直播功能实现流程_第2张图片
单主播直播 API 调用时序图如下所示:

2、多主播直播

2.1 功能介绍

多主播直播是主播与观众连麦,使观众也成为主播的互动功能。多主播直播的推流、拉流流程,同单主播基本一致,不同点在于,主播发布直播时,需要声明 flag 为 ZEGO_JOIN_PUBLISH。

2.2 系统架构图

连麦系统架构图如下所示:
Windows 视频直播功能实现流程_第3张图片
2.3 API 调用时序图

多主播直播 API 调用时序图如下所示:
Windows 视频直播功能实现流程_第4张图片
3、混流直播

3.1 功能介绍

混流直播模式下,Zego 服务器会将多路单独的音视频流混成一路音视频流。混流直播的推流、拉流流程,同单主播基本一致,不同点在于:

  1. 主播发布直播时,需要声明 flag 为 ZEGO_MIX_STREAM。

  2. 观众可以使用 mixStreamID 选择拉一路混流数据,也可使用 streamID 分别拉多路单流数据,取决于用户需求,SDK不做强制要求。

  3. 混流直播模式下,支持主播与观众连麦。

对于上述第 3 点,多主播(连麦)直播与混流直播中的连麦区别是:

  • 连麦模式:若两个主播连麦,观众端需要拉两路单独音视频流播放两个主播的画面。

  • 混流模式:若两个主播连麦,Zego
    混流服务器会把两路单独的音视频流混合成一路音视频流。观众端有两个选择:1、拉一路混流播放两主播的画面。2、拉两路单独的流播放两个主播的画面。

此时,混流直播相对于多主播直播的优势:

  • 观众端只要拉一路混流就可以成功播放两个主播的画面。

  • 只需要分享一个直播链接,观众端就可以通过回放录播文件,看到两个主播的画面。

LiveDemo5 中设置混流相关的源码片段演示如下,仅供参考:

ZegoMixStreamAnchorDialog.cpp

// 流增加时的混流操作
void ZegoMixStreamAnchorDialog::MixStreamAdd(QVector vStreamList, const QString& roomId)
{
    //主播端流增加,更新混流信息
    int width = m_pAVSettings->GetResolution().cx;
    int height = m_pAVSettings->GetResolution().cy;
    qDebug() << "current mix size = " << m_mixStreamInfos.size();
    // 对待混流的单流进行布局设置,此处的案例为最多新增2条流进行混流。请开发者酌情参考。
    for (auto streamInfo : vStreamList)
    {
        StartPlayStream(streamInfo);

        if (m_mixStreamInfos.size() == 1)
        {
            AV::ZegoMixStreamConfig *mixStreamInfo = new AV::ZegoMixStreamConfig;
            strcpy(mixStreamInfo->szStreamID, streamInfo->getStreamId().toStdString().c_str());
            mixStreamInfo->layout.top = (int)(height * 2.0 / 3);
            mixStreamInfo->layout.bottom = height;
            mixStreamInfo->layout.left = (int)(width * 2.0 / 3);
            mixStreamInfo->layout.right = width;

            m_mixStreamInfos.push_back(mixStreamInfo);
        }
        else if (m_mixStreamInfos.size() == 2)
        {
            AV::ZegoMixStreamConfig *mixStreamInfo = new AV::ZegoMixStreamConfig;
            strcpy(mixStreamInfo->szStreamID, streamInfo->getStreamId().toStdString().c_str());
            mixStreamInfo->layout.top = (int)(height * 2.0 / 3);
            mixStreamInfo->layout.bottom = height;
            mixStreamInfo->layout.left = (int)(width * 1.0 / 3);
            mixStreamInfo->layout.right = (int)(width * 2.0 / 3);

            m_mixStreamInfos.push_back(mixStreamInfo);
        }

    }

        StartMixStream();
}

//流减少时的混流操作
void ZegoMixStreamAnchorDialog::MixStreamDelete(QVector vStreamList, const QString& roomId)
{
    for (auto bizStream : vStreamList)
    {
        StopPlayStream(bizStream->getStreamId());

        for (int i = 0; i < m_mixStreamInfos.size(); i++)
        {
            if (strcmp(m_mixStreamInfos[i]->szStreamID, bizStream->getStreamId().toStdString().c_str()) == 0)
            {
                m_mixStreamInfos.removeAt(i);
                break;
            }
        }
    }

    StartMixStream();
}

//无论时流增加或者流减少,在这之后均需要更新混流配置,此处的 StartMixStream 可理解为 UpdateMixStream
void ZegoMixStreamAnchorDialog::StartMixStream()
{
    int size = m_mixStreamInfos.size();
    int width = m_pAVSettings->GetResolution().cx;
    int height = m_pAVSettings->GetResolution().cy;

    AV::ZegoCompleteMixStreamConfig mixStreamConfig;
    mixStreamConfig.pInputStreamList = new AV::ZegoMixStreamConfig[size];

    for (int i = 0; i < size; i++)
    {
        strcpy(mixStreamConfig.pInputStreamList[i].szStreamID, m_mixStreamInfos[i]->szStreamID);
        mixStreamConfig.pInputStreamList[i].layout.top = m_mixStreamInfos[i]->layout.top;
        mixStreamConfig.pInputStreamList[i].layout.bottom = m_mixStreamInfos[i]->layout.bottom;
        mixStreamConfig.pInputStreamList[i].layout.left = m_mixStreamInfos[i]->layout.left;
        mixStreamConfig.pInputStreamList[i].layout.right = m_mixStreamInfos[i]->layout.right;
    }

    mixStreamConfig.nInputStreamCount = size;
    strcpy(mixStreamConfig.szOutputStream, m_myMixStreamID.toStdString().c_str());
    mixStreamConfig.bOutputIsUrl = false;
    mixStreamConfig.nOutputWidth = width;
    mixStreamConfig.nOutputHeight = height;
    mixStreamConfig.nOutputFps = m_pAVSettings->GetFps();
    mixStreamConfig.nOutputBitrate = m_pAVSettings->GetBitrate();

    // 调用 SDK 接口更新混流配置到后台
    LIVEROOM::MixStream(mixStreamConfig, m_mixStreamRequestSeq++);
}

3.2 系统架构图

混流系统架构图如下所示:
Windows 视频直播功能实现流程_第5张图片
4、实现结构图

单主播、多主播、混流模式的实现区别如下:

  • 单主播模式:flag = ZEGO_SINGLE_ANCHOR,推流端推流到 CDN,拉流端从 CDN 拉流。

  • 多主播模式:flag = ZEGO_JOIN_PUBLISH,推流端推流到 Zego 媒体服务器,拉流端从 CDN 拉多路单流。

  • 混流模式:flag = ZEGO_MIX_STREAM,推流端推流到 Zego 媒体服务器,拉流端有两个选择:可以从 CDN
    拉多路单流,也可以从 CDN 拉一路混流。

数据流结构图如下:
Windows 视频直播功能实现流程_第6张图片

你可能感兴趣的:(技术)