← 文档库
📄 文档learn/其他业务/2026-06-27-文档听书TTS功能/article.md
🌱 创建于2026-06-27 03:57
✏️ 修改于2026-06-27 04:01
👁️ 浏览量—
🔗 短链接/~learn/s/6b6fda74
🔐 可见性

文档听书 TTS 功能 — 技术实现详解

概述

为文档浏览模块增加了"听书"能力:点击按钮即可用豆包语音合成朗读 Markdown 文档内容,支持三音色混音、语速/音高调节、断点续听、进度条拖拽。后端对接火山引擎豆包语音大模型 V3 HTTP API,前端使用 HTML5 Audio API 播放。

核心架构

浏览器(前端)                               Python HTTP Server(后端)                   火山引擎 TTS API
-----------                               ------------------------                   -----------------
DOC_PAGE 模板                              unified_server.py                         openspeech.bytedance.com
├─ JS: ttsExtractChunks() 提取文本片段       ├─ GET /api/tts/voices ──► JSON 声音列表     /api/v3/tts/unidirectional
├─ JS: ttsBuildUrl() 构造请求              ├─ GET /api/tts?text=...──► MP3 音频流      ├─ x-api-key 鉴权
├─ JS: ttsPlayChunk() 播放+预加载下一段       │   └─ TTSService.synthesize()           ├─ custom_mix_bigtts 混音
├─ JS: ttsSaveProgress() → localStorage    │       ├─ SQLite 缓存查询/写入              ├─ speech_rate [-50, 100]
├─ CSS: 底部固定悬浮播放器                      │       ├─ _call_api() → HTTP POST        └─ post_process.pitch [-12,12]
└─ HTML: 设置面板(模式/声音/语速/音高/混音比例)      │       └─ 流式 JSON Lines → base64 解码
                                           └─ tts_cache.db(SQLite WAL)

关键技术点

1. 火山引擎豆包语音 V3 HTTP API

请求结构

{
  "user": {"uid": "aohan_quant"},
  "req_params": {
    "text": "要合成的文本",
    "speaker": "custom_mix_bigtts",
    "audio_params": {
      "format": "mp3",
      "sample_rate": 24000,
      "speech_rate": -30
    },
    "mix_speaker": {
      "speakers": [
        {"source_speaker": "zh_female_cancan_mars_bigtts", "mix_factor": 0.6},
        {"source_speaker": "zh_female_sajiaonvyou_moon_bigtts", "mix_factor": 0.1},
        {"source_speaker": "zh_female_meilinvyou_moon_bigtts", "mix_factor": 0.3}
      ]
    },
    "additions": "{\"post_process\":{\"pitch\":7}}"
  }
}

响应解析

API 返回流式 JSON Lines,每行一个 JSON 对象:

将所有 code=0 的 data 解码后拼接即得完整 MP3。

2. 多音色混音

使用 custom_mix_bigtts speaker + mix_speaker.speakers[] 实现最多 3 种音色同时混合:

复制声音 替代公共音色 混音因子 voice_type
------------------------------------------
宝宝冯 灿灿/Shiny 0.6 zh_female_cancan_mars_bigtts
奶音甜妹 撒娇甜妹 0.1 zh_female_sajiaonvyou_moon_bigtts
慵懒女友 魅力女友 0.3 zh_female_meilinvyou_moon_bigtts

> 注意:如果用户在豆包 App 中使用了"声音复刻"功能创建了专属声音,其 voice_id 为 S_xxx 或 ICL_xxx 格式,可在火山引擎控制台 → 音色库 → 我的音色中获取,然后替换 default_mix 中的 source_speaker。

3. 参数映射(用户配置 → API 参数)

用户截图中的配置到 API 参数的映射关系:

用户配置 API 参数 转换公式
---------------------------
语速 0.70 speech_rate round((speed - 1.0) * 100) → -30
音高 1.5 post_process.pitch 半音单位,范围 [-12, 12],1.5 倍音高 ≈ +7 半音

speed 范围 [0.5, 2.0],对应 speech_rate [-50, 100]。speech_rate=0 表示正常语速。

4. SQLite 本地音频缓存

为避免重复合成相同内容,通过 SQLite 本地缓存合成结果:

5. 前端文本清洗与分段

文本提取规则(ttsExtractChunks)

从 Markdown 渲染后的 HTML DOM 中提取纯文本,跳过以下内容:

分段策略(TTSService.split_text)

6. 前端播放引擎

核心状态

tts_chunks = [];     // 文本片段数组
tts_idx = 0;         // 当前播放片段索引
tts_audio = null;    // HTML5 Audio 对象
tts_playing = false; // 播放状态

播放流程

断点续听

7. 前端 UI 组件

播放器栏(底部固定悬浮)

┌──────────────────────────────────────────────────────────┐
│ 项目架构文档                                        ⚙️ □  │
│ [▶] ────●──────────── 02:00 / 05:30                     │
└──────────────────────────────────────────────────────────┘

设置面板(点击 ⚙️ 展开)

浏览器兼容性

8. 后端路由

路由 方法 功能 返回
------------------------
/api/tts/voices GET 获取可用声音列表 JSON
/api/tts?text=&voice=&speed=&pitch=&mix= GET 合成音频 audio/mpeg
/api/tts/stats GET 缓存统计 JSON

核心文件

文件 角色
------------
adata/aohan/quant/utils/tts_service.py TTS 后端服务:API 调用、缓存、分段、声音列表
unified_server.py Web 服务器:3 个 TTS 路由 + DOC_PAGE 模板前端代码
api_balance_config.json API 密钥配置(volcengine.tts.*)
adata/aohan/quant/db/tts_cache.db SQLite 音频缓存(自动创建)

安全性

▶ 📜 变更历史(2 次提交)

35af6cd2026-06-27 04:01chore: 将文档听书TTS技术文档移至 learn/其他业务/
cf0c3c82026-06-27 03:57feat: 文档听书TTS功能 — 豆包语音合成朗读
🍃quant 知识库
by 伊甸园和枫

🔊 播放设置

勾选音源后调节配比,总和自动归一化
已选 0 个 · 合计:0%
合成中...
00:00/00:00
1.0x

分享图片

生成中...