【开发者的减法日常】使用声网 [跨频道媒体流转发] 实现 [语音房 - 单人 - 跨房PK] 功能 2

我正在参加「声网 RTE 开发者社区」征文活动 https://www.shengwang.cn/cn/community/discussion/43/25573



跟声网同学QA整理

1] Q : 文档上说, src_uid 应该设置成 0 , dest_uid 要设置成当前用户的 uid,
但是声网代码demo上面 src_uid 和 dest_uid 设置的都是 当前用户的uid

A : 3.x按照文档为准, 就是说 src_uid 设置成 0 .
等到升级到 4.x 的时候, 需要再去跟声网沟通如何设置.

2] 对src_token 和 dest_token 的理解如下 :
src_token : 当前用户所在频道的token (这个是给加入本频道的观众机器人使用的,这个token是需要服务端提前生成好,然后给到客户端)

注意 : // 注意 sourceChannelToken 和用户加入源频道时的 Token 不一致,需要用 uid = 0 和源频道名重新生成
dest_token : 需要转发的频道的token (给加入要转发的频道的观众机器人使用的,这个token时需要服务端提前生成好,然后给到客户端).


3] Q : 如何控制对方静音?
A : 一种简单的解决方案是, A房间给B房间发信令, 告知B房间主播不进行转发操作.

4] Q : 那么主播在调用 stopChannelMediaRelay 和 startChannelMediaRelay 是否会有延迟感?
A : 实测得出,A频道主持人通过信令 去控制B频道发流者的stop和 startChannelMediaRelay,生效延迟应该在1s左右(不包含信令传输时延),主观感知不是很明显.

5] Q : 文档上说, 频道转发最多支持4个频道, 如果转发第5个频道时, 会发生什么?
A : 新版本SDK已经没有这个限制了, 在V3.7.0.2(我们APP正在使用的版本), 已经放开到 64 个频道了.

6] Q :转发机器人 token 过期怎么处理?
A : 当前跨频道连麦机器人的token还不支持renew token,
所以当前可能需要咱们在生成token的时候把过期时间设置的稍微久一些(声网机器人token最大可以设置24小时过期)。

7] Q :如何显示正在说话中的, 对方主播的麦位水波纹?

A : 依旧使用 用户音量提示回调 onAudioVolumeIndication(final AudioVolumeInfo[] speakerArray, final int totalVolume) 远端回调最大声音共三个,跨房转发的主播依旧会回调这个方法。


8]Q :用户杀死APP之后, 然后重启APP, 此时需要重新进行转发API的调用吗?

注意 : 重新启动APP,然后进入之前的频道时, 会重走joinChannel流程.

我自己的实测结论如下 :

1) 如果杀死APP之后, 快速回房(1分钟内), 不重新调用startChannelMediaRelay方法, 发现之前的机器人还在工作, 但是在1分钟之后, 就会自动失效了.

2)如果杀死APP之后, 快速回房(1分钟内), 重新调用startChannelMediaRelay方法, 在调用startChannelMediaRelay之前, 接收转发的房间还会使用之前的机器人转发,

调用startChannelMediaRelay之后, 接收转发的房间, 会出现5秒以内的中断, 然后就可以正常接收转发了.

声网的建议 :

1] 对于快速杀死APP, 重新回房的场景, 不需要重新生成机器人token, 可以使用之前的机器人token;

2] 需要在重新回房时, 重新调用 startChannelMediaRelay方法, 创建新的转发机器人;


9]Q :如果主播的token过期, 对于跟该主播绑定的机器人, 是否有影响?

A : 没有影响


10]Q :如果想要使用 [频道转发] 功能, 那么建议使用声网哪个版本的SDK呢?

A : 建议使用 V3.7.1之后的版本, 该版本SDK有对 [跨频道媒体转发] 做优化

该版本优化点如下:


11]Q : “依赖的是主播和机器人之间的一条TCP的心跳连接。” 这个tcp链接是跨房pk场景特有的心跳,还是单个房间场景下,
每个观众和推流主播中已经存在的心跳链接?进而的问题是,如果这个心跳是在普通观众和主播间也存在的,那在单个房间场景里,如果出现观众侧大面积心跳失败的话,是否也可以有类似的回调机制给到主播端,进行底层的重新进房重试?
A : 这个tcp链接是跨房pk场景,主播和机器人直接的特有心跳.

12] Q :频道转发失败, 有没有给服务端的回调?
A : 目前没有


13] Q :客户端按照文档要求执行了leaveChannel / joinChannel 时,是否对应的服务器端回调能够区分出是正常的进房还是深度规避导致的进房(如果声网不能区分的话,是否支持传递我们客户端到声网给我们服务器端的回调里,携带自定义参数来区分这种场景)。如果都不支持的话,服务器端就要review一个人重复进房和重复出房的逻辑,包括反作弊事件的影响。

A : 都没有, 我们服务器端无法区别正常进房和深度规避进房,并且客户端调用 joinChannel 无法透传自定义参数.


14] Q :的开发注意事项中有 "在成功调用 startChannelMediaRelay 方法后,如果想再次调用该方法,
必须先调用 stopChannelMediaRelay 方法退出当前的转发状态" 这个建议, 我们是否可以简化为,
在每次调用 startChannelMediaRelay之前都固定调用 stopChannelMediaRelay呢?
A : 实测了一下,startChannelMediaRelay之前 无脑stop一下,没有发现什么报错和问题,可以这么做.


15] Q : 对于 [深度规避策略] 中, 如果出现 ( state==RELAY_STATE_FAILURE && (code == RELAY_ERROR_SERVER_NO_RESPONSE || code == RELAY_ERROR_SERVER_CONNECTION_LOST))

的概率很小, 那么是否跟另一个声网的网络异常场景一样呢?

网络异常场景如下 :

当 SDK 收到 onConnectionStateChanged(CONNECTION_STATE_RECONNECTING, CONNECTION_CHANGED_INTERRUPTED)

* 后连续 20 分钟无法重新加入频道时,会报告该状态并停止重连

A : 跟SDK重连这个不是一个链路,也不是相同机制,二者直接对比也不具备参考性哈.


16] Q : 调用 leaveChannel 之后, 要等待 (public void onLeaveChannel(RtcStats stats)) 方法异步执行成功之后,

再进行下一步动作吗?(下一步是调用 joinChannel), 还是可以调用leaveChannel之后, 立刻调用 joinChannel.

A : 这个是可以在leaveChannel之后,立刻调用 joinChanne的哈,这个虽然leaveChannel是异步方法,但是sdk内部会在leavechannel完成后再进行joinchannel的动作。


17] Q : 客户端如何判断 [本次转发成功] ?
A : 在 onChannelMediaRelayStateChanged 收到 (state == RELAY_STATE_RUNNING) 时, 既可以判定本次转发成功.


18] Q : 进行转发请求的用户A, 怎么能够确定 接收转发的用户B ,已经收到了A转发过去的流呢?
A : 用户A可以通过监听 onChannelMediaRelayEvent(RELAY_EVENT_PACKET_SENT_TO_DEST_CHANNEL(4):SDK 开始向目标频道发送数据包), 来确定.

注意 : 这个事件在一次转发流程中, 不会重复回调.

下面是一次完整频道转发请求, 到成功的log输出 :
onChannelMediaRelayStateChanged --> state == 1 , code == 0

onChannelMediaRelayEvent -> 1

onChannelMediaRelayEvent -> 2

onChannelMediaRelayEvent -> 6

onChannelMediaRelayEvent -> 5

onChannelMediaRelayEvent -> 3

onChannelMediaRelayStateChanged --> state == 2 , code == 0

onChannelMediaRelayEvent -> 4

onChannelMediaRelayEvent -> 11



19] Q : 客户端调用 pauseAllChannelMediaRelay()方法, 怎么确定该方法执行成功或者失败呢?

A :


20] Q : 服务器生成uid = 0的机器人, 那么这个机器人跟用户是一对一绑定的吗?

A :在声网频道内, 每次有一个主播需要转发行为时, 都会生成一对跟他独立绑定的机器人(src 和 dest).
如果在当前频道内, 一个主播需要向多个房间进行转发操作. 那么会生成3个机器人(本房间1个, 目标房间2个),
需要生成3个token ,src_token只有一个(根据uid=0生成), dest_token2个.
本房间机器人(uid = 0), 只是负责接收其他dest机器人转发过来的流而已.


21] 一个场景, 用户先进行A频道的转发,之后又进行另一个频道B的转发,

那么此时客户端可以直接调用 updateChannelMediaRelay 就行了, 不需要先调用 stopChannelMediaRelay.


22] Q : 如果加入多个频道, 是否会出现个别频道失败.比如转发4个频道, 其中一个频道失败了, 错误码怎么返回.
A :不会出现这种情况, 声网服务器进行保证.


23] 设置uid=0, 生成token时, 声网会随机生成一个uid, 而token中是包含着这个uid的.


24] Q : 如何在水晶球上, 识别一个用户是 “机器人”

A : OS是Linux, NET是LAN, SDK是4.0.0_media_relay


25] Q : A用户调用startChannelMediaRelay()转发给B, 然后A用户收到onChannelMediaRelayStateChanged(state=RELAY_STATE_RUNNING(2))回调之后,
立刻调用 pauseAllChannelMediaRelay(), 那么B用户有可能先听到A用户的声音, 然后立刻又听不到了吗?
或者客户端 可以串行调用 startChannelMediaRelay 和 pauseAllChannelMediaRelay 吗? 声网会顺序执行吗?
A :

1] 如果调用 startChannelMediaRelay之后立刻调用 pauseAllChannelMediaRelay, 会直接报错;
2] 如果调用 startChannelMediaRelay之后, 然后等到onChannelMediaRelayStateChanged(state=RELAY_STATE_RUNNING(2))回调之后再调用 pauseAllChannelMediaRelay, 就会 "漏音"
结论 : 客户端对于 主播快速回房的场景, 如果判断对方主播禁麦了当前主播, 那么就不能直接调用 startChannelMediaRelay进行转发操作了, 而是要等到 对方主播解麦自己时, 再去调用 startChannelMediaRelay, 否则会发生 "漏音”.


26] Q : 有 "跨频道连麦机器人" 支持 renew token 的计划嘛?
A :这点刚刚和产品同学沟通了,这个争取在今年q1的需求里带上


27] Q : 如果转发流过程中网络不触达,那等待中的状态.是哪个回调哪个状态,对应等待中的粒度到达什么程度.

A :https://docs.agora.io/cn/live-streaming-premium-legacy/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_channel_event_handler.html#a8fa397338b21ff94720edb1d312ff0db 咱们看一下这边的推流状态和错误码,针对部分异常情况可能需要咱们进行重推


28] Q :如果转发过程中,推流身份被登出,那么对应的机器人会自动登出吗?或者说token过期.

A :推流身份退出,对应机器人会自动退出.


29] Q : 如果我们直接杀死APP,未调用退出流转发,机器人发现主播连接断开,也会自动退出的是吗?
A :是的, 但是会有1分钟的延迟.
注意 : 这里会有一种特殊场景, A / B建立了频道转发, A直接杀死APP了, 然后重启APP之后回到之前的频道, 那么B还会听见A频道的转发声音1分钟, 1分钟之后,会自动断开.

附一个实测结果 :

1) 如果杀死APP之后, 快速回房(1分钟内), 不重新调用startChannelMediaRelay方法, 发现之前的机器人还在工作, 但是在1分钟之后, 就会自动失效了.
2) 如果杀死APP之后, 快速回房(1分钟内), 重新调用startChannelMediaRelay方法, 在调用startChannelMediaRelay之前, 接收转发的房间还会使用之前的机器人转发, 调用startChannelMediaRelay之后, 接收转发的房间, 会出现5秒以内的中断, 然后就可以正常接收转发了.



30] Q : A,B两个频道.分别只有一个主播, A主播把自己转发给B频道

问:此时是A频道多一个转发机器人,还是B频道多一个机器人.机器人的作用是把谁转发给谁.

A :https://docs.qq.com/doc/DVmZyUFJDR1ZoZ0dx这个文档里有详细的说明哈, 也可以参考下面这个图

就是A主播发起跨频道连麦,会在本频道加入一个观众机器人负责接收A主播的流,然后在目标频道加入一个推流机器人把前面观众机器人接收到的流转发出来。
同时B主播也发起跨频道,机器人作用同理



31] Q : 请问, 对于异常退出APP(比如说崩溃), 然后快速回到APP的场景下, 可以复用之前生成的机器人token吗?还是需要重新生成? 因为会重新进行 joinChannel .

A : 只要token还在有效期内,使用原来的token没有问题.


32] Q : “依赖的是主播和机器人之间的一条TCP的心跳连接。” 这个tcp链接是跨房pk场景特有的心跳,还是单个房间场景下,每个观众和推流主播中已经存在的心跳链接?进而的问题是,如果这个心跳是在普通观众和主播间也存在的,那在单个房间场景里,如果出现观众侧大面积心跳失败的话,是否也可以有类似的回调机制给到主播端,进行底层的重新进房重试?

A : 这个tcp链接是跨房pk场景,主播和机器人直接的特有心跳哈


32] Q : 请问如果同时转发多个频道.那这个回调(onChannelMediaRelayEvent)应该是怎么样子的呀.A同时转发给BCDEF频道这种.
A : 这个回调是这样的,即使是同时跨多频道,在发起的时候,回调都只会是一组。服务端会保证所以目标频道行为的一致性

onChannelMediaRelayEvent -> 1

onChannelMediaRelayEvent -> 2

onChannelMediaRelayEvent -> 5

onChannelMediaRelayEvent -> 6

onChannelMediaRelayEvent -> 3

onChannelMediaRelayEvent -> 4

onChannelMediaRelayEvent -> 11


33] 如果在 onChannelMediaRelayStateChanged 回调中收到 state == RELAY_STATE_FAILURE , code == RELAY_ERROR_SERVER_NO_RESPONSE 时,

注意 : RELAY_ERROR_SERVER_NO_RESPONSE(2) 错误代码是有2层含义的

1) 服务器无响应(这个无响应可能是网络,也可能其他原因)

2) AppId没有开通权限



推荐阅读
相关专栏
开发者实践
182 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。