# Talkify 开发指南 本文档旨在为 Talkify 项目的开发者提供全方位的技术指导,涵盖架构设计、核心流程、代码规范及扩展指南。 ## 目录 1. [项目概述](#1-项目概述) 2. [快速开始](#2-快速开始) 3. [技术架构](#3-技术架构) 4. [关键业务流程](#4-关键业务流程) 5. [配置存储方案](#5-配置存储方案) 6. [UI 与设计规范](#6-ui-与设计规范) 7. [扩展指南:添加新引擎](#7-扩展指南添加新引擎) 8. [发布与版本控制](#8-发布与版本控制) --- ## 1. 项目概述 Talkify 是一款基于 Android 的现代化 TTS (Text-to-Speech) 引擎应用。它不产生语音,而是作为**连接器**,将云端大模型(如通义千问、豆包、腾讯云)的高质量语音合成能力,通过 Android 标准 TTS 接口提供给系统和第三方阅读软件使用。 ### 1.1 核心特性 - **云端驱动**:接入阿里云百炼(DashScope)、火山引擎(Volcengine)和腾讯云的流式 API。 - **架构解耦**:采用插件化架构,轻松扩展新的 TTS 服务商。 - **体验流畅**:完整的启动检查流程(网络/权限/电池优化),确保服务在后台稳定运行。 - **现代设计**:完全基于 Jetpack Compose 构建,遵循 Material 3 Expressive 设计规范。 --- ## 2. 快速开始 ### 2.1 环境要求 - **IDE**: Android Studio Ladybug | 2024.2.1+ - **JDK**: JDK 17 - **Android SDK**: API 36 (Android 16) / minSdk 30 ### 2.2 常用命令 项目使用 Gradle 进行构建管理: ```bash # Debug 构建(开发调试) ./gradlew assembleDebug # Release 构建(正式包) ./gradlew assembleRelease # 代码检查 (Lint) ./gradlew lint # 运行单元测试 ./gradlew test # 清理构建缓存 ./gradlew clean ``` ### 2.3 依赖说明 关键依赖版本管理位于 `gradle/libs.versions.toml`: - **UI**: Jetpack Compose BOM 2026.02.01 - **Network**: OkHttp 4.12.0 - **AI SDK**: DashScope SDK 2.22.9 - **Kotlin**: 2.3.10 - **腾讯云TTS**: stream_tts-release-v2.0.16 - **MP3解码**: JLayer 1.0.1 (用于微软TTS引擎的流式MP3解码) --- ## 3. 技术架构 Talkify 严格遵循 **MVVM (Model-View-ViewModel)** 架构模式,配合 **Clean Architecture** 的分层思想,实现逻辑与 UI 的分离。 ### 3.1 核心目录结构 ```text app/src/main/java/com/github/lonepheasantwarrior/talkify/ ├── MainActivity.kt // 【容器】无业务逻辑,仅承载 MainScreen ├── TalkifyApplication.kt // 【应用类】应用初始化、通知通道创建、全局异常处理 ├── GlobalException.kt // 【异常处理】全局未捕获异常处理器 ├── TalkifyCheckDataActivity.kt // 【检查页】引擎数据完整性校验 ├── TalkifyDownloadVoiceData.kt // 【下载页】引擎音色数据下载管理 ├── TalkifySampleTextActivity.kt // 【样本文本】预置示例文本管理 ├── util/ // 【工具层】通用工具类 │ └── TalkifyAudioPlayer.kt // 音频播放工具(语音预览) ├── domain/ // 【领域层】纯 Kotlin 业务接口与模型 │ ├── model/ // 引擎配置、更新信息等数据模型 │ │ ├── BaseEngineConfig.kt // 引擎配置基类 │ │ ├── ConfigItem.kt // 配置项模型 │ │ ├── EngineIds.kt // 引擎 ID 定义 │ │ ├── Qwen3TtsConfig.kt // 通义千问 3 引擎配置 │ │ ├── SeedTts2Config.kt // 豆包 Seed TTS 2 引擎配置 │ │ ├── TencentTtsConfig.kt // 腾讯语音合成引擎配置 │ │ ├── TtsEngineRegistry.kt // 引擎注册中心 │ │ ├── TtsModels.kt // TTS 相关数据模型 │ │ ├── UpdateCheckResult.kt // 更新检查结果模型 │ │ └── UpdateInfo.kt // 更新信息模型 │ └── repository/ // 仓储接口定义 (Repository Interfaces) │ ├── AppConfigRepository.kt // 应用配置仓储接口 │ ├── EngineConfigRepository.kt // 引擎配置仓储接口 │ └── VoiceRepository.kt // 音色仓储接口 ├── infrastructure/ // 【基础设施层】技术实现细节 │ ├── app/ // 应用级设施 │ │ ├── notification/ // 通知管理 │ │ │ ├── NotificationHelper.kt │ │ │ ├── NotificationModels.kt │ │ │ └── TalkifyNotificationHelper.kt │ │ ├── permission/ // 权限管理 │ │ │ ├── ConnectivityMonitor.kt │ │ │ ├── NetworkConnectivityChecker.kt │ │ │ └── PermissionChecker.kt │ │ ├── power/ // 电源管理 │ │ │ └── PowerOptimizationHelper.kt │ │ ├── update/ // 更新检查 │ │ │ └── UpdateChecker.kt // GitHub API 版本检查 │ │ └── repo/ // 配置仓储实现 │ │ └── SharedPreferencesAppConfigRepository.kt │ └── engine/ // 引擎级设施 │ └── repo/ // 引擎仓储实现 │ ├── Qwen3TtsConfigRepository.kt │ ├── Qwen3TtsVoiceRepository.kt │ ├── SeedTts2ConfigRepository.kt │ ├── SeedTts2VoiceRepository.kt │ ├── TencentTtsConfigRepository.kt │ └── TencentTtsVoiceRepository.kt ├── service/ // 【服务层】Android Service 实现 │ ├── TalkifyTtsService.kt // 系统 TTS 服务入口 │ ├── TalkifyTtsDemoService.kt // Demo 预览服务 │ ├── TtsErrorCode.kt // 错误码定义 │ ├── TtsErrorHelper.kt // 错误处理工具 │ ├── TtsLogger.kt // 日志工具 │ ├── engine/ // TTS 引擎统一抽象 │ │ ├── AbstractTtsEngine.kt // 引擎抽象基类 │ │ ├── TtsEngineApi.kt // 引擎接口定义 │ │ ├── TtsEngineFactory.kt // 引擎工厂 │ │ ├── AudioConfig.kt // 音频配置 │ │ └── impl/ // 具体引擎实现 │ │ ├── Qwen3TtsEngine.kt │ │ ├── SeedTts2Engine.kt │ │ ├── TencentTtsEngine.kt │ │ └── MicrosoftTtsEngine.kt └── ui/ // 【表现层】Jetpack Compose UI ├── components/ // 通用 UI 组件 │ ├── BatteryOptimizationDialog.kt │ ├── ConfigBottomSheet.kt │ ├── ConfigEditor.kt │ ├── EngineSelector.kt │ ├── MarkdownText.kt │ ├── NetworkBlockedDialog.kt │ ├── NotificationPermissionDialog.kt │ ├── PermissionDialog.kt │ ├── UpdateDialog.kt │ └── VoicePreview.kt ├── screens/ // 页面级 Composable │ ├── MainScreen.kt // 主界面(含默认引擎提示横栏、关于应用提示横栏) │ ├── AboutScreen.kt // 关于页面(含检查更新、打赏功能) │ └── DefaultEngineBanner.kt // 默认引擎提示横栏组件 ├── viewmodel/ // 状态管理 │ └── MainViewModel.kt └── theme/ // Material 3 主题定义 ├── Color.kt ├── Theme.kt └── Type.kt ``` ### 3.2 架构设计详解 #### 3.2.1 启动流程架构 (MVVM) 应用启动涉及多个复杂的异步检查步骤。为了避免 `MainActivity` 代码膨胀和弹窗冲突,我们采用 **State Machine(状态机)** 模式: - **ViewModel (`MainViewModel`)**: 维护单一真实数据源 `uiState` (`StartupState`)。它按顺序调度检查任务,控制流程流转。 - **View (`MainScreen`)**: 响应式 UI。根据 `uiState` 的变化(如 `CheckingNetwork`, `RequestingBattery`)动态切换显示的弹窗或内容。 - **Activity (`MainActivity`)**: 极简容器,不处理任何逻辑。 #### 3.2.2 TTS 引擎架构 (Plugin-based) 引擎模块采用接口隔离设计,确保新增引擎不影响现有代码: - **`TtsEngineApi`**: 定义标准行为(合成、停止、销毁)。 - **`AbstractTtsEngine`**: 提供通用实现(日志、状态检查)。 - **`TtsEngineRegistry`**: 引擎注册中心,管理所有可用引擎。 - **`TtsEngineFactory`**: 引擎实例工厂,根据 ID 创建对应引擎。 #### 3.2.3 应用初始化架构 - **`TalkifyApplication`**: 应用入口类,负责: - 初始化 `TalkifyAppHolder` 全局上下文 - 注册 `TalkifyExceptionHandler` 全局异常处理器 - 预创建所有通知通道(`ensureNotificationChannel`) --- ## 4. 关键业务流程 ### 4.1 应用启动自检流程 应用冷启动时,`MainViewModel` 会严格按照以下顺序执行串行检查。任何一步受阻都会暂停流程,直到用户解决或授权。 ```mermaid graph TD Start[应用启动] --> Step1[1. 检查网络连通性] Step1 -- 失败 --> DialogNet[显示全屏网络阻断页] DialogNet -- 去设置 --> SysSettings[系统设置] Step1 -- 成功 --> Step2[2. 检查通知权限] Step2 -- 无权限 --> DialogNotif[请求通知权限] DialogNotif -- 授权/跳过 --> Step3 Step2 -- 有权限 --> Step3[3. 检查电池优化] Step3 -- 受限 --> DialogBattery[请求允许后台运行] DialogBattery -- 去设置/跳过 --> Step4 Step3 -- 无限制 --> Step4[4. 检查应用更新] Step4 -- 发现新版 --> DialogUpdate[显示更新弹窗] Step4 -- 完成 --> Step5[5. 检查默认引擎状态] Step5 -- 非默认引擎 --> BannerDefault[显示设为默认引擎横栏] Step5 -- 已是默认引擎 --> MainUI[进入主界面] BannerDefault -- 点击横栏 --> TtsSettings[跳转系统 TTS 设置] TtsSettings -- 返回应用 --> Step5[重新检查默认引擎状态] MainUI -- 应用恢复前台 --> Step5[重新检查默认引擎状态] ``` ### 4.2 权限管理策略 为了保障 TTS 服务的核心体验,我们对关键权限采取**持续引导**策略: 1. **允许后台运行 (忽略电池优化)** * **必要性**:TTS 服务通常在后台运行,若被系统电池优化杀掉进程或切断网络,会导致朗读中断。 * **策略**:应用不保存"以后再说"的状态。只要检测到未忽略电池优化,**每次启动都会提示**。 * **交互**:点击"去设置"会尝试直接弹窗,失败则跳转系统列表页。 2. **通知权限** * **必要性**:用于在前台服务运行时显示"正在朗读"通知,以及错误提示。 * **策略**:同上,未授权则每次启动均提示。 ### 4.3 语音合成流程 1. 第三方 App 调用 Android `TextToSpeech` API。 2. `TalkifyTtsService` 接收请求,解析文本。 3. 委托给当前选中的 `TtsEngine` 实现类(如 `Qwen3TtsEngine`)。 4. 引擎通过网络流式请求音频数据。 5. 数据通过 `SynthesisCallback` 写入 Android 音频管道播放。 ### 4.4 音频播放机制 - **WakeLock**: 防止合成过程中设备进入休眠状态 - **WifiLock**: 确保 WiFi 保持高性能模式,保障流式传输稳定性 - **前台服务**: 使用 `START_STICKY` 机制确保服务被系统杀死后能够自动重启 - **动态音频配置**: 播放器根据实际音频数据动态创建,确保采样率、格式和声道数与音频数据完全匹配 ### 4.5 音频采样率动态匹配机制 为了确保音频播放质量,Talkify 实现了智能的音频采样率匹配机制: #### 4.5.1 预览服务 (TalkifyTtsDemoService) - **动态播放器创建**: 在收到第一个音频数据时,根据实际音频参数创建播放器 - **实时参数匹配**: 播放器使用与音频数据相同的采样率、格式和声道数 - **架构优势**: 高内聚、低耦合,适用于所有支持动态采样率的TTS引擎 #### 4.5.2 系统TTS服务 (TalkifyTtsService) - **延迟初始化**: 系统回调在收到第一个音频数据时初始化,而非合成开始前 - **参数同步**: 确保系统播放器配置与实际音频数据完全匹配 - **符合规范**: 保持同步操作,不违反Android TTS服务规范 #### 4.5.3 腾讯云TTS引擎优化 - **音色采样率动态匹配**: 每个音色使用其最高支持的采样率(8k/16k/24k 优先选择 24k) - **文本分块处理**: 支持长文本自动分块(每块最多 300 字符),在句子/标点处智能分割 - **参数映射**: 正确映射语速(0-200)到腾讯云离散值(-2到6)和音量(0.0-1.0)到腾讯云范围(-10到10) - **官方SDK集成**: 使用腾讯云官方流式TTS SDK(stream_tts-release-v2.0.16),提供更稳定的连接和更好的性能 #### 4.5.4 通义千问3语音合成引擎优化 - **WAV头识别与剥离**:阿里云接口返回的音频流可能包含44字节的WAV文件头,需要精准识别并安全剥离,防止首字破音 - **双重保险机制**: 1. **请求级干预**:在 `buildConversationParam` 中显式添加 `format=pcm` 参数,请求云端直接返回纯净PCM数据 2. **代码级拦截**:在接收到第一个音频包时,通过检查 `RIFF` 和 `WAVE` 标识来识别WAV头,如有则安全切除前44字节 - **首字破音修复**:通过剥离WAV文件头,避免了将元数据当作波形数据播放导致的刺耳"滋"声 #### 4.5.5 微软语音合成引擎特点 - **无需API Key**: 直接使用微软Edge TTS服务,无需配置任何密钥 - **WebSocket通信**: 使用WebSocket协议进行流式音频传输 - **DRM处理**: 实现了微软TTS的Sec-MS-GEC token生成和DRM验证 - **真正的流式播放**: 使用JLayer库实现MP3流式解码,支持边接收边播放 - **管道架构**: 使用PipedInputStream/PipedOutputStream建立音频数据管道 - **协程优化**: 使用CoroutineScope替代GlobalScope,避免内存泄漏 - **现代同步机制**: 使用CompletableDeferred替代Object.wait(),实现非阻塞等待 - **动态采样率**: 从MP3 Header中动态提取真实采样率,避免"变声器"效应 - **64KB缓冲区**: 扩容管道缓冲区,彻底解放 OkHttp 网络接收能力,防止接收线程阻塞拖慢网络 - **完善的异常处理**: 支持优雅停止和错误提示 - **多语言支持**: 支持中文、英文、日文、韩文、法文、德文、西班牙文等多种语言 #### 4.5.6 微软语音合成引擎性能优化(TTFB优化) 针对首字发声延迟(TTFB, Time To First Byte)的深度优化: 1. **DNS 预热 (DNS Pre-warming)** - 在引擎实例化时(`init` 代码块),开一个后台线程提前去解析微软服务器的域名 - 真正开始合成时,可以完全省去几十到上百毫秒的 DNS 耗时 2. **零拷贝与降级内存分配** - 使用 `ByteBuffer` 直接读取,避免多次 `ByteArray` 拷贝 - 使用 `String.contains` 快速比对,避免正则字符串切分和 Map 创建 - 极大减少了内存分配和 CPU 消耗,降低 GC 停顿 3. **PCM 转换加速 (NIO 优化)** - JLayer 解码出的 `ShortArray` 转 `ByteArray`,使用 Java NIO 的 `ByteBuffer.asShortBuffer().put()` - 底层内存块拷贝,效率远高于循环单字节位运算赋值 4. **线程调度优化** - MP3 解码属于标准的 CPU 密集型任务,将 `decodeJob` 的执行协程调度器从 `Dispatchers.IO` 改为 `Dispatchers.Default` - 减少线程上下文切换的等待 5. **管道缓冲区策略** - 纠正误区:`PipedInputStream` 只要有 1 个字节写入就会立刻返回,不会等填满才输出 - 64KB 缓冲区确保网络下载速度快于解码速度时,OkHttp 的网络读取线程不会被阻塞 ### 4.6 默认引擎检测 为了提供更好的用户体验,应用会在启动时检查 Talkify 是否已设置为系统的默认 TTS 引擎: - **检测时机**: - 应用启动完成时 - 应用从后台恢复到前台时 - **检测逻辑**:通过 `TextToSpeech.defaultEngine` 获取当前系统默认引擎,与 Talkify 的包名进行比较 - **提示展示**:若非默认引擎,显示 `DefaultEngineBanner` 提示横栏 - **交互方式**:点击横栏任意位置跳转到系统 TTS 设置页面 - **状态刷新**:用户设置完成后返回应用时,自动重新检测并更新横栏显示状态 ### 4.7 关于页面与新功能提示 应用提供关于页面供用户了解应用信息,同时通过提示横栏引导用户发现新功能: #### 4.7.1 关于页面入口 - **入口方式**:点击主界面顶部的 "Talkify" 标题文字即可打开关于页面 - **页面内容**: - 应用版本号 - GitHub 开源仓库链接 - 检查更新功能(手动触发) - 打赏功能(支持微信和支付宝二维码保存到相册) - **导航实现**:使用 Jetpack Navigation Compose,支持页面切换动画和预测性返回手势 #### 4.7.2 关于应用提示横栏 为了引导用户发现关于页面,应用在主界面顶部显示提示横栏: - **显示条件**: - 用户从未打开过关于页面 (`hasOpenedAboutPage` 为 false) - 应用启动流程已完成 (`startupState == StartupState.Completed`) - **临时关闭**:点击横栏可临时关闭提示(本次会话中不再显示) - **永久消失**:当用户通过点击 Talkify 标题真正打开关于页面后,提示横栏将永久消失 - **状态持久化**:关于页面打开状态存储在 `SharedPreferences` 中,键名为 `has_opened_about_page` #### 4.7.3 检查更新功能 - **启动时检查**:应用启动时自动检查 GitHub Releases 是否有新版本 - **手动检查**:关于页面提供"检查更新"按钮,用户可手动触发更新检查 - **API 调用**:使用 GitHub REST API (`https://api.github.com/repos/{owner}/{repo}/releases/latest`) - **错误处理**: - 403/404:视为无可用更新 - 5xx 服务器错误:提示用户稍后再试 - 网络超时:提示网络问题 #### 4.7.4 打赏功能 - **入口**:关于页面中的"打赏支持"按钮 - **渠道选择**:底部抽屉提供微信和支付宝两个选项 - **二维码保存**: - 从 `res/drawable` 目录读取二维码图片 - 使用 MediaStore API 保存到手机相册(兼容 Android 11+) - 需要 `READ_MEDIA_IMAGES` 权限(Android 13+)或 `READ_EXTERNAL_STORAGE`(Android 11-12) - **提示信息**:保存成功后显示操作说明,引导用户使用对应 App 扫码支付 --- ## 5. 配置存储方案 应用采用轻量级的 `SharedPreferences` 进行配置持久化,统一通过 `SharedPreferencesAppConfigRepository` 管理: 1. **应用级配置 (`AppConfigRepository`)** - 存储:统一的 SharedPreferences 文件 (`talkify_app_config`) - 内容: - 当前选中的引擎 ID (`selected_engine`) - 是否已请求过通知权限 (`has_requested_notification`) - 是否已打开过关于页面 (`has_opened_about_page`) 2. **引擎级配置 (`EngineConfigRepository`)** - 存储:各引擎独立的配置键值对 - 内容:各引擎独立的 API Key、Voice ID、音色配置等。 - 扩展性:每个引擎配置类继承自 `BaseEngineConfig`,实现配置隔离。 --- ## 6. UI 与设计规范 项目全面拥抱 **Jetpack Compose** 和 **Material 3 Expressive** 风格。 ### 6.1 弹窗规范 为了保持系统一致性和良好的阅读体验: - **标题**:简明扼要,使用 `HeadlineSmall` 样式。 - **正文**:说明性文字必须使用 **左对齐 (`TextAlign.Start`)**,避免大段文字居中造成的阅读困难。 - **操作**:主要操作(如"去设置")在右侧,次要操作(如"以后再说")在左侧。 ### 6.2 资源管理 - **多语言**:所有文本提取至 `res/values/strings.xml`,严禁在代码中硬编码字符串。 - **声音数据**:各引擎支持的音色列表定义在 `res/values/xxx-voices.xml` 中,便于独立更新。 - **示例文本**:预置朗读样本文本定义在 `res/values/demo_texts.xml` 中。 ### 6.3 主题规范 - **颜色**:遵循 Material 3 色彩系统,使用 `Color.kt` 定义应用级配色。 - **字体**:使用 `Type.kt` 统一定义字体样式和排版规范。 --- ## 7. 扩展指南:添加新引擎 若需接入新的 TTS 服务商,请遵循以下步骤: 1. **定义配置**:在 `domain/model` 下创建 `XxxConfig`,继承 `BaseEngineConfig`。 2. **实现引擎**:在 `service/engine/impl` 下创建 `XxxTtsEngine`,继承 `AbstractTtsEngine`,实现合成逻辑。 3. **实现仓储**:在 `infrastructure/engine/repo` 下创建对应的 Voice 和 Config 仓储实现。 4. **注册引擎**: - 在 `EngineIds` 中添加引擎ID枚举。 - 在 `TtsEngineFactory` 中注册引擎实例创建逻辑。 - 在 `EngineSelector` UI 中添加分支支持(如果 UI 需要特殊处理)。 5. **添加音色资源**:在 `res/values` 下创建 `xxx-voices.xml` 定义支持的音色列表。 6. **编写测试**:在 `app/src/test/java` 下编写单元测试验证引擎功能。 > **示例**:微软语音合成引擎(microsoft-tts)实现了无需API Key的TTS服务,配置类为 `MicrosoftTtsConfig`,引擎实现为 `MicrosoftTtsEngine`,音色定义在 `microsoft-tts-voices.xml`。 --- ## 8. 发布与版本控制 ### 8.1 版本号规范 - **versionName**: `Major.Minor.Patch` (例如 1.0.17) - **versionCode**: 单调递增整数 (例如 19) ### 8.2 发布检查清单 - [ ] 确保 `gradle/libs.versions.toml` 中的库版本为最新稳定版。 - [ ] 运行 `lint` 检查潜在问题。 - [ ] 运行 `test` 确保单元测试通过。 - [ ] 验证启动全流程(全新安装、覆盖安装)。 - [ ] 验证所有引擎的 API Key 配置能否正常保存和读取。 --- ## 9. 示例代码与测试 ### 9.1 示例代码 项目提供以下示例代码供参考: - `examples/AudioParameters.java`: 音频参数配置示例 - `examples/ProcessingReal‑timePlayback.java`: 实时播放处理示例 - `examples/StreamingOutputRequest.java`: 流式输出请求示例 - `examples/tts_http_demo.py`: Python HTTP 流式合成示例 ### 9.2 测试覆盖 - **单元测试**: `app/src/test/java/` 目录 - `ExampleUnitTest.kt`: 基础单元测试 - `TtsErrorCodeTest.kt`: 错误码测试 - **仪表盘测试**: `app/src/androidTest/java/` 目录 - `ExampleInstrumentedTest.kt`: 仪器化测试 --- *文档最后更新时间: 2026年03月08日* *对应应用版本: 1.0.19*