Files
smartDriveEEUniApp/docs/bluetooth-recorder-implementation.md
2026-01-09 19:41:18 +08:00

9.1 KiB
Raw Permalink Blame History

蓝牙录音设备接入技术方案

一、概述

本文档详细说明如何在uni-app项目中实现蓝牙录音设备的连接、数据接收和文件处理功能。

二、技术架构

2.1 技术栈

  • 框架: uni-app (Vue 3)
  • 平台: APP端 (Android/iOS)
  • 蓝牙协议: BLE (低功耗蓝牙) / 经典蓝牙
  • 音频格式: PCM (可根据设备调整)

2.2 核心组件

  1. 蓝牙工具类 (common/bluetooth.js)

    • 蓝牙适配器管理
    • 设备搜索与连接
    • 数据接收与处理
    • 连接状态管理
  2. 蓝牙录音页面 (pages/bluetooth-recorder/bluetooth-recorder.vue)

    • 设备搜索界面
    • 连接管理界面
    • 数据监控界面
    • 文件保存与上传

三、实现步骤

步骤1: 配置权限

manifest.json 中添加蓝牙相关权限:

Android权限:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

iOS权限: 在 manifest.jsonapp-plus -> ios 配置中添加:

"privacyDescription": {
  "NSBluetoothAlwaysUsageDescription": "需要蓝牙权限以连接录音设备",
  "NSBluetoothPeripheralUsageDescription": "需要蓝牙权限以连接录音设备",
  "NSLocationWhenInUseUsageDescription": "需要位置权限以搜索蓝牙设备"
}

步骤2: 初始化蓝牙适配器

import bluetoothRecorder from '@/common/bluetooth.js'

// 初始化蓝牙适配器
await bluetoothRecorder.initBluetoothAdapter()

步骤3: 搜索蓝牙设备

// 开始搜索
await bluetoothRecorder.startScan({
  allowDuplicatesKey: false,  // 不允许重复上报
  interval: 0                 // 上报间隔
})

// 监听设备发现
bluetoothRecorder.onDeviceFound = (device) => {
  console.log('发现设备:', device.name, device.deviceId)
}

步骤4: 连接蓝牙设备

// 连接设备
await bluetoothRecorder.connectDevice(deviceId)

// 监听连接状态
bluetoothRecorder.onDeviceConnected = (deviceId) => {
  console.log('设备连接成功:', deviceId)
}

bluetoothRecorder.onDeviceDisconnected = (deviceId) => {
  console.log('设备断开:', deviceId)
}

步骤5: 接收音频数据

连接成功后,系统会自动:

  1. 获取设备的服务列表
  2. 查找可通知的特征值
  3. 启用特征值通知
  4. 监听数据变化
// 监听音频数据接收
bluetoothRecorder.onAudioDataReceived = (data) => {
  // data.data: Base64编码的音频数据
  // data.arrayBuffer: ArrayBuffer格式的音频数据
  // data.timestamp: 时间戳
  
  console.log('收到音频数据:', data)
}

步骤6: 处理音频数据

6.1 保存到本地文件

// 获取所有音频数据
const audioData = bluetoothRecorder.mergeAudioData()

// 转换为ArrayBuffer
const arrayBuffer = uni.base64ToArrayBuffer(audioData)

// 保存到文件系统
const fs = uni.getFileSystemManager()
const filePath = `${uni.env.USER_DATA_PATH}/recording.pcm`

fs.writeFile({
  filePath: filePath,
  data: arrayBuffer,
  success: () => {
    console.log('文件保存成功:', filePath)
  }
})

6.2 上传到服务器

// 准备上传数据
const audioData = bluetoothRecorder.mergeAudioData()
const arrayBuffer = uni.base64ToArrayBuffer(audioData)

// 上传到服务器
const formData = {
  audio: arrayBuffer,
  fileName: 'recording.pcm',
  deviceId: deviceId
}

const res = await post('/api/audioManagement/uploadBluetoothAudio', formData, {
  header: {
    'Content-Type': 'multipart/form-data'
  }
})

四、蓝牙设备协议说明

4.1 服务UUID和特征值

不同的蓝牙录音设备可能使用不同的服务UUID和特征值。常见的有

标准音频服务:

  • 服务UUID: 0000110a-0000-1000-8000-00805f9b34fb (A2DP)
  • 特征值UUID: 设备特定

自定义服务:

  • 需要根据设备厂商提供的文档配置

4.2 数据格式

蓝牙设备传输的音频数据通常是:

  • 格式: PCM (脉冲编码调制)
  • 采样率: 8kHz, 16kHz, 44.1kHz 等
  • 位深: 16bit
  • 声道: 单声道或立体声

4.3 数据包处理

蓝牙BLE设备通常以数据包形式传输音频

  • 每个数据包大小: 20字节 (BLE限制)
  • 需要将多个数据包合并为完整的音频流
  • 可能需要处理数据包丢失和重排序

五、使用示例

5.1 完整使用流程

import bluetoothRecorder from '@/common/bluetooth.js'

// 1. 初始化
await bluetoothRecorder.initBluetoothAdapter()

// 2. 搜索设备
bluetoothRecorder.onDeviceFound = (device) => {
  console.log('发现设备:', device)
}

await bluetoothRecorder.startScan()

// 3. 连接设备
await bluetoothRecorder.connectDevice(deviceId)

// 4. 接收数据
bluetoothRecorder.onAudioDataReceived = (data) => {
  // 处理音频数据
  console.log('收到数据:', data)
}

// 5. 保存数据
const audioData = bluetoothRecorder.mergeAudioData()
// ... 保存或上传逻辑

// 6. 断开连接
await bluetoothRecorder.disconnectDevice()

// 7. 清理资源
await bluetoothRecorder.closeBluetoothAdapter()

5.2 页面集成

在需要使用的页面中:

<template>
  <view>
    <button @click="connectBluetooth">连接蓝牙设备</button>
    <button @click="saveAudio">保存录音</button>
  </view>
</template>

<script>
import bluetoothRecorder from '@/common/bluetooth.js'

export default {
  methods: {
    async connectBluetooth() {
      await bluetoothRecorder.initBluetoothAdapter()
      await bluetoothRecorder.startScan()
    },
    
    async saveAudio() {
      const audioData = bluetoothRecorder.mergeAudioData()
      // 保存逻辑
    }
  }
}
</script>

六、注意事项

6.1 权限要求

  1. Android 12+: 需要 BLUETOOTH_SCANBLUETOOTH_CONNECT 权限
  2. 位置权限: 搜索蓝牙设备需要位置权限Android要求
  3. 运行时权限: 需要在代码中动态申请权限

6.2 平台差异

  1. iOS:

    • 需要用户明确授权蓝牙权限
    • 后台运行限制更严格
    • 某些蓝牙功能可能受限
  2. Android:

    • 权限管理更复杂
    • 不同版本API差异较大
    • 需要处理权限动态申请

6.3 性能优化

  1. 数据缓冲: 使用缓冲区避免频繁处理小数据包
  2. 内存管理: 及时清理不需要的数据,避免内存溢出
  3. 连接管理: 合理管理连接状态,避免资源泄漏

6.4 错误处理

常见错误及处理:

  1. 蓝牙未开启: 提示用户开启蓝牙
  2. 权限被拒绝: 引导用户到设置页面授权
  3. 设备连接失败: 检查设备是否在范围内,是否已被其他设备连接
  4. 数据接收中断: 实现重连机制

七、调试方法

7.1 日志输出

工具类已内置详细日志,可通过控制台查看:

  • 设备搜索日志
  • 连接状态日志
  • 数据接收日志
  • 错误日志

7.2 测试步骤

  1. 确保手机蓝牙已开启
  2. 确保蓝牙录音设备已开启并处于可发现状态
  3. 运行应用,点击"开始搜索"
  4. 等待发现设备后,点击设备进行连接
  5. 连接成功后,观察数据接收情况
  6. 测试保存和上传功能

八、扩展功能

8.1 音频格式转换

如果需要转换为其他格式如MP3、WAV可以使用

  • 前端转换库(如 lamejs
  • 后端转换服务

8.2 实时播放

可以结合 uni.createInnerAudioContext() 实现实时播放接收到的音频数据。

8.3 数据加密

如果需要对传输的音频数据进行加密,可以在接收数据后进行解密处理。

九、常见问题

Q1: 搜索不到设备?

  • 检查蓝牙是否开启
  • 检查位置权限是否授权
  • 检查设备是否处于可发现状态
  • 尝试重启蓝牙

Q2: 连接失败?

  • 检查设备是否在范围内
  • 检查设备是否已被其他应用连接
  • 检查设备是否支持BLE
  • 查看错误日志获取详细信息

Q3: 接收不到数据?

  • 检查是否已启用特征值通知
  • 检查服务UUID和特征值UUID是否正确
  • 检查设备是否正在发送数据
  • 查看设备文档确认数据格式

Q4: 数据不完整?

  • 检查数据包是否丢失
  • 实现数据包校验和重传机制
  • 检查缓冲区是否溢出

十、参考资料

十一、更新日志

  • 2024-01-XX: 初始版本,实现基础蓝牙连接和数据接收功能
  • 后续根据实际使用情况进行优化和扩展