docs(m4): 收敛文档/dock/changelog,env 减到 4 个引导变量
M3 后所有业务配置(api_key/resource_id/speaker/format/sample_rate/...)已搬入 数据库,env 只剩 4 个启动引导参数(setup 前 / DB 还不存在时必需): 1. TTS_ADMIN_KEY 安装 token(/api/setup 鉴权) 2. TTS_DB_PATH DB 路径(可选) 3. PORT 监听端口(可选) 4. OPENAI_TTS_API_KEY OpenAI 端鉴权(可选) 之前 .env.example 仍列出 11 个 BYTEDANCE_TTS_* env,误导用户把配置填 env 里 (实际被 DB 覆盖,改了不生效)。 改: - .env.example: 只列 4 个 bootstrap env,其他写"通过 WebUI 设置" - docker-compose.yml: env 块只透传 4 个,加 named volume 持久化 tts.db (无 volume = 容器重启丢所有配置) - Dockerfile: 准备 /data 目录,appuser 可写 - CHANGELOG.md: 新文件,记 v0.2.0 全部 M0-M3 + 这次修复 不动: - README.md(M4 第 5 步独立 commit,文件大) - 集成测试(M4 第 6 步) e2e 验证: - go build ./... 通过 - 旧 .env 文件如果存在仍然兼容(env var 作为 DB 缺失时的 fallback) 未 push (待 M4 全部完成)
This commit is contained in:
+26
-62
@@ -1,69 +1,33 @@
|
|||||||
# 字节火山引擎 TTS v3 API 配置示例
|
# 字节火山引擎 TTS v3 → OpenAI 兼容接口
|
||||||
# 将此文件复制为 .env 并填入实际配置
|
# 配置文件示例 · 复制为 .env 后填入
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# 必需的环境变量
|
# 启动引导环境变量(4 个,启动前必看)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
# 业务配置(api_key / resource_id / speaker / 格式 / 采样率 ...)通过 WebUI 设置,
|
||||||
|
# 不再需要在这里配。M3 起所有 BYTEDANCE_TTS_* 已搬入数据库。
|
||||||
|
|
||||||
# 火山引擎新版控制台获取的 API Key
|
# 1. 安装 token(必设,首次 /setup 时校验)
|
||||||
BYTEDANCE_TTS_API_KEY=your_api_key_here
|
# 留空 = 不设 token,任何人可调 /api/setup(适合本地开发)
|
||||||
|
# 正式部署务必设复杂字符串
|
||||||
|
TTS_ADMIN_KEY=
|
||||||
|
|
||||||
# 资源信息ID(决定使用1.0还是2.0模型)
|
# 2. 数据库路径(可选, 默认 ./tts.db)
|
||||||
# 复刻 2.0 音色(seed-icl-2.0)
|
# Docker 部署务必改成挂载路径,例: /data/tts.db
|
||||||
BYTEDANCE_TTS_RESOURCE_ID=seed-icl-2.0
|
# TTS_DB_PATH=/data/tts.db
|
||||||
|
|
||||||
# 发音人(音色)ID
|
# 3. 服务监听端口(可选, 默认 8080)
|
||||||
BYTEDANCE_TTS_SPEAKER=your_speaker_id_here
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# 可选的环境变量
|
|
||||||
# ==========================================
|
|
||||||
|
|
||||||
# 单次合成超时,默认30s
|
|
||||||
BYTEDANCE_TTS_TIMEOUT=30s
|
|
||||||
|
|
||||||
# 上游实际请求的音频格式:mp3 / pcm / ogg_opus
|
|
||||||
# 客户端要求 wav 时,内部自动转 pcm 上游 + 本地拼 WAV 头
|
|
||||||
BYTEDANCE_TTS_FORMAT=mp3
|
|
||||||
|
|
||||||
# 上游采样率:8000/16000/22050/24000/32000/44100/48000
|
|
||||||
BYTEDANCE_TTS_SAMPLE_RATE=24000
|
|
||||||
|
|
||||||
# MP3 比特率(可选),仅 MP3 生效
|
|
||||||
# BYTEDANCE_TTS_BIT_RATE=128000
|
|
||||||
|
|
||||||
# 复刻 2.0 子模型(可选),留空则使用控制台默认值
|
|
||||||
# seed-tts-2.0-standard:标准版,延时更优
|
|
||||||
# seed-tts-2.0-expressive:表现力增强版,支持 QA / Cot
|
|
||||||
# BYTEDANCE_TTS_MODEL=seed-tts-2.0-standard
|
|
||||||
|
|
||||||
# 复刻 2.0 模型类型(可选,推荐显式指定)
|
|
||||||
# 4 = ICL V2,5 = ICL V3
|
|
||||||
# BYTEDANCE_TTS_MODEL_TYPE=4
|
|
||||||
|
|
||||||
# 非中文/英文合成时指定语种(可选)
|
|
||||||
# zh-cn / en / ja / es-mx / id / pt-br / ko
|
|
||||||
# BYTEDANCE_TTS_EXPLICIT_LANGUAGE=zh-cn
|
|
||||||
|
|
||||||
# 复刻 2.0 启用字级时间戳(可选)
|
|
||||||
# BYTEDANCE_TTS_ENABLE_SUBTITLE=false
|
|
||||||
|
|
||||||
# OpenAI兼容接口的API密钥(可选,多个用逗号分隔)
|
|
||||||
OPENAI_TTS_API_KEY=your_openai_compatible_key_here
|
|
||||||
|
|
||||||
# 反代拓扑配置(0-10)。控制 X-Forwarded-For 解析方式,影响 IP 限流的 key。
|
|
||||||
# 不设置 / 0:启发式模式(默认)—— 从 XFF 链尾扫描,跳过私有 IP,返回第一个公网 IP
|
|
||||||
# 适合 90% 部署(单跳/多跳/直出),无需了解精确跳数
|
|
||||||
# N (N>0) :精确模式 —— 精准到真实 client IP,需要正确配置跳数
|
|
||||||
# N=1:单跳反代(client → nginx → 本服务)
|
|
||||||
# N=2:双跳反代(client → CDN → nginx → 本服务,如 Cloudflare + nginx)
|
|
||||||
# N=3:三跳,以此类推
|
|
||||||
# 直出部署(无反代):无需配置,XFF 分支不会执行
|
|
||||||
# 详见 README "反代拓扑与 X-Forwarded-For 解析"章节
|
|
||||||
# TRUSTED_PROXY_HOPS=
|
|
||||||
|
|
||||||
# CORS 跨域白名单(逗号分隔;开发环境可设 *;空则拒绝所有跨域)
|
|
||||||
# ALLOWED_ORIGINS=https://example.com,https://app.example.com
|
|
||||||
|
|
||||||
# 服务监听端口,默认8080
|
|
||||||
PORT=8080
|
PORT=8080
|
||||||
|
|
||||||
|
# 4. OpenAI 兼容接口的鉴权 key(可选)
|
||||||
|
# 不设 = 不鉴权,任何人能调 /v1/audio/speech(适合内网/反代后)
|
||||||
|
# 多个 key 用逗号分隔
|
||||||
|
# 公网部署必设,见 README "公网部署安全清单"
|
||||||
|
OPENAI_TTS_API_KEY=
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 装完后可改(也支持环境变量作为 DB 缺失时的 fallback)
|
||||||
|
# ==========================================
|
||||||
|
# X-Forwarded-For 解析跳数(可选, 0=启发式默认, N>0=精确 N 跳反代)
|
||||||
|
# 装好后推荐到 /admin 改 trusted_proxy_hops
|
||||||
|
# TRUSTED_PROXY_HOPS=2
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
本项目的所有重要变更都记录在本文档。版本号遵循 [SemVer](https://semver.org/)。
|
||||||
|
|
||||||
|
## [0.2.0] - 2026-08-30
|
||||||
|
|
||||||
|
### 新增
|
||||||
|
|
||||||
|
- **M0 · SQLite + store 包**: 引入 `modernc.org/sqlite` (无 CGO), 所有运行时配置 (settings + voices) 持久化到 SQLite
|
||||||
|
- **M1 · 安装流程**: 首次启动进入 `/setup` 向导, 通过 4 步表单收集凭证 + 默认音色 + 音色列表, 完成后写 `installed.lock` 锁定
|
||||||
|
- 引导页无外部依赖: Vue 3.4 + axios 1.6 via bootcdn, `//go:embed` 进 binary
|
||||||
|
- **自愈回退**: 检测到 DB 损坏自动备份 + 转 setup 模式 (不丢数据)
|
||||||
|
- **M2 · WebUI 后台**: `/admin` 单页 SPA, 含登录 / 仪表盘 / 音色管理 / 设置 / CORS 配置
|
||||||
|
- 默认鉴权基于 `auth_key` (DB), 失败计数 + 限流
|
||||||
|
- 浏览器安装修复: 同源请求跳过 CORS 校验, install 模式完全跳过 CORS
|
||||||
|
- **M3 · 全局设置 + 声音路由**:
|
||||||
|
- `default_speaker` 是 voice **名字** (如 `chun`), 路由时查 voice 表拿到真 speaker ID (如 `S_G8tEKnaJ1`)
|
||||||
|
- `/v1/audio/speech` 支持 `voice=<name>` 动态路由, 命中但 enabled=0 返回 403
|
||||||
|
- 未知 voice 返回 400 `unknown_voice: '<name>'`
|
||||||
|
- 禁用 voice 返回 403 `voice '<name>' is disabled`
|
||||||
|
- **OpenAI 端 key 走 DB**: `auth_key` 设置项, 不再依赖 `OPENAI_TTS_API_KEY` env
|
||||||
|
- **CORS 全 DB 化**: `cors_origins` / `cors_allow_all` 走 `/admin` 设置, install 模式跳过
|
||||||
|
- **CORS 修复**: 同源请求跳过 CORS 校验 (避免浏览器自家人拦自家人)
|
||||||
|
- **运营工具**: `cmd/dumpdb` — 离线 dump tts.db 的 settings + voices
|
||||||
|
- **fail-fast**: normal 模式下 TTS 配置损坏 → `log.Fatalf` 退出, 触发 K8s / Docker 重启
|
||||||
|
- 配套 metric `tts_config_load_failures_total{mode="normal"}` 便于告警
|
||||||
|
- `/health` body 加 `error` 字段直接展示失败原因
|
||||||
|
- **speaker ID 隐私保护**: 日志里 `telemetry.MaskSpeaker` (`S_G8****naJ1`); `/metrics` 标签用 `telemetry.SpeakerLabel` (sha1[:8])
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
|
||||||
|
- **resource_id 覆盖**: `LoadRuntimeConfig` 之前用 voice 行的 `resource_id` 覆盖 settings 里的, 导致用户设的 `default_resource_id` 永远没机会生效。现在 settings 优先, voice 行的 resource_id 仅在 `voice=` 显式传时使用
|
||||||
|
- **默认值修正**: 把过时的 `volc.megatts.icl` / `volc.megatts.default` 全部改成 v3 API 2.0 复刻项目唯一合法的 `seed-icl-2.0`; 模型名统一 `seed-tts-2.0-standard`
|
||||||
|
- **log 格式一致**: voice 命中 log 跟合成 log 同样打码
|
||||||
|
- **setup UX 改进**: voice 行 `resource_id` 留空时, 自动用 settings 里的 `default_resource_id` 兜底, 避免 settings / voice 资源 ID 不一致导致 500
|
||||||
|
- **/admin dashboard banner 误报**: `reloadAll()` 加 `loadSettings()`, 避免 "CORS 未配置" 黄条永远显示
|
||||||
|
|
||||||
|
### 变更
|
||||||
|
|
||||||
|
- **.env.example 收敛**: 移除 `BYTEDANCE_TTS_*` 业务 env, 只留 4 个引导 env (`TTS_ADMIN_KEY` / `TTS_DB_PATH` / `PORT` / `OPENAI_TTS_API_KEY`); 业务配置走 WebUI
|
||||||
|
- **docker-compose**: 加 `tts-data` named volume 持久化 tts.db
|
||||||
|
- **Dockerfile**: 准备 `/data` 目录, appuser 可写, 解决 tts.db 落盘权限
|
||||||
|
|
||||||
|
## [0.1.0] - 初版
|
||||||
|
|
||||||
|
- 火山 TTS v3 → OpenAI 兼容 `/v1/audio/speech` 单二进制
|
||||||
|
- 配置全 env 驱动 (`BYTEDANCE_TTS_*` 11 个)
|
||||||
|
- 限流 / 鉴权 / Prometheus metrics / CORS / 反代 XFF 解析
|
||||||
+5
-2
@@ -27,13 +27,16 @@ WORKDIR /app
|
|||||||
COPY --from=builder /app/tts-api .
|
COPY --from=builder /app/tts-api .
|
||||||
# health.html 已通过 //go:embed 嵌入 binary,无需单独复制
|
# health.html 已通过 //go:embed 嵌入 binary,无需单独复制
|
||||||
|
|
||||||
RUN chown -R appuser:appgroup /app
|
# 准备 /data 目录存 SQLite (tts.db + installed.lock)
|
||||||
|
# appuser 必须可写,否则启动后无法创建 DB
|
||||||
|
RUN mkdir -p /data \
|
||||||
|
&& chown -R appuser:appgroup /app /data
|
||||||
|
|
||||||
USER appuser
|
USER appuser
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||||
CMD wget -qO- http://localhost:8080/health || exit 1
|
CMD wget -qO- http://localhost:8080/health || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["./tts-api"]
|
ENTRYPOINT ["./tts-api"]
|
||||||
|
|||||||
+18
-9
@@ -1,23 +1,32 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
tts-api:
|
tts-api:
|
||||||
build: .
|
build: .
|
||||||
|
image: volcano-tts-aggregator:latest
|
||||||
container_name: tts-api
|
container_name: tts-api
|
||||||
ports:
|
ports:
|
||||||
- "${PORT:-8080}:8080"
|
- "${PORT:-8080}:8080"
|
||||||
environment:
|
environment:
|
||||||
- BYTEDANCE_TTS_API_KEY=${BYTEDANCE_TTS_API_KEY}
|
# 4 个启动引导 env(仅这 4 个必看)
|
||||||
- BYTEDANCE_TTS_RESOURCE_ID=${BYTEDANCE_TTS_RESOURCE_ID}
|
# 业务配置(api_key/resource_id/speaker/格式...)通过 WebUI 设置,
|
||||||
- BYTEDANCE_TTS_SPEAKER=${BYTEDANCE_TTS_SPEAKER}
|
# 存到 /data/tts.db 持久化
|
||||||
- BYTEDANCE_TTS_TIMEOUT=${BYTEDANCE_TTS_TIMEOUT:-30s}
|
- TTS_ADMIN_KEY=${TTS_ADMIN_KEY:-}
|
||||||
- OPENAI_TTS_API_KEY=${OPENAI_TTS_API_KEY:-}
|
- TTS_DB_PATH=/data/tts.db
|
||||||
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-}
|
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
|
- OPENAI_TTS_API_KEY=${OPENAI_TTS_API_KEY:-}
|
||||||
|
# 可选,装好后也可在 /admin 改
|
||||||
|
- TRUSTED_PROXY_HOPS=${TRUSTED_PROXY_HOPS:-}
|
||||||
|
volumes:
|
||||||
|
# DB + lock 文件必须挂载,否则容器重启后配置全丢
|
||||||
|
- tts-data:/data
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
# 用 wget 检查,alpine 镜像有
|
||||||
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
|
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 5s
|
start_period: 10s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
tts-data:
|
||||||
|
name: tts-api-data
|
||||||
|
|||||||
Reference in New Issue
Block a user