更新记录
1.0.0(2022-01-19)
首次更新
平台兼容性
Android | Android CPU类型 | iOS |
---|---|---|
适用版本区间:4.4 - 14.0 | armeabi-v7a:支持,arm64-v8a:支持,x86:未测试 | 适用版本区间:11 - 17 |
原生插件通用使用流程:
- 购买插件,选择该插件绑定的项目。
- 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
- 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
- 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
- 开发完毕后正式云打包
付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios
注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择
KJ-HatomPlayer
海康iSecure Center实时视频预览、录像回放、倍数回放、抓图、声音、录像、语言对讲、鱼眼(ios、android)
海康V1版本地址
海康(HIKVISION)实时视频预览、录像回放、语音对讲:https://ext.dcloud.net.cn/plugin?id=2403
引入插件
<KJ-HatomPlayer ref='KJHatomPlayer' style="width:750rpx;height:200px" @onPlayerStatus="onPlayerStatus"
@onTalkStatus="onTalkStatus"></KJ-HatomPlayer>
基本使用步骤
1.如何获取海康视频流地址?
答:后台开发人员对接海康提供的接口,
获取流地址,参考海康的开放平台:https://open.hikvision.com/docs/docId?productId=5c67f1e2f05948198c909700&curNodeId=979ab5f343114ad6a96f2d46d8cc26c9
相关代码
<template>
<div>
<KJ-HatomPlayer ref='KJHatomPlayer' style="width:750rpx;height:200px" @onPlayerStatus="onPlayerStatus"
@onTalkStatus="onTalkStatus"></KJ-HatomPlayer>
<view class="btns">
<button type="primary" @click="init">初始化</button>
<button type="primary" @click="start">开始播放</button>
<button type="primary" @click="stop">停止播放</button>
<button type="primary" @click="changeStream">切换码流</button>
<button type="primary" @click="startVoiceTalk">开启对讲</button>
<button type="primary" @click="stopVoiceTalk">停止对讲</button>
<button type="primary" @click="startPlayback">开启录像回放</button>
<button type="primary" @click="seekPlayback">按绝对时间回放定位</button>
<button type="primary" @click="pause">暂停回放</button>
<button type="primary" @click="resume">恢复回放</button>
<button type="primary" @click="getPlaybackSpeed">获取回放倍速值</button>
<button type="primary" @click="setPlaybackSpeed">设置回放倍速</button>
<button type="primary" @click="enableAudio">开启声音</button>
<button type="primary" @click="enableAudio_close">关闭声音</button>
<button type="primary" @click="getOSDTime">获取视频中屏幕显示时间</button>
<button type="primary" @click="screenshoot">抓图</button>
<button type="primary" @click="getTotalTraffic">获取消耗的流量</button>
<button type="primary" @click="startRecord">开始录像</button>
<button type="primary" @click="stopRecord">结束录像</button>
<button type="primary" @click="setFishEyeEnable">开启鱼眼</button>
<button type="primary" @click="setFishEyeEnable_close">关闭鱼眼</button>
<button type="primary" @click="setFishEyeMode">设置鱼眼模式</button>
</view>
<image :src="imageSrc" mode="aspectFill"> </image>
</div>
</template>
<script>
var RealPlayUrl = "rtsp://xxx.xxx.xxx.xxx:xxx/openUrl/4YdN7xu" //预览取流URL
var PlaybackUrl = "rtsp://xxx.xxx.xxx.xxx:xxx/openUrl/3ToKcqk" //回放取流URL
var voiceDataSource = "rtsp://xxx.xxx.xxx.xxx:xxx/openUrl/xxx" //语言对讲取流URL
export default {
data() {
return {
imageSrc: '../../static/logo.png',
recordFilePath: null
}
},
onLoad() {
},
onReady() {
//this.startPlayback();
},
methods: {
/**
* 播放状态回调
* */
onPlayerStatus(e) {
//{"playStatus":"SUCCESS","errorCode":"HVPErrorCodeSuccess"}
//错误码参考插件市场文档
console.log("onPlayerStatus: " + JSON.stringify(e.detail))
},
/**
* 语音对讲状态回调
* */
onTalkStatus(e) {
console.log("onTalkStatus: " + JSON.stringify(e.detail))
},
init() {
this.$refs.KJHatomPlayer.initSDK(""); //萤石appkey,如果是海康isc平台,传空字符
},
/**
* 开启预览
* */
start() {
console.log(this.$refs.KJHatomPlayer)
var dic = {
"playConfig": {
hardDecode: true, //是否开启硬解码 true-开启 false-关闭
privateData: true, //是否显示智能信息 true-显示 false-不显示
timeout: 20, //取流超时时间,默认20s
secretKey: "", //码流解密key
bufferLength: 5 * 1024 * 1024, //流缓冲区大小,默认为5M
},
"dataSource": RealPlayUrl, //播放url
"headers": {
"token": ""
} //请求参数 默认要传token,值可以为空字符串
}
this.$refs.KJHatomPlayer.initPlayConfig(dic);
this.$refs.KJHatomPlayer.start();
},
stop() {
this.$refs.KJHatomPlayer.stop();
},
/**
* 切换码流
* */
changeStream() {
var dic = {
"qualityType": 2, //0-高清 1-标清 2-流畅
}
this.$refs.KJHatomPlayer.changeStream(dic, (res) => {
console.log("changeStream: " + JSON.stringify(res))
});
},
/**
* 开启对讲
* 需要麦克风权限,android需要动态获取
* */
startVoiceTalk() {
var dic = {
"voiceDataSource": voiceDataSource, //对讲url
"headers": {
"token": ""
} //请求参数 默认要传token,值可以为空字符串
}
this.$refs.KJHatomPlayer.startVoiceTalk(dic, (res) => {
console.log("startVoiceTalk: " + JSON.stringify(res))
});
},
/**
* 停止对讲
* */
stopVoiceTalk() {
this.$refs.KJHatomPlayer.stopVoiceTalk();
},
/**
* 开启录像回放
* */
startPlayback() {
var dic = {
"playConfig": {
hardDecode: true, //是否开启硬解码 true-开启 false-关闭
privateData: true, //是否显示智能信息 true-显示 false-不显示
timeout: 20, //取流超时时间,默认20s
secretKey: "", //码流解密key
bufferLength: 5 * 1024 * 1024, //流缓冲区大小,默认为5M
},
"dataSource": PlaybackUrl, //回放url
"headers": {
"token": "", //请求参数 默认要传token,值可以为空字符串
"startTime": "2021-07-29T00:00:00.000+08:00", //开始时间,必传,yyyy-MM-dd'T'HH:mm:ss.SSS+08:00时间格式
"endTime": "2021-07-29T23:59:59.000+08:00", // 结束时间,必传,yyyy-MM-dd'T'HH:mm:ss.SSS+08:00时间格式
}
}
this.$refs.KJHatomPlayer.initPlayConfig(dic);
this.$refs.KJHatomPlayer.start();
},
/**
* 按绝对时间回放定位
* 使用按绝对时间回放定位接口之前,必须先调用开始回放接口
* */
seekPlayback() {
var dic = {
"seekTime": "", //定位时间,格式为 yyyy-MM-dd'T'HH:mm:ss.SSS
}
this.$refs.KJHatomPlayer.seekPlayback(dic);
},
/**
* 暂停回放
* */
pause() {
this.$refs.KJHatomPlayer.pause();
},
/**
* 恢复回放
* */
resume() {
this.$refs.KJHatomPlayer.resume();
},
getPlaybackSpeed() {
this.$refs.KJHatomPlayer.getPlaybackSpeed((res) => {
console.log("getPlaybackSpeed: " + JSON.stringify(res))
});
},
setPlaybackSpeed() {
var dic = {
"speed": 2, //倍速值-8/-4/-2/1/2/4/8,负数为慢放,正数为快放
}
this.$refs.KJHatomPlayer.setPlaybackSpeed(dic, (res) => {
console.log("setPlaybackSpeed: " + JSON.stringify(res))
});
},
/**
* 开启声音
* */
enableAudio() {
var dic = {
"enable": true, //true-开启声音 false-关闭声音
}
this.$refs.KJHatomPlayer.enableAudio(dic, (res) => {
console.log("openSound: " + JSON.stringify(res))
});
},
/**
* 开启声音
* */
enableAudio_close() {
var dic = {
"enable": false, //true-开启声音 false-关闭声音
}
this.$refs.KJHatomPlayer.enableAudio(dic, (res) => {
console.log("openSound: " + JSON.stringify(res))
});
},
/**
*获取视频中屏幕显示时间
* */
getOSDTime() {
var _this = this;
var interval = setInterval(function() {
_this.$refs.KJHatomPlayer.getOSDTime((res) => {
console.log("getOSDTime: " + JSON.stringify(res))
});
}, 1000);
},
getTotalTraffic() {
var _this = this;
var interval = setInterval(function() {
_this.$refs.KJHatomPlayer.getTotalTraffic((res) => {
console.log("getTotalTraffic: " + JSON.stringify(res))
});
}, 1000);
},
/**
*抓图
*注意:filePath 一定要是_doc绝对目录
* */
screenshoot() {
var filePath = plus.io.convertLocalFileSystemURL("_doc/KJHatomPlayer");
var fileName = new Date().getTime() + ".png"
var dic = {
"filePath": filePath,
"fileName": fileName,
}
console.log("dic: " + JSON.stringify(dic))
if (plus.os.name == 'Android') {
this.$refs.KJHatomPlayer.screenshoot(dic, (res) => {
console.log("screenshoot: " + JSON.stringify(res))
this.imageSrc = plus.io.convertAbsoluteFileSystem(filePath + "/" +
fileName);
console.log(this.imageSrc);
uni.saveImageToPhotosAlbum({
filePath: this.imageSrc,
fail(res) {
console.log(JSON.stringify(res))
}
})
});
} else {
this.$refs.KJHatomPlayer.screenshoot2(dic, (res) => {
console.log("screenshoot: " + JSON.stringify(res))
this.imageSrc = plus.io.convertAbsoluteFileSystem(filePath + "/" +
fileName);
console.log(this.imageSrc);
uni.saveImageToPhotosAlbum({
filePath: this.imageSrc,
fail(res) {
console.log(JSON.stringify(res))
}
})
});
}
},
/**
*开始录像
*注意:filePath 一定要是_doc绝对目录
* */
startRecord() {
var filePath = plus.io.convertLocalFileSystemURL("_doc/KJHatomPlayer");
var fileName = new Date().getTime() + ".png"
var dic = {
"filePath": filePath,
"fileName": fileName
}
this.recordFilePath = plus.io.convertAbsoluteFileSystem(filePath + "/" +
fileName)
this.$refs.KJHatomPlayer.startRecord(dic, (res) => {
console.log("startRecord: " + JSON.stringify(res))
});
},
/**
*结束录像
* */
stopRecord() {
this.$refs.KJHatomPlayer.stopRecord((res) => {
console.log("stopRecord: " + JSON.stringify(res))
uni.saveVideoToPhotosAlbum({
filePath: this.recordFilePath,
fail(res) {
console.log(JSON.stringify(res))
}
})
});
},
/**
*开启鱼眼
* */
setFishEyeEnable() {
var dic = {
"enable": true, //是否打开
"isAddGr": true, //是否添加手势
}
this.$refs.KJHatomPlayer.setFishEyeEnable(dic, (res) => {
console.log("setFishEyeEnable: " + JSON.stringify(res))
});
},
/**
*关闭鱼眼
* */
setFishEyeEnable_close() {
var dic = {
"enable": false, //是否打开
"isAddGr": false, //是否添加手势
}
this.$refs.KJHatomPlayer.setFishEyeEnable(dic, (res) => {
console.log("setFishEyeEnable: " + JSON.stringify(res))
});
},
/**
*设置鱼眼模式
* 安装方式与矫正方式关系表 √-支持 x-不支持
* 矫正方式 | Wall | Floor | Ceiling
* Ptz | √ | √ | √
* 180 | x | √ | √
* 360 | √ | √ | √
* Lat | √ | x | x
* Hemisphere | x | √ | √
* Cylinder | x | √ | √
* Planet | x | √ | √
* CylinderCut| x | √ | √
* */
setFishEyeMode() {
var dic = {
"correctType": "Hemisphere", //Ptz-PTZ模式 180-180度矫正(对于2P)360-360度矫正(对应1P)Lat-维度拉伸 Hemisphere-半球模式 Cylinder-圆柱模式 Planet-小行星模式 CylinderCut-圆柱断开
"placeType": "Ceiling", //None-无安装 Wall-壁装(法线水平)Floor-地面安装(法线向上)Ceiling-顶装方式(法线向下)
}
this.$refs.KJHatomPlayer.setFishEyeMode(dic, (res) => {
console.log("setFishEyeMode: " + JSON.stringify(res))
});
}
}
}
</script>
<style>
.btns {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
justify-content: flex-start;
}
</style>
错误码及说明
playStatus
错误码 | 说明 |
---|---|
SUCCESS | 播放成功(包括开启预览、开启回放、回放seek操作、开启 对讲) |
FAILED | 播放失败(包括开启预览、开启回放、回放seek操作、开启 对讲) |
EXCEPTION | 播放中异常(包括预览、回放、对讲中) |
FINISH | 播放结束 |
errorCode
错误码 | 说明 |
---|---|
errorCode | 错误码,只有在 playStatus 状态为: FAILED 、 EXCEPTION 才有值 ,其他 status 值为 -1。 |
取流库错误码 errorCode
错误代码数值 | 说明 |
---|---|
0x017开头 | 媒体⽹网关或媒体取流SDK的错误 |
0x018开头 | 视频点播服务的错误码 |
0x019开头 | 设备接⼊入框架的错误码 |
0x022开头 | 视频联⽹网⽹网关的错误码 |
常⻅见问题排查
1.SDK 初始化的 appKey 从哪获取?
目前版本的 SDK 不校验 appKey,可以是任意字符,也可以为 nil。
2.开启语音对讲失败?
开放平台 OpenAPI 目前仅支持海康、国标、Ehome 协议接入的监控设备语音对讲。
3.为什么 SDK 不支持云台操作?
SDK 只负责取流及解码展示。而云台操作需要通过开放平台 OpenAPI 接口调用设备能力实现。
4.iOS11 以下 iPhone 转 MP4 格式后本地录像文件无法播放?
登录摄像头的页面(浏览器中输入摄像头的 ip 地址,输入摄像头用户名和密码),检查摄像头的视频格 式是否为 h265,iOS11 以下不支持 h265 解码,请升级 iPhone 手机的系统为 iOS11 及以上,或者设置 摄像头的视频格式为 h264(不推荐)。
5.开启实时预览或录像回放后,始终不显示画面?
首先请确认要查看的监控设备是否是大华设备,获取监控点取流 URL 的请求体"expand"字段中指定扩展 字段为: "expand": " transcode=1&videotype=h264" 。否则 SDK 无法解码大华协议的码流,导致画面无 法显示。
6.鹰眼全景相机设备无法预览
鹰眼全景相机设备不支持子码流,只支持主码流。将码流切换成主码流即可预览。
7.开启语音对讲失败?
请确认进行对讲的设备类型,目前仅支持海康、国标、Ehome协议接入的监控设备语音对讲。 如果出现错误码:0x03d1000b 则此设备的音频解码类型是Android手机不支持的类型。 解码类型只支持:G722、G711_U、G711_A三种,需要把设备的解码类型改成支持的解码类型
8.进行本地录像后发现没有录像文件生成?
请检测App是否有写入权限,如没有,则无法保存录像文件。 请确认是否使用转码库将录像文件进行转码,如已使用,请确认是否正常完成转码。