feat: 添加发送语音相关逻辑

This commit is contained in:
fanpeng 2025-06-19 10:18:09 +08:00
parent 88b512aa7f
commit 6356b071ac
4 changed files with 319 additions and 107 deletions

View File

@ -31,7 +31,7 @@
return 'XHJ'
}
// #endif
return 'XHJ'
return 'DEV'
}
},
computed: {

View File

@ -1,110 +1,113 @@
{
"name": "星星锁Lite",
"appid": "__UNI__933D519",
"description": "",
"versionName": "1.3.0",
"versionCode": "37",
"mp-weixin": {
"appid": "wx9829a39e65550757",
"setting": {
"urlCheck": true,
"minified": true
},
"permission": {
"scope.bluetooth": {
"desc": "蓝牙将用于控制和管理您的智能门锁"
}
},
"usingComponents": true,
"lazyCodeLoading": "requiredComponents",
"optimization": {
"subPackages": true
},
"plugins": {
"wmpf-voip": {
"version": "latest",
"provider": "wxf830863afde621eb",
"genericsImplementation": {
"call-page-plugin": {
"custombox": "pages/main/customBox"
}
}
}
}
},
"vueVersion": "3",
"app-plus": {
"distribute": {
"icons": {
"android": {
"hdpi": "unpackage/res/icons/72x72.png",
"xhdpi": "unpackage/res/icons/96x96.png",
"xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi": "unpackage/res/icons/192x192.png"
"name" : "星星锁Lite",
"appid" : "__UNI__933D519",
"description" : "",
"versionName" : "1.3.0",
"versionCode" : "37",
"mp-weixin" : {
"appid" : "wx9829a39e65550757",
"setting" : {
"urlCheck" : true,
"minified" : true
},
"ios": {
"appstore": "unpackage/res/icons/1024x1024.png",
"ipad": {
"app": "unpackage/res/icons/76x76.png",
"app@2x": "unpackage/res/icons/152x152.png",
"notification": "unpackage/res/icons/20x20.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x": "unpackage/res/icons/167x167.png",
"settings": "unpackage/res/icons/29x29.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x": "unpackage/res/icons/80x80.png"
},
"iphone": {
"app@2x": "unpackage/res/icons/120x120.png",
"app@3x": "unpackage/res/icons/180x180.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x": "unpackage/res/icons/120x120.png"
}
"permission" : {
"scope.bluetooth" : {
"desc" : "蓝牙将用于控制和管理您的智能门锁"
}
},
"usingComponents" : true,
"lazyCodeLoading" : "requiredComponents",
"optimization" : {
"subPackages" : true
},
"plugins" : {
"wmpf-voip" : {
"version" : "latest",
"provider" : "wxf830863afde621eb",
"genericsImplementation" : {
"call-page-plugin" : {
"custombox" : "pages/main/customBox"
}
}
}
}
},
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" />"
]
},
"ios": {
"dSYMs": false
}
},
"modules": {
"Bluetooth": {},
"VideoPlayer": {},
"LivePusher": {},
"Camera": {},
"Record": {}
},
"splashscreen": {
"waiting": false
"vueVersion" : "3",
"app-plus" : {
"distribute" : {
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" />",
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.MANAGE_EXTERNAL_STORAGE\"/>"
]
},
"ios" : {
"dSYMs" : false
}
},
"modules" : {
"Bluetooth" : {},
"VideoPlayer" : {},
"LivePusher" : {},
"Camera" : {},
"Record" : {}
},
"splashscreen" : {
"waiting" : false
}
}
}
}

View File

@ -187,7 +187,14 @@
// #endif
// #ifdef APP-PLUS
import { startService, getLiveUrl, stopService } from '@/uni_modules/xhj-tencent-xp2p'
import {
startService,
getLiveUrl,
stopService,
runSendService,
stopSendService,
dataSend
} from '@/uni_modules/xhj-tencent-xp2p'
// #endif
const $bluetooth = useBluetoothStore()
@ -223,6 +230,8 @@
onMounted(async () => {
// #ifdef APP-PLUS
isApp.value = true
//
initRecorder()
// #endif
// #ifdef MP-WEIXIN
@ -268,6 +277,11 @@
})
if (urlResult.code === 0) {
url.value = urlResult.data.url
runSendService(
`${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`,
'channel=0',
true
)
handlePlaySuccess()
} else {
$basic.backAndToast(message)
@ -284,6 +298,12 @@
onUnload(() => {
// #ifdef APP-PLUS
//
if (isVoice.value && recorderManager.value) {
stopRecording()
}
stopSendService(`${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`)
stopService({
id: `${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`
})
@ -460,6 +480,103 @@
return false
}
// #ifdef APP-PLUS
const recorderManager = ref(null)
const recordingFilePath = ref('')
// #endif
const convertAudioFileToUint8Array = filePath => {
// #ifdef APP-PLUS
try {
plus.io.resolveLocalFileSystemURL(filePath, entry => {
entry.file(
file => {
console.log(11111, file)
if (file.size === 0) return
const fileReader = new plus.io.FileReader()
fileReader.onloadend = async evt => {
try {
const base64 = evt.target.result.split(',')[1]
const binaryString = atob(base64)
const byteArray = []
for (let i = 0; i < binaryString.length; i++) {
byteArray[i] = binaryString.charCodeAt(i)
}
const id = `${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`
await dataSend(id, byteArray)
} catch (error) {
console.error('音频数据转换失败:', error)
}
}
fileReader.onerror = () => {
console.error('音频文件读取失败')
}
fileReader.readAsDataURL(file)
},
error => console.error('获取文件对象失败:', error)
)
})
} catch (error) {
console.error('音频文件处理异常:', error)
}
// #endif
}
const initRecorder = () => {
// #ifdef APP-PLUS
recorderManager.value = uni.getRecorderManager()
recorderManager.value.onStart(() => {
console.log('录音开始')
})
recorderManager.value.onError(error => {
console.error('录音出错:', error)
})
recorderManager.value.onStop(res => {
console.log('录音结束:', res)
recordingFilePath.value = res.tempFilePath
convertAudioFileToUint8Array(res.tempFilePath)
})
// #endif
}
//
const startRecording = () => {
// #ifdef APP-PLUS
if (!recorderManager.value) {
initRecorder()
}
recorderManager.value.start({
duration: 60000,
sampleRate: 16000,
format: 'aac'
})
console.log('开始录音')
// #endif
}
//
const stopRecording = () => {
// #ifdef APP-PLUS
if (recorderManager.value) {
recorderManager.value.stop()
console.log('停止录音')
}
// #endif
}
const toggleVoice = () => {
// #ifdef MP-WEIXIN
if (isVoice.value) {
@ -479,7 +596,18 @@
}
}
// #endif
console.log(1111)
// #ifdef APP-PLUS
if (isVoice.value) {
isVoice.value = false
stopRecording()
} else {
uni.vibrateLong()
isVoice.value = true
//
startRecording()
}
// #endif
}
const handlePlaySuccess = () => {

View File

@ -77,3 +77,84 @@ export const stopService = async function (params: IdParams): Promise<Result> {
// console.log(2, error)
// }
// }
export const runSendService = async function (
id: string,
cmd: string,
crypto: boolean
): Promise<Result> {
try {
await XP2P.runSendService(id, cmd, crypto)
console.log('开始发送服务')
return {
code: 0,
data: {},
message: '成功'
}
} catch (error) {
return {
code: -1,
data: {},
message: error.toString()
}
}
}
export const stopSendService = async function (id: string): Promise<Result> {
try {
await XP2P.stopSendService(id, null)
console.log('停止发送服务')
return {
code: 0,
data: {},
message: '成功'
}
} catch (error) {
return {
code: -1,
data: {},
message: error.toString()
}
}
}
export const dataSend = async function (id: string, data: Array<number>): Promise<Result> {
try {
let byteTest = new ByteArray((data.length + 7).toInt())
byteTest.set(0, (0xff).toByte())
byteTest.set(1, (0xf9).toByte())
let profile = 2
let freqIdx = 8
let chanCfg = 1
let packetLen = data.length + 7
byteTest.set(2, (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2)).toByte())
byteTest.set(3, (((chanCfg & 3) << 6) + (packetLen >> 11)).toByte())
byteTest.set(4, ((packetLen & 0x7ff) >> 3).toByte())
byteTest.set(5, (((packetLen & 7) << 5) + 0x1f).toByte())
byteTest.set(6, (0xfc).toByte())
for (let i = 0; i < data.length; i++) {
byteTest.set((i + 7).toInt(), data[i].toByte())
}
console.log(byteTest)
console.log(1, id, byteTest[0], byteTest[1], (data.length + 7).toInt())
const result = await XP2P.dataSend(id, byteTest, (data.length + 7).toInt())
console.log('发送数据', result)
return {
code: 0,
data: {},
message: '成功'
}
} catch (error) {
return {
code: -1,
data: {},
message: error.toString()
}
}
}