产品
基础服务
视频云
人工智能
物联网
区块链
第三方服务
存储服务
云存储
网络加速
CDN
PCDN
动态加速(DCDN)
全站加速(WSA)
奇盾
企业应用
云短信
SSL证书
电子签章
支付系统
帐号服务平台
视频应用
云直播
云点播
音视频通信RTC
媒体处理
视频工具
剪辑SDK
播放SDK
云剪辑
推流SDK
内容安全
图片审核
视频审核
文本审核
音频审核
OCR识别
卡证识别
通用文本识别
车牌识别
人脸与人体识别
人脸实名认证
人脸识别
人体识别
图像技术
以图定位
AI开发平台
机器学习平台 Prophet Pro
AI能力定制平台 Prophet Lite
物联网视频
帝视
物联网平台
设备接入
设备管理
规则引擎
应用开发
边缘计算
区块链通用服务
QBaaS
开测平台
兼容性测试
真机租用
运营
消息推送
企业应用
企业直播-小虎盟
企业培训/在线教育/知识付费
教学直播-易讲
视频技术与传统教室融合
智能监控-小安
云边融合, AI使能的智能视频监控
解决方案
通用解决方案
行业解决方案
视频
通用直播解决方案
短视频解决方案
公共语音房聊天室解决方案
物联网
儿童手表音视频通话
云端NVR解决方案
数据上云
通用存储解决方案
IoT设备
摄像机
门锁
安防传感
网关
个护健康
账号体系
360用户帐号体系解决方案
智慧城市
智慧社区
智慧交通
电商
电商视频解决方案
电商平台收款解决方案
教育
在线教育解决方案
互动课堂解决方案
全屋智能
智慧公寓
智慧酒店
家庭智能
智慧安防
医疗
健康看护
智能制造
工业物联网
游戏
游戏音视频解决方案
帮助支持
关于我们
技术社区
控制台
登录
注册
SDK管理
云直播
产品文档
常见问题
API文档
云点播
产品文档
快速入门
API文档
CDN
产品文档
API文档
云存储
产品文档
SDK手册
API文档
互动直播
产品文档
API文档
操作指南
SDK管理
播放SDK
上传SDK
剪辑SDK
媒体处理
产品文档
API文档
帝视
产品文档
API文档
操作指南
帐号服务平台
整体介绍
SDK文档
支付平台
产品列表
产品文档
渠道接入解析
内容审核
产品文档
API文档
OCR识别
产品文档
API文档
人脸与人体识别
产品文档
API文档
SSL证书
产品说明
购买指南
电子签章
产品介绍
接入流程
云短信
接口文档
物联网平台
产品简介
快速入门
小虎盟
产品介绍
OBS使用教程
Android互动直播
开发文档
版本说明
Windows互动直播
开发文档
版本说明
iOS互动直播
Android推流
开发文档
版本说明
iOS推流
iOS推流SDK开发文档
Android上传SDK
Android上传SDK接入文档
Android上传SDK版本说明
IOS上传SDK
iOS上传sdk开发文档
IOS上传SDK版本说明
Net SDK
iOS
开发文档
版本说明
Android
开发文档
版本说明
IoT SDK
iOS
开发文档
版本说明
Android
开发文档
版本说明
Web
开发文档
版本说明
固件端
开发文档
WEB播放SDK
WEB播放器介绍
跨域请求媒体源失败
QHWW-Player
拍摄SDK
iOS
开发文档
版本说明
Android
开发文档
版本说明
剪辑SDK
iOS
版本说明
开发文档
Android
开发文档
版本说明
投屏SDK
iOS
开发文档
Android
开发文档
播放SDK
iOS
开发文档
版本说明
Android
开发文档
版本说明
Web 上传SDK
首页
>
开发者中心
>
SDK管理
>
Android推流
>
开发文档
# Android推流SDK开发文档 ### Android推流SDK简单介绍 智汇云以SDK形式提供视频直播采集,可以帮助开发者快速实现视频直播能力。SDK包含jar包、so库、demo及开发文档。 ### 功能说明: | **系统特性** | **支持内容** | |--|--| | 系统版本 | Android 4.0及以 | | 流媒体协议 | RTMP、私有协议 | | 硬件特 | armeabi-v7a、arm64-v8 | | 属性 | 支持内容 | | 参数设置 | 自定义采集分辨率、码率、帧率、关键帧间隔、声道数等 | | 编码方式 | H254、H265、AAC | | 设备驱动 | 摄像头、声音开关 | | **功能列表** | |--| | 美颜(需授权) | | 美白(需授权) | | 瘦脸(需授权) | | 大眼(需授权) | | FaceU(需授权) | | 镜像 | | 推流过程中静音 | | 纯音频推流 | | 前后置摄像头,以及动态切换 | | 推流过程中关闭、开启推送视频流 | | 推流视频保存到本地 | | 水印 | | 截帧 | | 横竖屏推流 | ### 业务流程  ### SDK集成 #### 下载SDK sdk下载链接:[https://zyun.360.cn/developer](https://live.360.cn/index/sdkdownload) - jar - qhvc_tools_sdk.jar - qhvc_recorder_sdk.jar - so: - armeabi-v7a/libtranscore.so - armeabi-v7a/libopenh264.so - armeabi-v7a/libpublisher.so - armeabi-v7a/libqycodec.so - armeabi-v7a/libfudx.so - armeabi-v7a/liblua.so 若接入美颜、FaceU功能,还需要以下jar包及so库: - jar - qhvc_beautybase_sdk.jar - so - armeabi-v7a/libaisoften.so - armeabi-v7a/libqhfacesdk.so - armeabi-v7a/libvxproto-1.0.3.so - armeabi-v7a/libyuv.so - armeabi-v7a/libyuvjni.so demo下载链接:[https://github.com/360livecloud/android_demo.git](https://github.com/360livecloud/android_demo.git) 若接入美颜、FaceU功能,请将demo工程中的以下资源文件复制到自己的工程: - src/main/assets/eff - src/main/assets/filter.png - src/main/assets/model.zip #### 配置说明 将qhvc_tools_sdk.jar、qhvc_recorder_sdk.jar放到工程libs目录下,在build.gradle中配置: ``` dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') } ``` 将libtranscore.so、libopenh264.so、libpublisher.so、libqycodec.so、libfudx.so、liblua.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()`获取。 #### 权限配置 在AndroidManifest.xml文件中申请相应权限: ``` <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-feature android:glEsVersion="0x00020000" android:required="true"/> <uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> <uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <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"/> ``` #### 混淆规则 ``` -keep class com.qihoo.livecloud.** { <fields>; <methods>; } -keep class com.qihoo.videocloud.** { <fields>; <methods>; } -keep class net.qihoo.videocloud.** { <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("appId") .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为"LiveCloudRecorder"。 ``` 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()); ``` ### 接口说明 #### 美颜、FaceU功能初始化及鉴权 建议在APP启动时调用,可参考demo中VideoCloudApplication类。若需开通权限,请联系视频云商务。 ``` //预加载Faceu需要的model文件 QHVCFaceModelsManager.copyAndUnzipModelFiles(context); //faceU鉴权 QHVCLiveKitAdvanced.initFaceULibs(context, ak, timeStamp, random, token, new QHVCFaceUInitCallBack() { @Override public void onCallback(int info) { if (info == AUTHENT_OK) { //TODO } } }); //美颜鉴权 QHVCLiveKitAdvanced.initBeautyLibs(context, ak, timeStamp, random, token, new QHVCBeautyInitCallBack() { @Override public void onCallback(int info) { if (info == AUTHENT_OK) { //TODO } } }); ``` 鉴权结果返回码请参考[美颜、FaceU鉴权接口返回值](#美颜鉴权接口返回值) #### 初始化采集推流类 可参考demo工程中`com.qihoo.videocloud.recorder. RecorderActivityNewAPI`类。 ``` mQhvcLiveKitAdvanced = QHVCLiveKitAdvanced.getInstance(this.getApplicationContext());//初始化推流操作类 mQhvcLiveKitAdvanced.setMediaSettings(mQHVCMediaSettingsBuilder.build());//设置采集的音视频相关参数 mQhvcLiveKitAdvanced.setPublishSettings(mQhvcPublishSettingsBuild.build());//设置推流参数 mQhvcLiveKitAdvanced.setRtmpPushAddr(URL);// 设置推流地址 mQhvcLiveKitAdvanced.setDisplayPreview(mSurfaceView);//设置预览显示界面 ``` #### 创建推流事件监听 ``` //设置推流信息回调 mQhvcLiveKitAdvanced.setStateCallback(new QHVCRecorderCallBack() { /*设置状态回调*/ @Override public void onState(int sessionId, int pubEvent, int msg1, String msg2) { } @Override public void onEncodedMessage(int sessionId, int type, ByteBuffer buffer, int length, long time) { } }); ``` `QHVCRecorderCallBack`:采集回调函数,用于回传推流消息,具体消息码(pubEvent)含义请查看[SDK消息通知](#消息通知)。 #### 设置推流码率 ``` mQhvcLiveKitAdvanced.setBitrate(codeRateSp*1024);/*设置码率,需在调用mQhvcLiveKitAdvanced.prepare()之前调用*/ ``` #### 准备推流 ``` mQhvcLiveKitAdvanced.prepare();/*准备*/ ``` #### 开始预览 ``` mQhvcLiveKitAdvanced.startPreview();/*开始预览*/ ``` #### 开始推流 ``` mQhvcLiveKitAdvanced.startPublish();/*开始推流*/ ``` #### 暂停推流 ``` mQhvcLiveKitAdvanced.pausePublish();/*暂停传输*/ ``` #### 暂停预览 ``` mQhvcLiveKitAdvanced.pausePreview();/*暂停预览*/ ``` #### 停止推流 ``` mQhvcLiveKitAdvanced.stop();/*停止采集推流*/ ``` #### 资源释放 ``` mQhvcLiveKitAdvanced.release();/*释放资源*/ ``` 更多详细接口请参考[API接口文档]()及demo。 ### SDK集成注意事项 1. 如需用到美颜、美白、FaceU等相关功能需联系我们进行授权并在应用启动时进行初始化和鉴权。初始化代码请参照[初始化及鉴权美颜功能库](#美颜功能初始化及鉴权)。 2. `QhvcLiveKitAdvanced.prepare()`需在`QhvcLiveKitAdvanced.startPreview()`方法之前调用。 3. `QhvcLiveKitAdvanced.setBitrate()`设置推流码率需放在`QhvcLiveKitAdvanced.prepare()`方法之前。 ### 消息通知 调用`QhvcLiveKitAdvanced.setStateCallback()`后,SDk通过onState()函数中的pubEvents回调消息,详细调用方法见[创建推流事件监听](#创建推流事件监听)。 pubEvent 值含义: | **值** | **对应消息** | |--------|----------------------------------------| | 1 | 连接成功 | | 2 | 连接失败 | | 3 | 连接断开 | | 4 | 收到SN,但是被jni层截获,处理为返回sn了 | | 5 | 获取SN与调度信息失败 | | 6 | 开流失败 | | 7 | 开流完成 | | 8 | 通知业务端,播放结束,直播不使用 | | 9 | 本地录制失败(无参数或WriteLocalEvent) | | 10 | 丢帧,内部事件 | | 11 | 需要重新调度(无参数) | | 12 | 推流效果较差(无参数) | | 100 | 表示开始使用硬编码 | | 101 | 自适应码率 | | 1000 | 设置输入失败 | | 999001 | 打开相机失败 | | 999002 | 相机不支持的预览尺寸 | | \-1 | 句柄无效 | | \-2 | 参数无效 | | \-3 | 不支持的协议 | | \-4 | 未调用初始化函数 | | \-5 | 申请内存失败 | | \-6 | 申请线程失败 | | \-7 | 申请句柄失败 | | \-8 | 错误的调用顺序 | | \-999 | 未知错误 | | \-200 | 采集音频出错 | | \-201 | 未设置续推所需数据 | | \-202 | 此设备不支持硬编美颜功能 | ### 美颜鉴权接口返回值 | **值** | **对应消息** | |--------|----------------------------------------| | 0 | 鉴权成功 | |-11 | 鉴权失败 | |-2 | 加密上行包出错 | |-3 | 解析返回报文出错 | |-5 | 没有对称密钥,需要先执行V6协商 | |-6 | 对称密钥过期,需要重新用V6协商 | |-7 | 用户取消 | |-8 | 网络查询失败 | |-100 | 没联网 | |-101 | 编码格式不支持 | |-3000 | 连不上服务器 | | 1 | 操作失败 | | 9 | 系统错误 | | 10 | 内部错误 | | 11 | 无效的参数 | | 12 | sig invalid | | 27 | 错误的平台信息 | | 28 | 参数为空 | | 29 | 参数不存在 | | 30 | 入口签名错误 | | 31 | 用户不存在 | | 32 | 参数格式化错误 | | 34 | 洪水请求 | | 35 | 服务器被拒绝 | | 36 | redis操作失败 | | 39 | 参数不存在 | | 43 | 无权限访问 | | 1307 | 第三方资源请求失败 | | 9997 | 服务器异常在 | | 9999 | 通知:系统正在升级,预计30分钟后恢复 | | 100025 | 数据解密失败 | | 100026 | 数据解析失败 | | 100029 | 接口未授权 | | 100100 | 非有效的base64数据 | | 100101 | v6v11解密失败 | | 100102 | v6v11解密的内容非json格式 | | 100103 | 参数不全 | | 100104 | ak格式错误 | | 100105 | 包名格式错误 | | 100106 | 未找到用户信息 | | 100107 | sign验证失败 | | 100108 | sign已使用过 | | 100109 | 连接验证资源失败 | | 100110 | 时间戳过期 | | 100200 | 未找到配置 | | 100201 | 未找到模块 | | 100202 | 模块已过期 |
即刻开始使用
只需完成注册与实名认证,即可体验我们的贴心服务
立即注册
请您联系我们
邮箱
g-zyun@360.cn
电话
010-56821952
给我们留言
您的姓名
手机号
公司名称(选填)
相关产品
留言内容
需求描述
产品建议
其他
提交
登录后才可以留言哦
立即登录
去注册账号