时间: 2020-09-03 00:08:26 人气: 2356 评论: 0
进入2018年最火的新鲜事物无疑就是“直播答题”了,动辄上百万的奖金更是吸引了大量用户的参与。一场直播动辄几百万的奖金,每人可以分到几十元甚至百万元,越来越多的人希望用自己的智商赚点零花钱。直播答题有多火?
多个直播平台服务器多次遭到宕机。实际上,几百万人一同在线的确会带给服务器不小的压力,更何况是新上线的
App,他们或许还没有想到自己会火得这么快。
近期很多直播答题app出现了个人账号上显示奖金额数不对、在线用户无法进入游戏、技术故障导致游戏被迫临时
取消等情况。某视频平台还出现了系统将正确答案判定错误的情况,导致百万人被迫中止游戏。隔几天就来一次的
技术故障除了说明App准备不足外,也从侧面反映了这类游戏的火爆程度。为了让众多公司及开发者尽快赶上风口浪尖,腾讯云直播团队也是第一时间上线了“在线知识竞技解决方案”。
iOS平台(ipa) Android平台(apk) Obs Studio 定制版本(exe)
创建房间即可体验主持人一端的效果;进入房间即可体验观众端的效果。
iPhone 平台的 Demo 采用了企业签名方式,请先到“设置-通用-设备管理”里,添加信任证书。
Demo 仅作演示之用,用来展示腾讯云的技术能力,不代表最终产品形态,接入请仔细阅读文档。
这种体验方式是直接使用腾讯云改造的 Obs Studio 进行推流:
// iOS 示例代码 [_answerPusher sendMessage:[mesg dataUsingEncoding:NSUTF8StringEncoding]];
//Android 示例代码 mTXLivePusher.sendMessage(questionInfo.getBytes("UTF-8"));
消息接收的接入方案可以参考我们的接入文档(iOS平台 | Android平台)
总结一下:方案二跟方案一的最大区别就在于题目的扩散方式,方案二的核心思路是让题目先通过IM通道快速送达观众端APP,在观众端先缓存下来,等待播放器通知了预期的 NTP 时间戳之后,再把题目显示出来。
方案一和方案二都可以实现“音-话-题”完美同步,但是相比于这种体验上的小优化,APP的扩散能力则是更加重要的。小程序恰恰提供给了APP可以病毒式传播的能力。
腾讯云 SDK 已经默认打包在微信版本中,并以 <live-player> 标签的形式对外提供,如果:
那么就可以实现非常理想的播放延迟,并能够让各观众之间的延迟误差在1s以内,虽然无法做到“音-话-题”分毫不差(在微信打包视频云 SDK 的时候,在线答题模式还没有兴起,所以不支持在音视频流中夹带消息),但也能达到几乎可以媲美APP的体验效果。
剩下的事情,就是通过小程序的 websocket 通道,或者我们的 webim 解决方案,向小程序发题就可以了。
联系我们开通腾讯云 直播服务,如果您时间比较急,可以 400 客服电话我们加急审核。
想要简单获取一个推流URL,可以参考文档:快速获得地址。 想要了解推流地址和直播间ID的关系,可以参考文档:后台自动拼装。 想要了解如果保护自己的推流地址不被盗用,可以参考文档:防盗链签名。
播放URL和推流URL是一一映射的,映射规则参考下面的图示您就能明白了:
请务必使用 FLV 格式的播放地址,RTMP在高并发场景下容易出现卡顿问题。
如果您是使用APP进行推流,直接参考文档(iOS | Android)。
如果您是使用Obs推流,请注意以下几个重要设置项:
一般演播台的接入方式有两种:OBS Studio 推流或者编码盒推流,这两种推流工具均有比较成熟的设置接口。建议将 GOP(也叫关键帧间隔)设置为 1s ,这样可以让观众端的延迟差异非常小。
x264 的 gop 设置对编码效率的影响不是很大,但对延迟的影响非常大:gop越大,服务器缓存越多。由于 SDK 的延迟修正需要一个修正时间,如果 gop 太大,对于刚进入的观众会有很大的影响 。
如下是Obs Studio 设置关键帧间隔的图示:
推荐推荐配置 | 分辨率 | 视频比特率 | 帧率 | 声道数 | 采样率 | 音频比特率 |
|---|---|---|---|---|---|---|
优先画质 | 540x960 | 1000kbps | 25 | 1 | 48k | 72kbps |
优先成本 | 360x640 | 600kbps | 20 | 1 | 48k | 72kbps |
//iOS源码 TXLivePlayConfig *config = [[TXLivePlayConfig alloc] init]; TXLivePlayer *player = [[TXLivePlayer alloc] init]; // //开启消息接受,收不到消息的话就是没打开这个(默认:关) config.enableMessage = YES; // //设置延迟平衡点为1s(考虑到云端和推流端引入的延迟,实际延迟为2s多,SDK推流:2s, obs推流:3-4秒) config.bAutoAdjustCacheTime = YES; config.maxAutoAdjustCacheTime = 1; config.minAutoAdjustCacheTime = 1; config.cacheTime = 1; config.connectRetryCount = 3; config.connectRetryInterval = 3; config.enableAEC = NO; //先setConfig再startPlay [player setConfig:config];
//Android源码 mTXLivePlayConfig = new TXLivePlayConfig(); mTXLivePlayer = new TXLivePlayer(context); // //开启消息接收,收不到消息的话就是没打开这个(默认:关) mTXLivePlayConfig.setEnableMessage(true); // //设置延迟平衡点为1s(考虑到云端和推流端引入的延迟,实际延迟为2s多,SDK推流:2s, obs推流:3-4秒) mTXLivePlayConfig.setAutoAdjustCacheTime(true); mTXLivePlayConfig.setCacheTime(1.0f); mTXLivePlayConfig.setMaxAutoAdjustCacheTime(1.0f); mTXLivePlayConfig.setMinAutoAdjustCacheTime(1.0f); // //先setConfig再startPlay mTXLivePlayer.setConfig(mTXLivePlayConfig); 请务必使用 FLV 格式的播放地址,RTMP在高并发场景下容易出现卡顿问题。
可靠性评估 有些客户可能会担心:音视频通道本身不太稳定,那么万一卡了或者视频数据丢了,会不会导致观众端看不到题目。
所以,解决这个问题的办法就是每秒钟(gop设置为1s的前提条件下)发送一次题目消息,相同的题号在观众端剔重,这样就可以避免偶尔的音视频卡顿对题目到达可靠性的影响。
在我们的推流 APP Demo 以及定制版本的 Obs Studio 中,我们以 json 格式将题目组织成一段buffer,并将其夹在音视频流中送出去。
获取到这个buffer以后,您就可以将其解析出来,并完成对应的 UI 展示。如果你需要调整json格式以支持更多的定制型,请修改源码或者联系我们。
// iOS 的代码 -(void) onPlayEvent:(int)EvtID withParam:(NSDictionary *)param { [self asyncRun:^{ if (EvtID == PLAY_EVT_GET_MESSAGE) { dispatch_async(dispatch_get_main_queue(), ^{ //抛到主线程,避免线程安全问题 if ([_delegate respondsToSelector:@selector(onPlayerMessage:)]) { [_delegate onPlayerMessage:param[@"EVT_GET_MSG"]]; } }); } }]; }
//Android 示例代码 mTXLivePlayer.setPlayListener(new ITXLivePlayListener() { @Override public void onPlayEvent(int event, Bundle param) { if (event == TXLiveConstants.PLAY_ERR_NET_DISCONNECT) { roomListenerCallback.onDebugLog("[AnswerRoom] 拉流失败:网络断开"); roomListenerCallback.onError(-1, "网络断开,拉流失败"); } else if (event == TXLiveConstants.PLAY_EVT_GET_MESSAGE) { String msg = null; try { msg = new String(param.getByteArray(TXLiveConstants.EVT_GET_MSG), "UTF-8"); roomListenerCallback.onRecvAnswerMsg(msg); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } });
由于腾讯云 PAAS 的定位,所以对于跟客户业务绑定比较紧密的答题和支付系统,我们就不涉及了,需要您来参与开发。
这里普遍采用的方案是:将客户的答案以 HTTP(S) 请求方式汇总到答题服务器上,只是实现过程需要注意解决瞬间高并发的请求压力。
有客户可能会问,IM系统是否适合用来答题,这里目前看是不适合的,因为 IM 系统的主要能力在于消息扩散,而答题的主要目标是信息的收拢。
一般题目出来一段时间以后,就会进入闭题状态。这时,答题系统会将结果进行统计汇总,并将汇总结果下发给观众。
如果是用我们的定制版 Obs Studio 扩散结果,搭一个简单的服务器,并提供一个 http 接口,然后按照我们约定的 json 格式跟 Obs 进行题目、答案以及人数的通讯。从而实现题目和答案的分发。
这部分协议由于文档篇幅限制,暂时不放在文档中详细列出,有需要的话请 400 电话联系我们。
同方案一,不再赘述。
参考方案一,与方案一不同之处在于,推流 URL 需要额外增加一个参数:
加注NTP时间戳 在推流 URL 之后添加参数 &txAddTimestamp=1 参数,服务器会每隔1s向您的直播流中打入一个带有国际标准时间(误差在 100ms 以内)的 SEI 时间戳。如果您使用我们的播放器播放此视频流,那么就会每隔一秒钟收到一次代表当前画面 NTP 时间的消息通知。
同方案一,不再赘述。
同方案一,不再赘述。
参考方案一,与方案一不同之处在于,此时获取的message不再是一个json,而是一个8字节的64位时间戳。
long timeStamp = byteArrayToInt(param.getByteArray(TXLiveConstants.EVT_GET_MSG)); /** * 将8字节的byte数组转成一个long值 */ public static long byteArrayToInt(byte[] byteArray) { byte[] a = new byte[8]; int i = a.length - 1, j = byteArray.length - 1; for (; i >= 0; i--, j--) {// 从b的尾部(即int值的低位)开始copy数据 if (j >= 0) a[i] = byteArray[j]; else a[i] = 0;// 如果b.length不足4,则将高位补0 } // 注意此处和byte数组转换成int的区别在于,下面的转换中要将先将数组中的元素转换成long型再做移位操作, // 若直接做位移操作将得不到正确结果,因为Java默认操作数字时,若不加声明会将数字作为int型来对待,此处必须注意。 long v0 = 技术沙龙 教程文章 热点综合