Windows下视频直播场景主要有单主播直播、多主播(连麦)直播和混流直播等,主要结构及流程如下图所示:
请注意:
本文主要介绍如何使用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 调用时序图
单主播直播 API 调用时序图如下所示:
2、多主播直播
2.1 功能介绍
多主播直播是主播与观众连麦,使观众也成为主播的互动功能。多主播直播的推流、拉流流程,同单主播基本一致,不同点在于,主播发布直播时,需要声明 flag 为 ZEGO_JOIN_PUBLISH。
2.2 系统架构图
3.1 功能介绍
混流直播模式下,Zego 服务器会将多路单独的音视频流混成一路音视频流。混流直播的推流、拉流流程,同单主播基本一致,不同点在于:
主播发布直播时,需要声明 flag 为 ZEGO_MIX_STREAM。
观众可以使用 mixStreamID 选择拉一路混流数据,也可使用 streamID 分别拉多路单流数据,取决于用户需求,SDK不做强制要求。
混流直播模式下,支持主播与观众连麦。
对于上述第 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 系统架构图
单主播、多主播、混流模式的实现区别如下:
单主播模式:flag = ZEGO_SINGLE_ANCHOR,推流端推流到 CDN,拉流端从 CDN 拉流。
多主播模式:flag = ZEGO_JOIN_PUBLISH,推流端推流到 Zego 媒体服务器,拉流端从 CDN 拉多路单流。
混流模式:flag = ZEGO_MIX_STREAM,推流端推流到 Zego 媒体服务器,拉流端有两个选择:可以从 CDN
拉多路单流,也可以从 CDN 拉一路混流。