做一个电商直播App,跟上这波双十一

又快到一年一度的双十一了。淘宝直播一姐曾在去年双十一,一个人卖出了3.3亿的销售额,创造了行业的销售神话。最近淘宝直播一哥李佳琦,也成为了热门话题。近两年,很多电商平台开始关注起直播互动电商。在直播中,也可以增加互动,例如在直播过程中,抛出限量优惠商品,以题目的形式实时发送抢购的消息给观众。于是我们做了一个简单的Demo,效果如视频所示。

为了让主播可以快速输入,我们还通过合作伙伴搜狗的技术,为应用增加了语音识别与转写功能。主播通过语音输入题目,能更方便地发送给观众。观众收到题目后,屏幕会显示弹框。

1.1

功能拆解

  • 需支持互动直播功能,且直播音视频与文字消息、题目可以同步到达观众端。

  • 需要支持文字消息、题目消息的发送,并能稳定支持海量高并发。

  • 需要语音识别功能,语音识别结果需要主播确认后通过消息系统发送。

  • 观众收到题目信息时需要主动弹窗,给用户选择结果。

1.2

实现方案

在这个场景下,首先要保证音视频直播与互动消息可以做到同步,也就是说,当主播说出“我的天啊~买它~!”的时候,购物链接、题目等形式的消息需要与这句话同时发送到观众端。那就就需要采用基于 UDP 传输的实时音视频互动方案。

另一方面,文字、题目等消息不仅需要做到实时,还需要保证能抗住高并发。所以在这里我们采用实时消息 SDK。实时消息 SDK在传输方面,采用分布式架构、多机房多路保活机制、智能优化路径,在其它节点失效时自动转移,选择最优节点路径传输,服务可靠。同时,弹性可伸缩架构,支持单频道百万并发,轻松应对直播答题、电商互动直播、大班课等高并发场景。同时,支持动态快速扩容,可以灵活应对用户场景的快速增长。

  • 通过声网 Agora 视频互动直播 SDK实现直播功能。

  • 通过搜狗知音开放平台来实现语音识别功能。

  • 题目信息也是一种实时消息,就像文字消息、弹幕一样,可用实时消息通道进行传输。在这里我们统一用声网 Agora 实时消息 SDK 来实现。


2.1

实现视频直播

一个简单的视频直播 Demo 按以下几个步骤就可以实现了,可以找几个 Android 设备run一下看看效果。

Step1 SDK集成
SDK 支持 maven 依赖,在 build.gradle 的 dependencies 模块中加一行就行:


   
   
  1. dependencies {

  2. ...

  3. implementation 'io.agora.rtc:full-sdk:2.8.1'

  4. }

Step2 直播引擎创建

声网SDK 有个重要的类——RtcEngine,负责直播功能管理,提供了上/下线、状态监听、音/视频设置等 API。创建引擎时,需要用到 APP_ID ,大家可以在console.agora.io -->项目管理页面下获取 。


   
   
  1. privateRtcEngine mRtcEngine;

  2. try{

  3. mRtcEngine = RtcEngine.create(context, LiveDefine.APP_ID,

  4. mRtcEventHandler);

  5. mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);

  6. mRtcEngine.enableAudio(); // 开启音频功能

  7. mRtcEngine.enableVideo(); // 开启视频功能

  8. } catch(Exception e) {

  9. e.printStackTrace();

  10. }

Step3 直播View关联
在一个直播建中,参与者的角色有主播和观众,关联View时有些许区别。ANCHOR_UID为主播用户id,主播端关联View时为自己的用户id,观众端关联view时为观看的主播的用户id。


   
   
  1. SurfaceView surface = RtcEngine.CreateRendererView(this);

  2. // 主播端View关联

  3. mRtcEngine.setClientRole(Constants.CLIENT_ROLE_BROADCASTER);

  4. mRtcEngine.enableLocalAudio(true); // 主播端需要打开本地音频

  5. mRtcEngine.setupLocalVideo(newVideoCanvas(surface,

  6. VideoCanvas.RENDER_MODE_HIDDEN, ANCHOR_UID)); // 主播端设置的是本地video

  7. mRtcEngine.startPreview(); //主播需要开启视频预览

  8. // 观众端View关联

  9. mRtcEngine.setClientRole(Constants.CLIENT_ROLE_AUDIENCE);

  10. mRtcEngine.enableLocalAudio(false); // 观众端不需要打开本地音频

  11. mRtcEngine.setupRemoteVideo(newVideoCanvas(surface,

  12. VideoCanvas.RENDER_MODE_HIDDEN, ANCHOR_UID)); // 观众端设置的是远端即主播video

Step4 加入房间
加入房间时,参数token为当前登录账户对应的token,应用自己管理,测试时可以传null。第二个参数为频道id,也是由应用自己管理的。第三个参数为频道名称。最后一个参数为当前登录的账户id。


   
   
  1. mRtcEngine.joinChannel("", CHANNEL_ID, "CHANNEL_NAME", uid);

Step5 离开房间


   
   
  1. // 主播端离开

  2. mRtcEngine.setupLocalVideo(null);

  3. mRtcEngine.stopPreview();

  4. mRtcEngine.leaveChannel();

  5. // 观众端离开

  6. mRtcEngine.setupRemoteVideo(null);

  7. mRtcEngine.leaveChannel();

2.2

消息功能

直播房间消息功能可以说是相对基础而简单的了,我们选用的是声网实时信息SDK,这是一个独立的工具类SDK,声网将实时消息功能解耦出来,可以给各个场景提供消息支持。群聊实时消息可参考如下步骤:

Step1 依赖配置


   
   
  1. dependencies {

  2. ...

  3. implementation 'io.agora.rtm:rtm-sdk:1.0.1'

  4. }

Step2 消息引擎创建


   
   
  1. // APP_ID同视频互动SDK保持一致即可

  2. privateRtmClient mRtmClient;

  3. mRtmClient = RtmClient.createInstance(context, LiveDefine.APP_ID, listener);

Step3 房间消息初始化
创建一个消息频道前需要调一次登录操作,第一个参数为应用账户token,第二个参数为账户标识。


   
   
  1. mRtmClient.login("", userId,

  2. newResultCallback<Void>() {

  3. @Override

  4. publicvoid onSuccess(Void aVoid) {

  5. Log.d(TAG, "rtmClient login success");

  6. }

  7. @Override

  8. publicvoid onFailure(ErrorInfo errorInfo) {

  9. Log.d(TAG, "rtmClient login fail : "+ errorInfo);

  10. }

  11. });

创建消息频道,CHANNEL_ID是一个标识,可以和直播频道不一致,但是建议保持一致:


   
   
  1. RtmChannel mRtmChannel;

  2. RtmChannelListener rtmListener = newRtmChannelListener(){

  3. @Override

  4. publicvoid onMessageReceived(RtmMessage var1, RtmChannelMember var2){

  5. // 收到消息,自己发送的消息也会有该方法回调,可以通过RtmChannelMember判断发送消息的人是不是自己,如果是不处理本次消息即可。

  6. }

  7. @Override

  8. publicvoid onMemberJoined(RtmChannelMember var1){

  9. // 有用户加入,可用来做用户上线消息处理

  10. }

  11. @Override

  12. publicvoid onMemberLeft(RtmChannelMember var1){

  13. // 有用户离开,可用来做用户离线消息处理

  14. }

  15. };

  16. mRtmChannel = mRtmClient.createChannel(CHANNEL_ID,

  17. rtmListener );;

Step4 发送消息


   
   
  1. RtmMessage rtmMessage = mRtmClient.createMessage();

  2. rtmMessage.setText(msg);

  3. mRtmChannel.sendMessage(rtmMessage, callback);

Step5 退出消息频道
可在退出直播房间时,调用该方法。


   
   
  1. mRtmChannel.release();

2.3

语音识别

首先也是需要注册账户并创建应用,详见搜狗知音文档中心,实现可参考如下步骤:

Step1 初始化
调用init方法初始化


   
   
  1. // 以下信息从知音平台申请获得

  2. privatestaticfinalString BASE_URL = "api.zhiyin.sogou.com";

  3. privatestaticfinalString APP_ID = "";

  4. privatestaticfinalString APP_KEY = "";

  5. privateSogoSpeech mSogouSpeech;

  6. privateDefaultAudioSource mAudioSource;

  7. privateOnSogouAsrListener mListener;

  8. publicvoid init(Context context) {

  9. ZhiyinInitInfo.Builder builder = newZhiyinInitInfo.Builder();

  10. ZhiyinInitInfo initInfo = builder.setBaseUrl(BASE_URL).setUuid(UUID).setAppid(APP_ID).setAppkey(APP_KEY).create();

  11. SogoSpeech.initZhiyinInfo(context, initInfo);

  12. SogoSpeechSettings settings = SogoSpeechSettings.shareInstance();

  13. settings.setProperty(SpeechConstants.Parameter.ASR_ONLINE_AUDIO_CODING_INT,

  14. 1);

  15. settings.setProperty(SpeechConstants.Parameter.ASR_ONLINE_VAD_ENABLE_BOOLEAN,

  16. false);

  17. settings.setProperty(SpeechConstants.Parameter.ASR_ONLINE_VAD_LONGMODE_BOOLEAN,

  18. true); // 长时间ASR

  19. settings.setProperty(Parameter.ASR_ONLINE_LANGUAGE_STRING,

  20. ASRLanguageCode.CHINESE); // 也支持英文ASR ASRLanguageCode.ENGLIS

  21. mSogouSpeech = newSogoSpeech(context);

  22. mSogouSpeech.registerListener(mSpeechEventListener);

  23. mAudioSource = newDefaultAudioSource(newAudioRecordDataProviderFactory(context));

  24. mAudioSource.addAudioSourceListener(mAudioSourceListener);

  25. }

  26. privateEventListener mSpeechEventListener = newEventListener() {

  27. @Override

  28. publicvoid onEvent(String eventName, String param, byte[] data, int offset, int length, Object extra) {

  29. if(TextUtils.equals(SpeechConstants.Message.MSG_ASR_ONLINE_LAST_RESULT,

  30. eventName)) {

  31. if(null!= mListener) {

  32. mListener.onSogouAsrResult(param);

  33. }

  34. stopTransform();

  35. }

  36. }

  37. @Override

  38. publicvoid onError(String errorDomain, int errorCode, String errorDescription, Object extra) {

  39. // 9002 用户主动取消

  40. if(9002!= errorCode && null!= mListener) {

  41. mListener.onSogouAsrResult("");

  42. }

  43. stopTransform();

  44. }

  45. };

  46. privateIAudioSourceListener mAudioSourceListener = newIAudioSourceListener() {

  47. @Override

  48. publicvoid onBegin(IAudioSource iAudioSource) {

  49. Log.d(TAG, "AudioSource onBegin");

  50. mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_START, "", null, 0, 0);

  51. }

  52. @Override

  53. publicvoid onNewData(IAudioSource audioSource, Object dataArray, long packIndex, long sampleIndex, int flag) {

  54. finalshort[] data = (short[]) dataArray;

  55. mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_RECOGIZE, "", data, (int) packIndex, 0);

  56. }

  57. @Override

  58. publicvoid onEnd(IAudioSource audioSource, int status, Exception e, long sampleCount) {

  59. Log.d(TAG, "AudioSource onEnd");

  60. mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_STOP, "", null, 0, 0);

  61. }

  62. };

  63. publicinterfaceOnSogouAsrListener{

  64. void onSogouAsrResult(String result);

  65. }

Step2 开始语音识别


   
   
  1. publicvoid startTransform(OnSogouAsrListener listener) {

  2. mListener = listener;

  3. mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_CREATE,

  4. null, null, 0, 0);

  5. newThread(mAudioSource, "audioRecordSource").start();

  6. }

Step3 停止语音识别
正常情况下不需要调用该方法,在EventListener 回调中已经调用过该方法了,为了确保状态正常也可以在退出房间时,手动调用一次。


   
   
  1. publicvoid stopTransform() {

  2. mListener

  3. = null;

  4. if(null!= mAudioSource) {

  5. mAudioSource.stop();

  6. }

  7. }

我们已经将这个 Demo上传至 Github,大家可以直接下载使用。
Android版本:https://github.com/AgoraIO-Community/Live-Shop/tree/master/Android
iOS版本:https://github.com/AgoraIO-Community/Live-Shop/tree/master/iOS

如果大家有任何疑问,可以点击「阅读原文」,在 RTC 开发者社区 Agora 版块中提问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值