TEN Framework TTS Guarder 集成测试指南:从 API Key 配置到字幕对齐验证
2026/9/24 21:54:12 网站建设 项目流程
  • 人工智能
  • AI Agent
  • 多模态
  • 语音
  • AI 应用

【免费下载链接】ten-framework

Open-source framework for conversational voice AI agents

项目地址:https://gitcode.com/TEN-framework/ten-framework
点击查看免费下载

TTS Guarder 是 TEN Framework AI Agents 仓库中面向 TTS(文本转语音)扩展的一体化集成测试套件,位于 ai_agents/agents/integration_tests/tts_guarder 目录。它以 pytest + TEN Runtime 测试框架为底座,通过向真实 TTS 扩展注入tts_text_input数据并校验tts_audio_starttts_audio_endtts_text_result等输出事件,验证语音合成扩展的正确性。阅读本文后,你将掌握 TTS Guarder 的环境配置、命令行运行方式、Taskfile 任务封装,以及字幕对齐(Subtitle Alignment)这类高级校验的启用与原理。

TTS Guarder 定位与套件结构

TTS Guarder 与同目录下的 ASR Guarder 共同构成 AI Agents 的双向语音链路验证体系:ASR Guarder 校验语音识别,TTS Guarder 校验语音合成。二者共享同一套"动态注入被测扩展 + 独立测试用例"的设计模式。

从仓库目录结构看,TTS Guarder 套件由以下部分组成:

路径作用
tests/全部 pytest 测试用例(含 conftest.py 与测试数据)
tests/conftest.pypytest 插件与全局 fixture,负责启动 FakeApp、解析命令行选项
manifest-tmpl.json应用 manifest 模板,运行前动态替换{{extension_name}}
scripts/install_deps_and_build.sh依赖安装与构建脚本
property.json应用属性(当前为空对象)

其中manifest-tmpl.json是套件可针对任意 TTS 扩展复用的关键:它以{{extension_name}}作为占位符声明依赖ten_packages/extension/{{extension_name}},在运行时被替换为真实的扩展名(详见下文 Taskfile 解析),从而让同一套测试用例直接套用在 ElevenLabs、Cartesia、字节跳动(Bytedance)等不同厂商的 TTS 扩展上。

第一步:配置 TTS 厂商 API Key

运行测试前必须先为被测的 TTS 厂商服务配置 API Key。TTS Guarder 支持两种配置方式:

方式一:环境变量(export)

# TTS Vendor Services API Key export VENDOR_TTS_API_KEY=your_api_key_here # 例如 ElevenLabs: export ELEVENLABS_TTS_API_KEY=your_elevenlabs_api_key

方式二:项目根目录的.env文件

# .env file ELEVENLABS_TTS_API_KEY=your_elevenlabs_api_key

需要说明的是:VENDOR_TTS_API_KEY是通用占位变量,具体被测扩展实际读取的 Key 名称由该扩展自身的配置决定。例如 ElevenLabs 扩展对应ELEVENLABS_TTS_API_KEY.env文件方式与 ai_agents/Taskfile.yml 中的dotenv: [".env"]声明相衔接——Taskfile 在执行tts-guarder-test等任务时会自动加载.env中的变量,因此直接task tts-guarder-test EXTENSION=xxx即可读取配置,无需手动 export。

第二步:准备测试文本

README 明确指出:需要为不同测试场景准备多段文本("prepare mutiple text for testing different scenario")。这一要求在测试代码中有多处印证:

  • tests/test_data/short.txt:短文本测试数据,供test_short_text类用例读取;
  • test_basic_audio_setting.py 中直接内置了"hello world, hello agora, hello shanghai, nice to meet you!"作为采样率对比测试的输入文本;
  • test_subtitle_alignment.py 中则使用一段英文长句验证字幕与音频的时序对齐。

文本通过tts_text_input数据(Data)对象发送,携带textrequest_idtext_input_end以及含session_id/turn_idmetadata字段。建议至少准备:短文本、长文本、空文本/非法文本、带特殊字符的文本,以覆盖测试用例集中不同场景。

第三步:运行测试

命令行直接运行

# 运行单个测试用例 bash tests/bin/start tests/test_elevenlabs_tts_basic.py::test_short_text --extension_name=elevenlbas_tts_python

其中tests/bin/start是测试套件的统一启动入口(由安装脚本生成/下载),tests/test_elevenlabs_tts_basic.py::test_short_text指定要执行的测试文件与用例节点,--extension_name=elevenlbas_tts_python指定被测 TTS 扩展。

通过 Taskfile 运行整套测试

更推荐的方式是通过 ai_agents/Taskfile.yml 中定义的tts-guarder-test任务:

# 默认扩展(bytedance_tts_duplex) task tts-guarder-test # 指定被测扩展 task tts-guarder-test EXTENSION=cartesia_tts

该任务的完整执行流程(可从 ai_agents/Taskfile.yml 源码确认)为:

  1. sedmanifest-tmpl.json中的{{extension_name}}替换为实际扩展名,生成manifest.json
  2. 执行./scripts/install_deps_and_build.sh linux x64:该脚本会调用tman -y install安装 manifest 声明的全部依赖,并遍历ten_packages/extensionten_packages/system目录逐个安装各扩展的requirements.txt(见 install_deps_and_build.sh);
  3. 运行./tests/bin/start --extension_name <EXTENSION> --config_dir <扩展配置目录>,并透传{{ .CLI_ARGS }}中的附加参数。

任务还通过TEN_ENABLE_BACKTRACE_DUMP: "true"开启运行时回溯转储,便于测试失败时定位 C 核心层的崩溃现场。

关键 pytest 命令行选项

套件在 tests/conftest.py 中通过pytest_addoption注册了以下选项:

选项是否必填默认值说明
--extension_name被测 TTS 扩展名,如elevenlabs_tts_pythoncartesia_tts
--config_dir扩展配置目录的绝对路径,通常指向agents/ten_packages/extension/<扩展名>/tests/configs
--enable_sample_rateTrue是否启用采样率对比校验(True/False
--enable_subtitle_alignmentFalse是否启用字幕对齐测试(True/False

测试用例矩阵

套件的 tests/ 目录按功能维度组织了完整的 TTS 场景覆盖:

测试文件验证目标
test_basic_audio_setting.py基础音频设置:不同配置下采样率是否按预期生效,音频时长是否与 PCM 数据一致(容差 50ms)
test_connection_status.pyWebSocket 型 TTS 扩展的连接状态事件(支持 bytedance/minimax/rime 等,见源码SUPPORTED_WEBSOCKET_TTS_EXTENSIONS
test_append_input.py/test_append_input_stress.py/test_append_input_without_text_input_end.py追加式文本输入、压力场景、未发送结束标记的追加输入
test_interleaved_requests.py交错/并发请求处理
test_interrupt.py合成中断处理
test_corner_input.py/test_empty_text_request.py/test_invalid_text_handling.py边界与非法输入:空文本、非法文本、角落输入
test_invalid_required_params.py/test_miss_required_params.py缺失/非法必填参数的报错行为
test_flush.py冲刷(flush)语义
test_dump.py/test_dump_each_request_id.py音频 dump 与按 request_id 维度 dump
test_metrics.py指标输出
test_subtitle_alignment.py字幕(词级时间戳)与音频帧对齐(默认关闭,见下文)

以 test_basic_audio_setting.py 为例:它依次读取两份配置文件property_basic_audio_setting1.jsonproperty_basic_audio_setting2.json运行两次合成,若两份配置期望不同的采样率(如 16K 与 32K),则断言两次测试拿到的audio_frame.get_sample_rate()不同,从而验证扩展的采样率配置确实生效。

字幕对齐测试(Subtitle Alignment Test)

默认禁用与启用方式

字幕对齐测试在 TTS Guarder 中默认禁用,原因在于它依赖 TTS 厂商返回词级时间戳(word-level timing),并非所有厂商都支持。README 给出的用法如下:

# 默认运行:跳过字幕对齐测试 task tts-guarder-test EXTENSION=cartesia_tts # 显式启用字幕对齐测试 task tts-guarder-test EXTENSION=cartesia_tts -- --enable_subtitle_alignment=True

目前test_subtitle_alignment.py仅针对cartesia_tts运行。这一限制在源码中有两处强校验(见 test_subtitle_alignment.py):

  1. --enable_subtitle_alignment未开启,测试直接pytest.skip
  2. 若被测扩展不在SUPPORTED_TTS_EXTENSIONS = {"cartesia_tts"}集合内,同样跳过;
  3. 若配置目录下不存在property_subtitle_alignment.json配置文件,也会跳过("Subtitle alignment is optional for providers without text timing")。

六条对齐验证规则

SubtitleAlignmentTester 在收到tts_audio_end后延时 0.5 秒等待词级结果收齐,然后依次执行六个校验器:

规则校验内容源码函数
1首条文本的start_ms不得早于首个音频帧时间戳_validate_first_timestamp
2文本start_ms必须严格递增_validate_text_timestamps_ascending
3音频帧时间戳严格递增,且下一帧 ≈ 上一帧时间戳 + 上一帧时长(容差 ±10ms)_validate_audio_frames_ascending
4文本总时长与音频总时长差值不超过阈值DURATION_MISMATCH_THRESHOLD_MS = 1000ms_validate_duration_match
5turn_seq_id递增、request_id全程一致_validate_turn_sequence
6最后一条结果的turn_status必须为 1(正常结束)或 2(被打断)_validate_turn_status

校验失败时通过ten_env.stop_test(TenError.create(...))终止测试并抛出错误;全部通过则打印✅ All subtitle alignment validations passed并正常结束。音频帧时长由帧内样本数换算:duration_ms = samples * 1000 // sample_rate(见 test_subtitle_alignment.py)。

这六条规则共同保证了一个对语音交互产品至关重要的性质:字幕出现时机与听到的语音严格对齐——字幕不能先于声音、不能后于声音超过 1 秒、且各词序与音频帧序一致。

测试运行机制:FakeApp 与测试器

理解 TTS Guarder 的运行机制有助于排查失败用例。tests/conftest.py 中的 session 级 autouse fixture 会启动一个独立的FakeApp线程:FakeApp 在on_init中释放事件锁(使 fixture 得以继续执行),在on_configure中通过init_property_from_json注入控制台日志 handler,随后app.run(False)启动运行时;teardown 阶段关闭 app 并 join 线程。

测试用例本身继承AsyncExtensionTester,通过set_test_mode_single(extension_name, json.dumps(config))将扩展与配置绑定,然后:

  • on_start中构造Data.create("tts_text_input")并设置textrequest_idtext_input_endmetadatasend_data
  • on_data中按tts_audio_start/tts_audio_end/tts_text_result/error等消息名分派处理;
  • on_audio_frame中检查采样率、累积音频字节并核对时间戳。

这套"发送输入 → 收集输出 → 规则校验"的模型与真实 AI Agent 运行时中 TTS 扩展的接入方式一致,因此 TTS Guarder 的测试结果可以直接反映扩展在真实场景中的行为。

小结与排查建议

综合 README 与仓库源码,TTS Guarder 的完整使用路径可归纳为:

  1. 配置 API Key(export 或.env);
  2. 准备覆盖多场景的测试文本;
  3. 选择运行方式:bash tests/bin/start ... --extension_name=<ext>task tts-guarder-test EXTENSION=<ext>
  4. 按需追加--enable_sample_rate/--enable_subtitle_alignment等选项;
  5. 针对cartesia_tts等支持词级时间戳的扩展,可启用字幕对齐测试验证时序。

常见问题定位线索:若用例被跳过,优先检查--enable_subtitle_alignment是否开启、扩展名是否在SUPPORTED_TTS_EXTENSIONS集合内、config_dir下是否存在对应property_*.json配置文件;若用例失败,可借助TEN_ENABLE_BACKTRACE_DUMP=true(Taskfile 默认开启)的崩溃转储与测试日志中的错误信息定位具体校验规则。

  • 人工智能
  • AI Agent
  • 多模态
  • 语音
  • AI 应用

【免费下载链接】ten-framework

Open-source framework for conversational voice AI agents

项目地址:https://gitcode.com/TEN-framework/ten-framework
点击查看免费下载

相关推荐

上一篇:Celery 节点命名机制全解析:celery.utils.nodenames 模块源码级指南
下一篇:20个STM32实战例程:从零到机器人嵌入式开发终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询