有奖捉虫:办公协同&微信生态&物联网文档专题 HOT

连麦方案介绍

连麦方案演示

一般情况观众连麦流程如下:
连麦前:主播使用 RTC 地址推流,观众使用 CDN 地址进行拉流观看即可。
连麦时:观众切换为 RTC 地址推送自己的音视频,使用 RTC 地址播放主播音视频流,此时主播使用 RTC 地址播放观众的音视频流。
连麦后:观众切换为 CDN 地址拉流观看,主播停止播放观众音视频流。
下面是 MLVB-API-Example Demo 的演示效果。

演示图示

直播前
连麦操作
连麦中
主播
?
?
?
?
?
?
?
?
?
连麦观众和观众
?
?
?
?
?
?
?
?
?
?
?
主播
连麦观众
?
?
?
?
?
?
?
?
主播端(手机 A)
连麦观众(手机 B)
普通观众(手机 C)
?
?
?
?
?
?
?
?
?
?

连麦功能实现

如下示意图,用户 A 是主播,B 和 C 都是观众,如果观众 B 要与 主播 A 连麦,需要做的事情非常简单:
观众 B:启动trtc://协议推流,播放流也从 CDN 切到超低延迟的trtc://协议。
主播 A:开始播放观众 B 的流,同时发起混流指令,把 A 和 B 的内容合成一路。
观众 C:无需变化,继续 CDN 播放即可,只不过会看到混流后的连麦画面。
?
?
?

1. 主播 RTC 推流

主播 A 开始推流,调用V2TXLivePusher组件开始主播 A 的推流。URL 拼装方案请参见 如何拼装 URL
java
Objective-C
小程序
V2TXLivePusher pusher = new V2TXLivePusherImpl(this, V2TXLiveMode.TXLiveMode_RTC);
pushURLA= "trtc://cloud.tencent.com/push/streamid?sdkappid=1400188888&userId=A&usersig=xxx";
pusher.startPush(pushURLA);
V2TXLivePusher *pusher = [[V2TXLivePusher alloc] initWithLiveMode:V2TXLiveMode_RTC];
NSString *pushURLA = @"trtc://cloud.tencent.com/push/streamid?sdkappid=1400188888&userId=A&usersig=xxx";
[pusher startPush:pushURLA];
// wxml
<live-pusher url="{{pusher.url}}" />
// js
import TRTC from 'trtc-wx-sdk'
this.TRTC = new TRTC(this)
this.TRTC.createPusher({})
data: { pusher: {} }
this.setData({
pusher: this.TRTC.enterRoom({
userID: 'Anchor',
sdkAppID: 000000,
userSig: 'xxxxxx',
roomId: 123456
}),
}, () => {
trtc.getPusherInstance().start() // 开始推流
})
}

2. 观众 CDN 拉流

所有观众观看主播 A 直播,调用V2TXLivePlayer开始播放主播 A 的流。URL 拼装方案请参见 如何拼装 URL
java
Objective-C
小程序
V2TXLivePlayer player = new V2TXLivePlayerImpl(mContext);
/**
?
* 这里使用 CDN 拉流,支持 FLV、HLS、WebRTC 协议,任选一种协议。FLV、HLS 等标准协议价格更合理,WebRTC 快直播能够提供更低延迟的互动体验。
* playURLA= "http://3891.liveplay.myqcloud.com/live/streamidA.flv";
* playURLA= "http://3891.liveplay.myqcloud.com/live/streamidA.hls";
* playURLA= "webrtc://3891.liveplay.myqcloud.com/live/streamidA"
*/
player.startLivePlay(playURLA);
V2TXLivePlayer * player = [[V2TXLivePlayer alloc] init];
/**
* 这里使用 CDN 拉流,支持 FLV、HLS、WebRTC 协议,任选一种协议。FLV、HLS 等标准协议价格更合理,WebRTC 快直播能够提供更低延迟的互动体验。
* NSString *playURLA= @"http://3891.liveplay.myqcloud.com/live/streamidA.flv";
* NSString *playURLA= @"http://3891.liveplay.myqcloud.com/live/streamidA.hls";
* NSString *playURLA= @"webrtc://3891.liveplay.myqcloud.com/live/streamidA"
*/
[player setRenderView:view];
[player startLivePlay:playURLA];
// wxml
<live-player src="{{ url }}" />
/**
* 这里使用 CDN 拉流,支持 FLV、HLS、WebRTC 协议,任选一种协议。FLV、HLS 等标准协议价格更合理,WebRTC 快直播能够提供更低延迟的互动体验。
* playURLA= "http://3891.liveplay.myqcloud.com/live/streamidA.flv";
* playURLA= "http://3891.liveplay.myqcloud.com/live/streamidA.hls";
* playURLA= "webrtc://3891.liveplay.myqcloud.com/live/streamidA"
*/
this.setData({ ulr: playURLA })

3. 观众发起连麦

其中观众 B 调用V2TXLivePusher发起推流(后续会称呼为连麦观众 B)。
java
Objective-C
小程序
V2TXLivePusher pusher = new V2TXLivePusherImpl(this,V2TXLiveMode.TXLiveMode_RTC);
pushURLB= "trtc://cloud.tencent.com/push/streamid?sdkappid=1400188888&userId=B&usersig=xxx";
pusher.startPush(pushURLB);
V2TXLivePusher *pusher = [[V2TXLivePusher alloc] initWithLiveMode:V2TXLiveMode_RTC];
NSString *pushURLB = @"trtc://cloud.tencent.com/push/streamid?sdkappid=1400188888&userId=B&usersig=xxx";
[pusher startPush:pushURLB];
// wxml
<live-pusher url="{{pusher.url}}" />
// js
import TRTC from 'trtc-wx-sdk'
this.TRTC = new TRTC(this)
this.TRTC.createPusher({})
data: { pusher: {} }
this.setData({
pusher: this.TRTC.enterRoom({
userID: 'audience',
sdkAppID: 000000,
userSig: 'xxxxxx',
roomId: 123456
}),
}, () => {
trtc.getPusherInstance().start() // 开始推流
})
}

4. 进入连麦状态

主播 A 调用V2TXLivePlayer使用 RTC 协议拉取放连麦观众 B 的流。
java
Objective-C
小程序
V2TXLivePlayer player = new V2TXLivePlayerImpl(mContext);
playURLB= "trtc://cloud.tencent.com/play/streamid?sdkappid=1400188888&userId=A&usersig=xxx&appscene=live";
player.startLivePlay(playURLB);
V2TXLivePlayer * player = [[V2TXLivePlayer alloc] init];
NSString* playURLB = @"trtc://cloud.tencent.com/play/streamid?sdkappid=1400188888&userId=A&usersig=xxx&appscene=live";
[player setRenderView:view];
[player startLivePlay:playURLB];
// wxml
<live-player src="{{player.src}} mute-audio={{ false }}" mute-vedio="{{ false }}" />
// js
import TRTC from 'trtc-wx-sdk'
this.TRTC = new TRTC(this)
data: {
player: {}
}
// 远端用户推送视频
this.TRTC.on(TRTC_EVENT.REMOTE_VIDEO_ADD, (event) => {
const { player } = event.data
this.setData({ player: player })
})
// 远端用户推送音频
this.TRTC.on(TRTC_EVENT.REMOTE_AUDIO_ADD, (event) => {
const { player } = event.data
this.setData({ player: player })
})
同时,连麦观众 B 调用V2TXLivePlayer切换至 RTC 协议,开始播放主播 A 的流。
java
Objective-C
小程序
V2TXLivePlayer player = new V2TXLivePlayerImpl(mContext);
playURLA= "trtc://cloud.tencent.com/play/streamid?sdkappid=1400188888&userId=B&usersig=xxx&appscene=live";
player.startLivePlay(playURLA);
V2TXLivePlayer * player = [[V2TXLivePlayer alloc] init];
NSString* playURLA = @"trtc://cloud.tencent.com/play/streamid?sdkappid=1400188888&userId=B&usersig=xxx&appscene=live";
[player setRenderView:view];
[player startLivePlay:playURLA];
// wxml
<live-player src="{{player.src}} mute-audio={{ false }}" mute-vedio="{{ false }}" />
// js
import TRTC from 'trtc-wx-sdk'
this.TRTC = new TRTC(this)
data: {
player: {}
}
// 远端用户推送视频
this.TRTC.on(TRTC_EVENT.REMOTE_VIDEO_ADD, (event) => {
const { player } = event.data
this.setData({ player: player })
})
// 远端用户推送音频
this.TRTC.on(TRTC_EVENT.REMOTE_AUDIO_ADD, (event) => {
const { player } = event.data
this.setData({ player: player })
})
此时主播 A 和 连麦观众 B 即可进入超低延时的实时互动场景中。

5. 连麦成功后,进行混流

为了保证观众可以看到连麦观众 B 的画面,这里主播 A 需要发起一次混流操作。也就是将主播 A 自己和连麦观众 B,混合成一路流。观众可以在一路流上看到主播和连麦观众进行互动。A 调用 setMixTranscodingConfig 接口启动云端混流,调用时需要设置音频相关的参数,例如 音频采样率 audioSampleRate音频码率 audioBitrate声道数 audioChannels 等。 如果您的业务场景中也包含视频,需同时设置视频相关的参数,例如 视频宽度 videoWidth视频高度 videoHeight视频码率 videoBitrate视频帧率 videoFramerate 等。
示例代码
java
Objective-C
小程序
V2TXLiveDef.V2TXLiveTranscodingConfig config = new V2TXLiveDef.V2TXLiveTranscodingConfig();
// 设置分辨率为 720 × 1280, 码率为 1500kbps,帧率为 20FPS
config.videoWidth = 720;
config.videoHeight = 1280;
config.videoBitrate = 1500;
config.videoFramerate = 20;
config.videoGOP = 2;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 2;
config.outputStreamId = null;
config.mixStreams = new ArrayList<>();
?
// 主播摄像头的画面位置
V2TXLiveDef.V2TXLiveMixStream local = new V2TXLiveDef.V2TXLiveMixStream();
local.userId = "localUserId";
local.streamId = null; // 本地画面不用填写 streamID,远程需要
local.x = 0;
local.y = 0;
local.width = videoWidth;
local.height = videoHeight;
local.zOrder = 0; // zOrder 为 0 代表主播画面位于最底层
config.mixStreams.add(local);
?
// 连麦者的画面位置
V2TXLiveDef.V2TXLiveMixStream remoteA = new V2TXLiveDef.V2TXLiveMixStream();
remoteA.userId = "remoteUserIdA";
remoteA.streamId = "remoteStreamIdA"; // 本地画面不用填写 streamID,远程需要
remoteA.x = 400; //仅供参考
remoteA.y = 800; //仅供参考
remoteA.width = 180; //仅供参考
remoteA.height = 240; //仅供参考
remoteA.zOrder = 1;
config.mixStreams.add(remoteA);
?
// 连麦者的画面位置
V2TXLiveDef.V2TXLiveMixStream remoteB = new V2TXLiveDef.V2TXLiveMixStream();
remoteB.userId = "remoteUserIdB";
remoteB.streamId = "remoteStreamIdB"; // 本地画面不用填写 streamID,远程需要
remoteB.x = 400; //仅供参考
remoteB.y = 800; //仅供参考
remoteB.width = 180; //仅供参考
remoteB.height = 240; //仅供参考
remoteB.zOrder = 1;
config.mixStreams.add(remoteB);
?
// 发起云端混流
pusher.setMixTranscodingConfig(config);
V2TXLiveTranscodingConfig *config = [[V2TXLiveTranscodingConfig alloc] init];
// 设置分辨率为 720 × 1280, 码率为 1500kbps,帧率为 20FPS
config.videoWidth = 720;
config.videoHeight = 1280;
config.videoBitrate = 1500;
config.videoFramerate = 20;
config.videoGOP = 2;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 2;
config.outputStreamId = nil;
?
// 主播摄像头的画面位置
V2TXLiveMixStream *local = [[V2TXLiveMixStream alloc] init];
local.userId = @"localUserId";
local.streamId = nil; // 本地画面不用填写 streamID,远程需要
local.x = 0;
local.y = 0;
local.width = videoWidth;
local.height = videoHeight;
local.zOrder = 0; // zOrder 为 0 代表主播画面位于最底层
?
// 连麦者的画面位置
V2TXLiveMixStream *remoteA = [[V2TXLiveMixStream alloc] init];
remoteA.userId = @"remoteUserIdA";
remoteA.streamId = @"remoteStreamIdA"; // 本地画面不用填写 streamID,远程需要
remoteA.x = 400; //仅供参考
remoteA.y = 800; //仅供参考
remoteA.width = 180; //仅供参考
remoteA.height = 240; //仅供参考
remoteA.zOrder = 1;
?
// 连麦者的画面位置
V2TXLiveMixStream *remoteB = [[V2TXLiveMixStream alloc] init];
remoteB.userId = @"remoteUserIdB";
remoteB.streamId = @"remoteStreamIdB"; // 本地画面不用填写 streamID,远程需要
remoteB.x = 400; //仅供参考
remoteB.y = 800; //仅供参考
remoteB.width = 180; //仅供参考
remoteB.height = 240; //仅供参考
remoteB.zOrder = 1;
?
//设置混流 streams
config.mixStreams = @[local,remoteA,remoteB];
?
// 发起云端混流
pusher.setMixTranscodingConfig(config);
?
参考文档:服务端 REST API 混流方案 /document/product/647/16827?
注意:
发起云端混流后
不设置 outputStreamId,SDK 会执行默认逻辑,即房间里的多路流会混合到该接口调用者的视频流上,也就是 A + B => A
设置 outputStreamId,SDK 会将房间里的多路流混合到您指定的直播流 ID 上,也就是 A + B => C。
推荐取值默认值,不进行设置,即房间里的多路流会混合到该接口调用者的视频流上。

6. 结束连麦

注意:
RTC 连麦基于实时音视频 TRTC 实现,因此连麦结束后,需停止所有连麦参与者(主播和观众)的 RTC 推流和拉流,否则会产生额外的 TRTC 在房时长费用,具体实现请参考下方代码。
主播 A 停止连麦,先调用V2TXLivePusher组件的 setMixTranscodingConfig 并设置为 null 从而停止混流。然后调用V2TXLivePlayer 的 stopPlay停止播放连麦观众 B 的流。
java
Objective-C
小程序
// 停止混流
pusher.setMixTranscodingConfig(null);
// 停止播放连麦观众 B 的流
player.stopPlay();
// 停止混流
[pusher setMixTranscodingConfig: nil];
// 停止播放连麦观众 B 的流
[player stopPlay];
// wxml
<live-player src="{{ player.url }}" />
// 停止播放连麦观众 B 的流
this.setData({ player: {} })
连麦观众 B 停止连麦,先调用V2TXLivePusher组件的 stopPush 停止自身推流。然后停止播放主播 A 的 RTC 流。如需继续以观众身份留在房中观看,请按照步骤2,进行 CDN 拉流。
java
Objective-C
小程序
// 停止推流
pusher.stopPush();
// 停止播放主播 A 的 RTC 流
player.stopPlay();
// 停止推流
[pusher stopPush];
// 停止播放主播 A 的 RTC 流
[player stopPlay];
// wxml
<live-pusher url="{{ pusher.url }}" />
<live-player src="{{ player.src }}" />
// 停止播放主播 A 的 RTC 流
this.setData({ pusher: {}, player: {} })

常见问题

1. 为什么使用V2TXLivePusher&V2TXLivePlayer接口时,同一台设备不支持使用相同 streamid 同时推流和拉流,而 TXLivePusher&TXLivePlayer可以支持?

当前V2TXLivePusher&V2TXLivePlayer腾讯云 TRTC 协议实现,其基于 UDP 的超低延时的私有协议,考虑到用户的具体使用场景,不支持同一台设备,使用相同的 streamid,一边推超低延时流,一边拉超低延时的流

2. V2TXLivePusher&V2TXLivePlayer 如何设置音质或者画质呢?

我们有提供对应的音质和画质的设置接口,具体可以参考 设置画面质量

3. V2TXLivePusher#startPushV2TXLivePlayer#startLivePlay收到错误码:-5代表什么意思?

-5表示由于许可证无效,因此无法调用API,对应的枚举值为:V2TXLIVE_ERROR_INVALID_LICENSE

4. RTC连麦方案的时延性有可以参考的数据吗?

主播连麦的延时 < 200ms,主播和观众的延时在 100ms - 1000ms。

5. RTC 推流成功后,使用 CDN 拉流一直提示404?

检查一下是否有开启实时音视频服务的旁路直播功能,基本原理是 RTC 协议推流后,如果需要使用 CDN 播放,RTC 会在后台服务中旁路流信息到 CDN 上。

6. 如何避免额外计费?

及时主动停止推流(V2TXLivePusher 的 stopPush)和拉流(V2TXLivePlayer 的 stopPlay)。只要推流或拉流在进行中,就会正常计费。

7.观众连麦支持哪些平台?

观众连麦支持 iOS、Android、小程序和 Flutter 端。


http://www.vxiaotou.com