更新记录
1.0.14(2026-08-12)
- 优化
1.0.13(2026-08-12)
- 增加清晰度切换接口
1.0.12(2026-08-11)
- 增加鸿蒙支持
查看更多
平台兼容性
uni-app(3.8.1)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
- |
- |
√ |
√ |
5.0 |
√ |
- |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| - |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
uni-app x(3.8.1)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| - |
- |
5.0 |
√ |
- |
- |
其他
萤石SDK
- 预览:直播、截图抓图、声音开关
- 对讲:对讲、对讲音频音量大小
- 回放:回放、倍数回放、进度拖拽
集成步骤
- 拷贝demo示例项目里的AndroidManifest.xml文件到项目根目录
- 咨询或定制请点击上面"进入交流群"按钮私聊作者
- 登陆萤石管理后台创建应用获取到appKey、token,替换demo里App.vue里的appkey和token
- 替换playback.nvue和realPlay.nvue里的deviceSerial和cameraNo
文档
import {
EZOpen
} from "@/uni_modules/wrs-uts-ezopen"
EZOpen.showSDKLog(true)
EZOpen.setDebugStreamEnable(true)
EZOpen.enableP2P(true)
let appkey = "xxx" // 替换成自己应用的appKey
let token = "xxx" // 替换成自己应用的token
let apiUrl = "https://open.ys7.com" // 国内固定这个
let authUrl = "https://openauth.ys7.com" // 国内固定这个
let isEnableSDKWithTKToken = false
if (token.startsWith("tk.")) {
isEnableSDKWithTKToken = true
}
EZOpen.enableSDKWithTKToken(isEnableSDKWithTKToken)
let params = {}
params.appKey = appkey
params.apiUrl = apiUrl
params.authUrl = authUrl
if (isEnableSDKWithTKToken) {
params.httpToken = token
} else {
params.accessToken = token
}
EZOpen.sdkInit(params)
let params = {}
params.deviceSerial = ""
params.cameraNo = 0
EZOpen.captureCamera(params, (resp) => {
console.log("captureCamera resp:" + JSON.stringify(resp))
let result = resp.result
if (result) {
// result是抓图的地址
this.imageSrc = result
}
})
组件
<!-- #ifdef APP-HARMONY -->
<embed :style="'width:'+width+'px;height:'+height+'px;'" tag="vlc" :options="options"
@onevent="onEvent"></embed>
<!-- #endif -->
<!-- #ifndef APP-HARMONY -->
<wrs-uts-ezopenplayer ref='vlc' :params="params" :style="'width:'+width+'px;height:'+height+'px;'"
@onEvent="onEvent"></wrs-uts-ezopenplayer>
<!-- #endif -->
- 使用了该组件的页面需要用nvue或uvue
- 属性params是json格式的字符串
let deviceSerial = ""
let cameraNo = 0
let params = {}
params.businessArray = [{
business: "setUrl", // 业务
params: { // 业务参数
deviceSerial: deviceSerial,
cameraNo: cameraNo,
autoPlay: true
}
}]
let paramsStr = JSON.stringify(params)
let width = windowWidth
let height = width / (16.0 / 9.0)
return {
params: paramsStr,
options: {
params: paramsStr
},
deviceSerial: deviceSerial,
cameraNo: cameraNo,
width: width,
height: height,
imageSrc: null,
msg: null
}
onEvent(event) {
const detail = event.detail
console.log("onEvent detail:" + JSON.stringify(detail))
let opt = detail.opt
// console.log("onEvent detail:" + JSON.stringify(detail))
switch (opt) {
// 消息事件,仅支持Android
case "onEvent": {
// what码值:
// public static final int MSG_GET_CAMERA_INFO_SUCCESS = 100;
// public static final int MSG_GET_CAMERA_INFO_FAIL = 101;
// public static final int MSG_REALPLAY_PLAY_SUCCESS = 102;
// public static final int MSG_REALPLAY_PLAY_FAIL = 103;
// public static final int MSG_SET_VEDIOMODE_SUCCESS = 105;
// public static final int MSG_SET_VEDIOMODE_FAIL = 106;
// public static final int MSG_START_RECORD_SUCCESS = 107;
// public static final int MSG_START_RECORD_FAIL = 108;
// public static final int MSG_REALPLAY_PASSWORD_ERROR = 111;
// public static final int MSG_REALPLAY_ENCRYPT_PASSWORD_ERROR = 112;
// public static final int MSG_REALPLAY_VOICETALK_SUCCESS = 113;
// public static final int MSG_REALPLAY_VOICETALK_FAIL = 114;
// public static final int MSG_REALPLAY_VOICETALK_STOP = 115;
// public static final int MSG_REALPLAY_UPDATE_TALK_VOLUME = 116;
// public static final int MSG_PTZ_GET_SUCCESS = 122;
// public static final int MSG_PTZ_SET_SUCCESS = 123;
// public static final int MSG_PTZ_SET_FAIL = 124;
// public static final int MSG_REALPLAY_PLAY_START = 125;
// public static final int MSG_REALPLAY_CONNECTION_START = 126;
// public static final int MSG_REALPLAY_CONNECTION_SUCCESS = 127;
// public static final int MSG_REALPLAY_CHECK_SUCCESS = 131;
// public static final int MSG_REALPLAY_CHECK_FAIL = 132;
// public static final int MSG_REALPLAY_STOP_SUCCESS = 133;
// public static final int MSG_REALPLAY_PLAY_PREPARED = 139;
// public static final int MSG_PRIVATE_TOKEN_GET_SUCCESS = 135;
// public static final int MSG_VIDEO_LEVEL_AUTO_IMPROVE = 136;
// public static final int MSG_VIDEO_LEVEL_AUTO_REDUCE = 137;
// public static final int MSG_SET_VEDIOMODE_AUTO_SUCCESS = 138;
// public static final int MSG_NET_CHANGED = 140;
let what = detail.what
switch (what) {
// MSG_REALPLAY_PLAY_SUCCESS 播放成功
case 102:
break;
// MSG_REALPLAY_PLAY_FAIL播放失败
case 103:
break;
// MSG_REALPLAY_VOICETALK_SUCCESS 对讲成功
case 113:
break;
// MSG_REALPLAY_VOICETALK_FAIL 对讲失败
case 114:
break;
// MSG_PTZ_GET_SUCCESS
case 122:
break;
default:
break;
}
}
break;
// 收到播放消息,仅支持iOS
case "onReceivedMessage": {
let playerType = detail.playerType
if (playerType == 0) { // 播放器的回调
console.log("视频播放器")
} else { // 对讲的回调
console.log("对讲播放器")
}
// messageCode值:
// PLAYER_REALPLAY_START = 1, //直播开始
// PLAYER_VIDEOLEVEL_CHANGE = 2, //直播流清晰度切换中
// PLAYER_STREAM_RECONNECT = 3, //直播流取流正在重连
// PLAYER_VOICE_TALK_START = 4, //对讲开始
// PLAYER_VOICE_TALK_END = 5, //对讲结束
// PLAYER_STREAM_START = 10, //录像取流开始
// PLAYER_PLAYBACK_START = 11, //录像回放开始播放
// PLAYER_PLAYBACK_STOP = 12, //录像回放结束播放
// PLAYER_PLAYBACK_FINISHED = 13, //录像回放被用户强制中断
// PLAYER_PLAYBACK_PAUSE = 14, //录像回放暂停
// PLAYER_NET_CHANGED = 21, //播放器检测到wifi变换过
// PLAYER_NO_NETWORK = 22, //播放器检测到无网络
// PLAYER_CLOUD_IFRAME_CHANGED = 23, //云存储快放时,由全帧快放切换到抽帧快放的提示回调
// PLAYER_PLAYSPEED_LOWER = 24, //云存储快放时的降速通知(存在两次降速:当前倍速大于4倍速时,降到4倍速;当前为4倍速时,降为1倍速)
// PLAYER_VIDEO_LEVEL_AUTO_IMPROVE = 25,//预览自动清晰度提升消息
// PLAYER_VIDEO_LEVEL_AUTO_REDUCE = 26, //预览自动清晰度降低消息
// PLAYER_PREPARED = 27, //播放库已创建
let messageCode = detail.messageCode
switch (messageCode) {
case 1: {
// 直播开始
}
break;
case 2: {
// 直播流清晰度切换中
}
break;
case 3: {
// 直播流取流正在重连
}
break;
case 4: {
// 对讲开始
}
break;
case 5: {
// 对讲结束
}
break;
case 27: {
// 播放库已创建
}
break;
default:
break;
}
}
break;
// 播放失败,仅支持iOS
case "onPlayFailed": {
let code = resp.code
let playerType = detail.playerType
if (playerType == 0) {
console.log("视频播放器")
// code取值:
// EZ_NPC_CLIENT_PARAMETER_ERROR = 500001, //参数错误
// EZ_NPC_CLIENT_ORDER_ERROR = 500002, //调用顺序出错
// EZ_NPC_CLIENT_MEMORY_ERROR = 500003, //分配内存失败
// EZ_NPC_CLIENT_BUFFER_OVERFLOW_ERROR = 500004, //缓冲区溢出
// EZ_NPC_CLIENT_SYSTEM_NO_SUPPORT_ERROR = 500005, //系统不支持
// EZ_NPC_CLIENT_INVALID_PORT_ERROR = 500006, //无效端口
// EZ_NPC_CLIENT_STREAM_CLOSE_ERROR = 500101, //流关闭
// EZ_NPC_CLIENT_TRACK_CLOSE_ERROR = 500102, //TRACK_CLOSE
// EZ_NPC_CLIENT_NPCCREATE_ERROR = 500103, //创建失败
// EZ_NPC_CLIENT_TRSCREATE_ERROR = 500104, //TRSCREATE_ERROR
// EZ_NPC_CLIENT_FAIL_UNKNOWN_ERROR = 509999, //FAIL_UNKNOWN
if (code == 400035) { // 需要设备验证码
} else if (code == 400036) { // 设备验证码不匹配
}
} else {
console.log("对讲播放器")
}
}
break;
case "snapshot": {
// 截图回调
let filePath = detail.filePath
if (filePath) {
let path = detail.filePath
this.imageSrc = "file://" + path
} else {
this.showMsg("截图失败:" + JSON.stringify(detail))
}
}
break;
// 对讲音频音量大小
case "setVoiceTalkLoudnessCallback": {
let v = detail.v
}
break;
}
}
params.businessArray数组里支持的业务对象有:
{
business: "setUrl", // 业务
params: {
deviceSerial: "xxx", // 设备码
cameraNo: 1, // 相机编码
autoPlay: true // 是否自动播放
}
}
或者
{
business: "setUrl", // 业务
params: {
url: "rtsp://xxxx", // 直播地址
autoPlay: true // 是否自动播放
}
}
{
business: "startRealPlay"
}
{
business: "stopRealPlay"
}
- 是否开启声音,要在播放成功后才可以设置是否开启声音
{
business: "setSound",
params: {
isOpen: true
}
}
let params = {}
params.deviceSerial = deviceSerial
params.cameraNo = cameraNo
params.videoLevel = videoLevel
console.log("setVideoLevel params:" + JSON.stringify(params))
EZOpen.setVideoLevel(params, (resp) => {
let flag = resp.flag
if (flag) {
console.log("切换成功")
//清晰度切换成功后,再暂停播放,再重新播放
let newParams = {}
newParams.businessArray = [{
business: "stopRealPlay"
}, {
business: "startRealPlay"
}]
console.log("vue params:" + JSON.stringify(newParams))
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
params: newParamsStr
}
} else {
console.log("切换失败:" + JSON.stringify(resp))
}
})
let name = new Date().getTime()
let path = EZOpen.getFilesDir() + "/" + name + ".jpg"
{
business: "snapshot", // 截图
params: {
path: path // 本地保存图片的绝对地址
}
}
{
business: "startVoiceTalk", // 对讲
params: {
isOpen: false // 关闭
}
}
{
business: "setVoiceTalkStatus", // 对讲
params: {
isOpen: false // 关闭
}
}
business: "setVoiceTalkLoudnessCallback",
params: {
interval: 0.15
}
}
回放云端存储视频
{
business: "setUrl", // 业务
params: {
deviceSerial: "xxx", // 设备码
cameraNo: 1, // 相机编码
cloudFileKey: "" // 从EZOpen.searchRecordFileFromCloud接口获取
}
}
或
回放设备存储视频
{
business: "setUrl", // 业务
params: {
deviceSerial: "xxx", // 设备码
cameraNo: 1, // 相机编码
deviceFileKey: "" // 从EZOpen.searchRecordFileFromDevice接口获取
}
}
{
business: "setPlaybackRate", // 对讲
params: {
rate: "2" // 云端回放支持:"1/16", "1/8", "1/4", "1/2", "1", "2", "4", "8", "16", "32" 设备回放需要各自去根据设备获取
}
}
{
business: "seekPlayback", // 对讲
params: {
time: 21212121 // 播放时间戳,Android精确到毫秒,iOS精确到秒
}
}
let params = {}
params.deviceSerial = ""
params.cameraNo = 0
params.startTime = 5444 // 开始时间戳,精确到秒
params.endTime = 555 // 结束时间戳,精确到秒
// console.log("searchRecordFileFromCloud params:" + JSON.stringify(params))
EZOpen.searchRecordFileFromCloud(params, (resp) => {
let data = resp.data
if (data) {
let titles = []
let count = data.length
for (var i = 0; i < count; i++) {
let model = data[i]
let title = model.startTime + "-" + model.stopTime
titles.push(title)
}
this.showActionSheet(titles, (index) => {
let model = data[index]
this.model = model
let fileKey = model.fileKey
let newParams = {}
newParams.businessArray = [{
business: "setUrl", // 对讲
params: {
deviceSerial: this.deviceSerial,
cameraNo: this.cameraNo,
cloudFileKey: fileKey
}
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
params: newParamsStr
}
})
} else {
console.log(JSON.stringify(resp))
}
})
let params = {}
params.deviceSerial = this.deviceSerial
params.cameraNo = this.cameraNo
params.startTime = startTime // 开始时间戳,精确到秒
params.endTime = endTime // 结束时间戳,精确到秒
EZOpen.searchRecordFileFromDevice(params, (resp) => {
let data = resp.data
if (data) {
let titles = []
let count = data.length
for (var i = 0; i < count; i++) {
let model = data[i]
let title = model.startTime + "-" + model.stopTime
titles.push(title)
}
this.showActionSheet(titles, (index) => {
let model = data[index]
this.model = model
let fileKey = model.fileKey
let newParams = {}
newParams.businessArray = [{
business: "setUrl",
params: {
deviceSerial: this.deviceSerial,
cameraNo: this.cameraNo,
deviceFileKey: fileKey
}
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
params: newParamsStr
}
})
} else {
console.log(JSON.stringify(resp))
}
})