产品
存储与大数据
人工智能
计算与网络
SaaS基础设施
视联物联与通信
研发运维
专有部署
存储与大数据
存储服务
文件存储 QHDFS
具有标准HDFS访问协议、卓越性能的分布式文件系统
对象存储 OBS
稳定、安全、可靠的云存储服务
人工智能
视觉分析
视图计算 VEC
云边融合 AI赋能的智能视图计算
内容审核
内容审核 CM
图片审核|文本审核|音频审核|视频审核
人脸与人体识别
人脸人体识别 FHR
人脸识别|人体识别|人脸比对|摔倒检测
OCR识别
OCR识别 OCR
卡证识别|通用文本识别|车牌识别
图像技术
图像技术 IA
面向图片场景提供的多种人工智能技术
AI市场
模型市场 MaaS
图片、音频、视频等多场景的算法模型
计算与网络
网络加速
内容分发网络 CDN
安全、稳定、低延时的分发加速服务
P2P内容分发网络 PCDN
利用闲置资源而构建的低成本高品质CDN
SaaS基础设施
基础组件
统一身份认证 IAM
统一的身份认证、授权管理
视频应用
幕印企业学堂 MuYin
企业培训|内容付费|知识营销
易讲教室直播 YiJiang
视频技术与传统教室融合
企业工具
亿方云企业网盘 FangCloud
在线编辑、文件管理、知识管理
三六零天御加固保 JiaGu
提供安全可靠的加固防护产品及服务
视联物联与通信
视频应用
视频直播 LIVE
大规模实时转码、低延时的直播服务
视频点播 VOD
视频流畅播放服务
音视频通话 RTC
便捷的跨平台实时音视频互动直播服务
媒体处理 MPC
简洁的云媒体转码及内容合成处理服务
视频工具
视频工具 SDK
视频剪辑SDK | 播放SDK
物联网平台
帝视物联网 IOT
低延时、海量存储的物联网视频监控服务
企业物联网平台
设备管理|设备接入|规则引擎|应用开发
生活物联网平台
针对消费级智能设备的物联网平台
边缘计算
边云协同操作系统
应用开发
云短信 SMS
融合三网,安全可信的短信服务
研发运维
研发效能
兼容性测试 OpenTest
提供数百款TOP机型的云测服务
真机租用 RentPhone
远程真机租用,流畅体验如手机在手
iOS预审 iOSPre
智能扫描、分析、筛查ios审核的被拒风险点
专有部署
云计算
360云计算管理平台 Stack
规划、建设、运维一体的云计算解决方案
大数据
奇麟大数据 QiLin
企业级一站式大数据平台
容器服务
360容器管理平台 Container
可对外私有化的容器云平台
AI开发平台
360AI开发平台专有版 Prophet
全流程机器学习开发平台
更多产品,敬请期待
解决方案
产品解决方案
行业解决方案
产品解决方案
视频
通用直播解决方案
短视频解决方案
公共语音房聊天室解决方案
物联网
儿童手表音视频通话
云端NVR解决方案
数据上云
通用存储解决方案
IoT设备
AI+IPC解决方案
智能门锁解决方案
安防传感解决方案
智能网关解决方案
个护健康解决方案
账号体系
360用户帐号体系解决方案
行业解决方案
智慧城市
智慧社区解决方案
智慧交通解决方案
电商视频解决方案
电商视频解决方案
电商平台收款解决方案
教育
在线教育解决方案
互动课堂解决方案
全屋智能
智慧公寓解决方案
智慧酒店解决方案
家庭智能解决方案
智慧安防解决方案
医疗
健康看护解决方案
智能制造
工业物联网解决方案
游戏
游戏音视频解决方案
更多解决方案,敬请期待
帮助支持
技术社区
关于我们
控制台
登录
注册
互动直播
云直播
产品文档
常见问题
API文档
云点播
产品文档
快速入门
API文档
CDN
产品文档
API文档
云存储
产品文档
SDK手册
API文档
互动直播
产品文档
API文档
操作指南
SDK管理
播放SDK
上传SDK
剪辑SDK
媒体处理
产品文档
API文档
帝视
产品文档
API文档
操作指南
支付平台
产品列表
产品文档
渠道接入解析
内容审核
产品文档
API文档
OCR识别
产品文档
API文档
人脸与人体识别
产品文档
API文档
SSL证书
产品说明
购买指南
电子签章
产品介绍
接入流程
云短信
接口文档
物联网平台
产品简介
快速入门
幕印
产品介绍
OBS使用教程
生活物联网平台
产品简介
快速入门
图片处理
产品介绍
接口文档
产品说明
快速入门
控制台操作指南
API文档
通知接口
SDK参考
连麦SDK
Android开发文档
iOS开发文档
Android版本说明
Android开发文档
播放SDK
首页
>
开发者中心
>
互动直播
>
SDK参考
>
连麦SDK
>
Android开发文档
### Android互动直播开发文档 ### Android互动直播SDK简单介绍 智汇云以SDK形式提供互动直播,可以帮助开发者快速实现互动直播能力。SDK包含jar包、so库、demo及开发文档。开发者可参考文档或demo,将jar包和so库加入APP的工程中,完成相关配置,调用相关的API即可完成Android的互动直播服务。 ## 功能说明: | **系统特性** | **支持内容** | |----------------|---------------------------------------------------------------------| | **系统版本** | **Android 4.0及以上** | | **流媒体协议** | **私有协议** | | **硬件特性** | **armeabi-v7a、arm64-v8a** | | **参数设置** | **互动时的分辨率、码率、帧率等** | | **编码方式** | **H264** | | **设备驱动** | **摄像头、麦克风、耳机** | ### SDK集成 #### 下载SDK sdk下载链接:[https://zyun.360.cn/developer](https://live.360.cn/index/sdkdownload) - jar > qhvc_tools_sdk.jar > qhvc_interactive_sdk.jar - so > armeabi-v7a/libtranscore.so > armeabi-v7a/libapm-agora-plugin.so > armeabi-v7a/libagora-rtc-sdk-jni.so > armeabi-v7a/libzegoavkit.so demo下载链接:[https://github.com/360livecloud/android_demo.git](https://github.com/360livecloud/android_demo.git) #### 配置说明 将qhvc_tools_sdk.jar、qhvc_interactive_sdk.jar放到工程libs目录下,在build.gradle中配置: ``` dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') } ``` 将libtranscore.so、libapm-agora-plugin.so、libagora-rtc-sdk-jni.so、libzegoavkit.so放到工程src/main/jniLibs/armeabi-v7a/目录下,在build.gradle中配置: ``` android { defaultConfig { ndk { // 设置支持的CPU架构,目前只支持armeabi-v7a架构(该架构兼容armeabi、arm64-v8a、x86、x86_64架构) abiFilters 'armeabi-v7a' } } } ``` > 若qhvc_tools_sdk.jar、libtranscore.so已在接入其他模块时引入,请保留高版本,版本号可通过`Stats.getVersion()`获取。 在build.gradle中配置第三方依赖库: ``` dependencies { compile 'com.squareup.okhttp3:okhttp:3.2.0' } ``` #### 权限配置 ``` <uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.RECORD_VIDEO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.BROADCAST_STICKY"/> <uses-feature android:glEsVersion="0x00020000" android:required="true"/> <uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> ``` #### 混淆规则 ``` -keep class com.qihoo.livecloud.** { <fields>; <methods>; } -keep class com.qihoo.videocloud.** { <fields>; <methods>; } -keep class net.qihoo.videocloud.** { <fields>; <methods>; } -keep class io.agora.** { <fields>; <methods>; } -keep class com.zego.** { <fields>; <methods>; } -keep class com.justalk.** { <fields>; <methods>; } ``` #### SDK初始化 需要调用`QHVCSdk.getInstance().init()`,接口说明如下: appId(也叫businessId)是为业务分配的业务ID(appId获取地址:登录[视频云官网](https://zyun.360.cn/)-控制台-SDK-应用管理-新建应用【见下图】);version为业务端APP的版本号;machineId为设备唯一标识;uid为业务方用户标识,只要保证唯一即可。  [点此查看应用ID](https://zyun.360.cn/console/sdk/application) > 对appId和channelID这两个参数的引入,在设计之初目的是为了每个业务有独立的ID,通过appId来获取云端的一些参数控制,特别是视频缓冲策略、P2P行为、硬解码黑白名单以及解码库类型;channelID更多的为数据统计打点的唯一标注,可以通过云点播和云直播的服务标识来获取,以此获取播放数据反馈。UserID的设计是为了业务方和视频云唯一的沟通桥梁,只要保持唯一即可,一般为用户ID的加密字符串,通过UserID可以排查到一个用户的级别的失败日志; ``` QHVCSdkConfig.Builder builder = new QHVCSdkConfig.Builder(this) .setAppId("businessId") .setAppVersion("version") .setMachineId("machineId") .setUserId("uid"); QHVCSdk.getInstance().init(builder.build()); ``` #### APPID合法性验证 需要调用 `public int validityCheck(String appId, String authorization, long authTime, int randomNum, final QHVCAppAuth.ResultCallback<String> callback)`,接口说明如下: 合法性验证需要用到appId, Access Key(简称AK)和Secret Key(简称SK)。AK、SK获取地址: 登录[视频云官网](https://zyun.360.cn/)-用户中心-秘钥管理【见下图】。 只有appId、Access Key以及Secret Key相匹配,才能通过鉴权,否则将无法正常使用SDK。  [点此查看秘钥](https://zyun.360.cn/console/usercenter/accesskey) ==注意:此接口必须在启动APP后120秒内调用,否则将无法正常使用SDK。== appId使用和SDK初始化时同样的内容,callback可以用来监听合法性验证结果。 计算authorization时需要使用AK、SK以及当前系统的时间戳和随机数。 **为了保证AK、SK的安全,请业务接入时,务必把AK和SK存储在服务端,并且把authorization的计算也放在服务端来做。** 计算authorization的示例代码如下: ``` private void videocloudValidCheck() { int randomNum = new Random(100000000).nextInt(); //随机数 long authTime = System.currentTimeMillis() / 1000; //时间戳 (unix时间戳(10位)) //TODO 为了保证ak、sk的安全,请业务接入时,务必把AK和SK存储在服务端,并且把authorization的计算也放在服务端来做。 String authorization = getServerAuthorization(appId, AK, SK, randomNum, authTime); QHVCSdk.getInstance().validityCheck(appId, authorization, authTime, randomNum, new QHVCAppAuth.ResultCallback<String>() { @Override public void onSuccess(String data) { Logger.i(TAG, "validityCheck onSuccess, data: " + data); } @Override public void onFailed(int errCode, String errMsg) { Logger.e(TAG, "validityCheck onFailed, errCode: " + errCode + ", errMsg: " + errMsg); } }); } private String getServerAuthorization(String appID, String ak, String sk, int randNum, long authTime) { HashMap<String, String> mapParams = new HashMap<>(); mapParams.put("appid", appID); String strParams = getParams(mapParams); String paramSign = makeParamSign(strParams, randNum); String authString = ak + "\n" + authTime + "\n" + randNum + "\n" + paramSign; String encryptString = null; try { encryptString = encryptHMAC(authString, sk); } catch (Exception e) { e.printStackTrace(); } Logger.i(TAG, "apiAuth(), encryptString: " + encryptString); return ak + ":" + encryptString; } private String getParams(Map<String, String> mapParams) { String strParams; if (mapParams == null || mapParams.isEmpty()) { strParams = ""; } else { StringBuilder sbParams = new StringBuilder(); Object[] key_arr = mapParams.keySet().toArray(); Arrays.sort(key_arr);/*key升序排列*/ for (Object key : key_arr) { String value = mapParams.get(key); if (!TextUtils.isEmpty(value)) { sbParams.append("&").append(key).append("=").append(value); } } strParams = sbParams.substring(1); } return strParams; } private String makeParamSign(String param, int randNum) { return MD5.encryptMD5(MD5.encryptMD5(param) + randNum); } public String encryptHMAC(String data, String key) throws Exception { final String KEY_MAC = "HmacSHA1"; SecretKey secretKey = new SecretKeySpec(key.getBytes(), KEY_MAC); Mac mac = Mac.getInstance(KEY_MAC); mac.init(secretKey); byte[] rawHmac = mac.doFinal(data.getBytes()); return Base64.encodeToString(rawHmac, Base64.DEFAULT); } ``` 相关错误码: ``` int AUTH_OK = 1; //鉴权成功 int AUTH_FAILED = -11001; //鉴权未通过(鉴权失败) int AUTH_NOT_INVOKED = -11002; //未调用鉴权接口 ``` #### 调试 为便于接入时定位问题,可以在开发版本中打开logcat日志,播放相关TAG为QHVCPlayer。 ``` DebugUtils debugUtils = new DebugUtils(); debugUtils.setWriteLogs(true) .setPlayerLogLevel(Constants.ELogLevel.LOG_LEVEL_DEBUG) .setTransportLogLevel(Constants.ELogLevel.LOG_LEVEL_DEBUG); QHVCSdkConfig.Builder builder = new QHVCSdkConfig.Builder(this) .setAppId("appId") .setAppVersion("version") .setUserId("uid"), .setDebugUtils(debugUtils); QHVCSdk.getInstance().init(builder.build()); ``` ### 业务流程图 以下假设第一个进入直播间的用户为主播,之后进入直播间的用户为嘉宾。 #### 主播创建互动直播  #### 嘉宾加入互动直播  ### 接口说明 #### 初始化互动直播类 可参考demo工程中com.qihoo.videocloud.interactbrocast.InteractActivity、 com.qihoo.videocloud.interactbrocast.main.WorkerThread。 ``` mInteractEngine = QHVCInteractKit.getInstance(); mInteractEngine.setPublicServiceInfo(channelId, appKey, userSign); ``` #### 加载直播引擎并设置回调 ``` mInteractEngine.loadEngine(roomId, userId, caluSessionForTest(), optionInfo, InteractCallback.getInstance()); ``` InteractCallback:继承SDK回调类QHVCEngineEventHandler,用于回调SDK返回的消息,具体请查看Demo中InteractCallback类。 #### 设置互动直播参数 ``` //设置频道模式 mInteractEngine.setChannelProfile(QHVCInteractiveConstant.CHANNEL_PROFILE_LIVE_BROADCASTING); //开启视频模式 if (talkType != InteractConstant.TALK_TYPE_AUDIO) { mInteractEngine.enableVideo(); } //设置是否使用硬编码 if (InteractConstant.CURR_VIDEO_CAPTURE == InteractConstant.VideoCapture.RECORD_GPU) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { mInteractEngine.useHardwareEncoder(true); } } //设置视频编码属性 boolean swapWidthAndHeight = (orientation == Constants.EMode.EMODE_PORTRAIT) ? true : false; mInteractEngine.setVideoProfile(vProfile, swapWidthAndHeight); //设置用户模式 mInteractEngine.setClientRole(cRole); ``` #### 加入频道房间 ``` mInteractEngine.joinChannel(); ``` #### 开启本地预览 ``` mInteractEngine.setupLocalVideo(view,QHVCInteractConstant.RENDER_MODE_HIDDEN, uid); mInteractEngine.startPreview(); ``` #### 绑定远程用户和显示视图 ``` mInteractEngine.setupRemoteVideo(surface,QHLiveCloudInteractEngine.RenderMode.RENDER_MODE_HIDDEN, uid, ""); ``` #### 切换摄像头 ``` mInteractEngine.switchCamera(); ``` #### 静音/取消静音 ``` mInteractEngine.muteLocalAudioStream(); ``` #### 切换音频输出方式:扬声器或听筒 ``` mInteractEngine.setEnableSpeakerphone(); ``` #### 暂停/恢复发送本地视频流 ``` mInteractEngine.muteLocalVideoStream(); ``` #### 离开房间 ``` mInteractEngine.leaveChannel(); ``` #### 释放回收 ``` //释放互动直播引擎 mInteractEngine.releaseEngine(); //资源回收处理 mInteractEngine.destroy(); ``` 更多详细接口请参考[API接口文档](https://live.360.cn/developer/doc?page_id=72&item_id=5)及DEMO。 ### 高级功能 #### 双流模式 为减小视频延迟、节约带宽和计算资源、提升用户体验,智汇云互动直播SDK支持双流模式,默认为单流模式,业务方需调用API接口手动开启并设置小流参数。 ``` /** * 使用双流/单流模式 * * @param enabled 指定双流或者单流模式 true:双流 false:单流(默认) * @return 0成功,非0失败 */ QHVCInteractiveKit.getInstance().enableDualStreamMode(boolean enabled); ``` ``` /** * 设置小流的参数(仅在开启双流模式时有效) * 小流分辨率需要和大流的成比例,比如大流 360*640,小流可以设置 180*320,小流不要设置太大。 * 注: 请确保在joinChannel之前调用。 * * @param width 视频的宽度 * @param height 视频的宽度 * @param fps 帧率 * @param bitrate 码率 (单位:kbps) * @return 0成功,非0失败 */ QHVCInteractiveKit.getInstance().setLowStreamVideoProfile(int width, int height, int fps, int bitrate); ``` ``` /** * 视频大小流切换, 该方法指定接收远端用户的视频流大小。使用该方法可以根据视频窗口的大小动态调整对应视频流的大小,以节约带宽和计算资源。本方法调用状态将在下文的SDK 默认收到视频小流,节省带宽。如需使用视频大流,调用本方法进行切换。 * * @param uid 用户ID * @param streamType 设置视频流大小。QHVCInteractConstant.VIDEO_STREAM_HIGH (0): 视频大流;QHVCInteractConstant.VIDEO_STREAM_LOW (1): 视频小流 * @return 0成功,非0失败 */ QHVCInteractiveKit.getInstance().setRemoteVideoStream(String uid, int streamType); ``` #### 合流 ``` /** * n+m路转推(n路分流+m路合流),合流信息预设接口,请确保要在joinChannel之前调用。 * * @param mixStreamConfig 合流设置 * @return 0成功,非0失败 */ QHVCInteractiveKit.getInstance().setMixStreamInfo(QHVCInteractiveMixStreamConfig mixStreamConfig, QHVCInteractiveConstant.StreamLifeCycle lifeCycle); ``` ``` /** * 更新合流的视频布局(即画中画布局) * * @param mixStreamInfos 布局信息,请确保设置所有的视频流,包括主播的视频流。 * @return 0成功,非0失败 */ QHVCInteractiveKit.getInstance().setVideoCompositingLayout(QHVCInteractiveMixStreamRegion[] mixStreamInfos); ``` ### 错误码说明 调用mInteractEngine.loadEngine()后,SDk的错误信息会通过InteractCallback.onError(int errType, int errCode)函数回调,详细调用方法见[加载直播引擎并设置回调](#加载直播引擎并设置回调)。 errType 值含义: | **值** | **对应消息** | |--------|----------------------------------------| | 3601 | 加入频道错误 | | 3602 | 连麦中错误 | | 3603 | 加载引擎错误 | errCode 值含义: | **值** | **对应消息** | |--------|----------------------------------------| | 4001 | 参数缺失 | | 4101 | 服务内部异常 | | 4102 | 请求已过期 | | 4103 | 签名验证失败 | | 4201 | sname 不存在 | | 4202 | sname 未开通服务 | | 4302 | 加入房间失败 | | 4303 | 退出房间失败 | | 4304 | 获取房间信息失败 | | 4305 | 更新成员属性失败 | | 4306 | 更新房间属性失败 | | 4307 | 心跳更新失败 | | 4308 | 房间已存在 | | 4309 | sname 不可用 | | 4310 | 生成连麦信息失败 | | 4311 | 没有可用的连麦配置 | 其他错误码请参考SDK *com.qihoo.livecloud.interact.api.QHVCInteractiveConstant.ErrorCode* 的定义。
即刻开始使用
只需完成注册与实名认证,即可体验我们的贴心服务
立即使用
请您联系我们
邮箱
g-zyun@360.cn
电话
4000052360
小安提醒您
试用小安,请确保该账户已通过智汇云实名认证
前往认证中心>>
1对1免费
咨询智汇云专属顾问
为您量身定制产品解决方案
您的姓名 :
手机号 :
公司名称(选填) :
相关产品 :
留言内容 :
需求描述
产品建议
其他
提交
登录后才可以留言哦
立即登录
去注册账号