SuperAPI AI 工具集

earllm-build

智能体与模型

查看项目

更新于 10-16 04:23

技能介绍

EarLLM One — 构建与维护

概述

EarLLM One 是一个多模块 Android 应用(Kotlin + Jetpack Compose),从蓝牙耳机采集语音,将其转写,发送给大语言模型(LLM),并把回复以语音方式播报回来。本技能用于构建、维护和扩展该项目。

何时使用

当用户提到 "earllm"、"earbudllm"、"earbud app"、"voice pipeline kotlin"、"bluetooth audio android"、"sco microphone" 或相关主题时使用。

不适用场景

任务与 earllm 构建无关时;有更简单、更具体的工具可处理该请求时;用户需要的是无需领域专业知识的通用协助时。

工作原理

项目位置(资料提供路径):C:\Users\renat\earbudllm

模块依赖关系

app ──→ voice ──→ audio ──→ core-logging │ │ ├──→ bluetooth ──→ core-logging └──→ llm ──→ core-logging

模块与关键文件

core-logging:结构化日志与性能跟踪;关键文件 EarLogger.kt、PerformanceTracker.kt。

bluetooth:蓝牙发现、配对、A2DP/HFP 配置文件;关键文件 BluetoothController.kt、BluetoothState.kt、BluetoothPermissions.kt。

audio:音频路由(SCO/BLE)、采集、耳机按键;关键文件 AudioRouteController.kt、VoiceCaptureController.kt、HeadsetButtonController.kt。

voice:STT(SpeechRecognizer + Vosk 桩)、TTS、管线;关键文件 SpeechToTextController.kt、TextToSpeechController.kt、VoicePipeline.kt。

llm:LLM 接口、桩、OpenAI 兼容客户端;关键文件 LlmClient.kt、StubLlmClient.kt、RealLlmClient.kt、SecureTokenStore.kt。

app:UI、ViewModel、Service、设置与全部界面;关键文件 MainViewModel.kt、EarLlmForegroundService.kt,以及 6 个 Compose 界面。

构建配置

SDK:minSdk 26、targetSdk 34、compileSdk 34;构建工具:AGP 8.2.2、Kotlin 1.9.22、Gradle 8.5;Compose BOM:2024.02.00;关键依赖:OkHttp、AndroidX Security(EncryptedSharedPreferences)、DataStore、Media。

目标硬件

手机:Samsung Galaxy S24 Ultra,Android 14、One UI 6.1、Snapdragon 8 Gen 3。

耳机:Xiaomi Redmi Buds 6 Pro,BT 5.3,支持 A2DP/HFP/AVRCP、ANC、LDAC。

关键技术事实(资料称来自官方文档与设备测试)

多数设备的蓝牙 SCO 输入上限为 8kHz 单声道,部分支持 16kHz mSBC;BLE Audio(Android 12+,TYPE_BLE_HEADSET = 26)最高支持 32kHz 立体声,应优先使用 BLE Audio。

startBluetoothSco() 自 Android 12(API 31)起弃用,改用 AudioManager.setCommunicationDevice(AudioDeviceInfo) 与 clearCommunicationDevice();项目已在 AudioRouteController.kt 中实现两条路径。

Samsung One UI 7/8 存在已知 HFP 损坏缺陷:A2DP 播放会破坏 SCO 链路。应用通过静音检测与自动回退到手机内置麦克风来处理。

Redmi Buds 6 Pro 的轻触控制必须在小米耳机配套应用中设为 "Default"(播放/暂停)。若设为 ANC 或自定义功能,事件由耳机内部处理,不会传到 Android。

Android 14+ 需要 FOREGROUND_SERVICE_MICROPHONE 权限,并在服务声明中设置 foregroundServiceType="microphone";RECORD_AUDIO 必须在 startForeground() 之前授予。

VOICE_COMMUNICATION 音源启用 AEC(回声消除),这对防止 TTS 音频输出回灌到 STT 麦克风输入至关重要,未理解回声影响前不要更改该音源。

不要在 SCO 录音的同时播放 TTS(A2DP)。正确顺序是:停止播放 → 切换到 HFP → 录音 → 切换到 A2DP → 播放回复。

数据流

耳机按键轻触 → MediaSession(HeadsetButtonController)→ TapAction.RECORD_TOGGLE → VoicePipeline.toggleRecording() → VoiceCaptureController 采集 PCM(16kHz 单声道)→ stopRecording() 返回 ByteArray → SpeechToTextController.transcribe(pcmData) → LlmClient.chat(messages) → TextToSpeechController.speak(response) → 通过 A2DP 向耳机输出音频。

新增功能

确定受影响模块;先阅读这些模块的现有代码;遵循 StateFlow 模式,通过 MutableStateFlow / StateFlow 暴露状态;若功能需要 UI 集成则更新 MainViewModel.kt;在模块的 src/test/ 目录添加单元测试;若功能改变行为则更新文档。

修改音频采集

VoiceCaptureController.kt 负责 16kHz 单声道 PCM 录音;WAV 头使用十六进制字节值(而非字符字面量)以避免 shell 引号问题;VU 表:RMS 计算 → dB 转换 → 归一化到 0-1 范围;缓冲区大小:getMinBufferSize().coerceAtLeast(4096)。

修改蓝牙行为

BluetoothController.kt 管理发现、配对与配置文件代理;耳机检测使用名称启发式:"buds"、"earbuds"、"tws"、"pods"、"ear";必须同时处理 Bluetooth Classic 与 BLE Audio 两条路径。

修改 LLM 集成

LlmClient.kt 定义接口,保持通用;StubLlmClient.kt 用于离线测试(模拟 500ms 延迟);RealLlmClient.kt 使用 OkHttp 调用 OpenAI 兼容 API;API 密钥存放于 SecureTokenStore.kt(EncryptedSharedPreferences)。

生成构建产物

代码变更后重新生成 ZIP(自项目根目录执行):

powershell -Command "Remove-Item 'EarLLM_One_v1.0.zip' -Force -ErrorAction SilentlyContinue; Compress-Archive -Path (Get-ChildItem -Exclude '*.zip','_zip_verify','.git') -DestinationPath 'EarLLM_One_v1.0.zip' -Force"

运行测试

./gradlew test --stacktrace # 单元测试 ./gradlew connectedAndroidTest # 仪器化测试(需要设备)

Phase 2 路线图

通过耳机与 LLM 进行实时流式语音对话;智能助理:将语音分类为会议、购物清单、备忘录、邮件;集成 Vosk 离线 STT(目前为桩);唤醒词检测,以避免持续占用 SCO;流式 TTS(Android 内置 TTS 不支持流式)。

STT 引擎参考

Vosk small-en:40 MB,WER 约 10%,支持流式,适合实时移动端。

Vosk lgraph:128 MB,WER 约 8%,支持流式,准确率更好。

Whisper tiny:40 MB,WER 约 10-12%,不支持流式(批处理),适合话语后润色。

Android SpeechRecognizer:0 MB,WER 视情况而定,支持流式,适合在线、无额外依赖的场景。

最佳实践

提供关于项目与需求的清晰、具体上下文;应用所有建议到生产代码前先审阅;结合其他互补技能进行全面分析。

常见陷阱

将该技能用于领域之外的任务;未理解自身具体上下文就套用建议;未提供足够项目上下文导致分析不准确。

限制

仅在任务明确匹配上述范围时使用本技能;不要将输出视为环境特定验证、测试或专家评审的替代品;若缺少必需输入、权限、安全边界或成功标准,应停止并请求澄清。