Applio 产品定位与能力地图
Applio 是一个以易用性、音质和性能为核心的语音转换工具。仓库中的产品形态是一个由 Gradio 驱动的本地 Web UI,并通过 RVC 推理、训练、TTS、实时处理和模型管理等模块组成完整的语音工作台。
Purpose and Scope
本页描述 Applio 在当前仓库中的产品边界、启动方式、主要能力入口以及能力之间的关系,帮助开发者快速判断某项需求应落在哪个 UI Tab、核心编排函数或底层 RVC 模块中。
页面重点覆盖:
app.py如何创建 Gradio 应用、加载运行前置条件并注册能力 Tab;core.py如何将推理、TTS、预处理、特征提取和训练请求编排到 RVC 脚本或VoiceConverter;- 本地配置、端口、主机名、公开分享和 client mode 等运行参数;
- 模型文件、索引文件、日志目录和输出音频在能力地图中的位置。
安装脚本、Docker 镜像构建、法律条款和具体 Tab 内的 UI 细节属于相邻主题;本页仅在它们影响产品定位或运行边界时引用。模型算法本身也不在此页重新实现;这里记录 Applio 对算法能力的编排方式。
Overview
README 将 Applio 定义为面向艺术家、开发者和研究者的高质量 voice conversion 工具,并明确强调简单性、质量和性能。用户通过 run-applio.bat 或 run-applio.sh 启动应用,应用随后在默认浏览器中打开 Gradio 界面;TensorBoard 是可选的训练监控入口。
从代码结构看,产品采用“单一工作台 + 多能力 Tab”的组织方式:app.py 负责应用生命周期和界面组合,core.py 提供跨 Tab 复用的操作编排,rvc 包承担推理、训练、模型下载、预处理、特征提取和 TTS 等具体执行。这样的分层使 UI Tab 不需要直接管理底层命令行参数,同时保留对音频转换参数的细粒度控制。
能力地图可以概括为:
| 能力域 | 入口 | 代码中可确认的职责 |
|---|---|---|
| 单文件推理 | Inference / run_infer_script | 组装音高、F0、索引、清理、后处理和导出参数,调用 VoiceConverter.convert_audio |
| 批量推理 | run_batch_infer_script | 面向输入目录和输出目录的批量转换编排;完整实现位于 core.py 后续内容 |
| 训练 | Training / run_train_script | 训练参数、日志目录和训练脚本的编排 |
| 文本转语音再转换 | TTS / run_tts_script | 先运行 rvc/lib/tools/tts.py 生成语音,再交给 VoiceConverter 转换 |
| 数据准备 | run_preprocess_script、run_extract_script | 调用预处理和特征提取脚本,并将失败信息返回给 UI |
| 实时与扩展 | Realtime、Plugins | 在 app.py 中作为独立 Tab 注册;具体实现由对应 tabs 模块负责 |
| 运行支撑 | Download、Settings、TensorBoard | 模型下载、设置和训练监控入口 |
Architecture
图中的关键边界来自实际代码:app.py 导入各个 tabs 并以 gr.Tab 注册它们;应用启动前调用 run_prerequisites_script;core.py 通过缓存的 import_voice_converter() 创建 VoiceConverter,并把 UI 参数映射为转换器参数。图中的“执行层”不是另一个产品服务,而是当前 Python 进程通过导入或 subprocess.run 调用的仓库内模块。
产品组合与启动生命周期
启动前准备
app.py 首先基于当前工作目录定位 assets/config.json 和 assets/config_template.json。当配置文件不存在时,代码从模板复制一份新配置,然后调用 platform_config() 应用平台配置。随后,应用解析 --port、--server-name、--share、--open 和 --client 参数。
启动阶段还会执行:
- 将
uvicorn和httpx日志级别调到 warning; - 在 Windows 上抑制特定的
ConnectionResetError; - 修正 Gradio 数字控件对越界值和
None的预处理; - 导入所有能力 Tab;
- 调用
run_prerequisites_script(pretraineds_hifigan=True, models=True, exe=True); - 初始化国际化、可选 Discord presence、安装检查和主题;
- 创建
gr.Blocks,并按产品能力注册 Tab。
这种启动顺序的设计意图是先准备运行环境,再构建 UI。模型或可执行依赖缺失时,问题会在用户进入具体能力前暴露,而不是在第一次推理时才失败。
Tab 组织
当前 app.py 明确注册了 Inference、Training、TTS、Voice Blender、Realtime、Plugins、Download、Report a Bug、Extra、Settings 和 TensorBoard。因此,Applio 的产品定位不是单一“转换按钮”,而是围绕语音模型生命周期组织的工作台:推理消费模型,训练生产模型,TTS 和实时能力扩展输入形态,下载和设置解决运行准备,TensorBoard 支持训练观察。
核心数据流
对于普通推理,run_infer_script 直接把输入音频、模型路径、索引路径、F0 方法、音高、清理、导出格式和后处理参数组装成 kwargs,然后调用 convert_audio。对于 TTS,run_tts_script 明确分成两个阶段:先执行 tts.py,再将其输出作为 audio_input_path 交给同一个转换器。这种复用保持了 TTS 转换和普通音频转换的一致模型入口。
能力边界与扩展方向
- 若需求是改变界面布局或交互,应优先定位对应
tabs/<capability>模块,而不是在core.py增加 UI 逻辑。 - 若需求是增加底层转换参数,应检查
run_infer_script的参数签名、kwargs映射和VoiceConverter.convert_audio的契约,三者必须同步。 - 若需求是增加训练前处理,应围绕
run_preprocess_script、run_extract_script和run_train_script的脚本边界扩展。 - 若需求是新的外部工具或模型下载流程,应放在相应
rvc.lib.tools能力中,并由 Tab 或核心编排函数调用。
1# app.py 在应用启动前执行运行前置条件
2run_prerequisites_script(
3 pretraineds_hifigan=True,
4 models=True,
5 exe=True,
6)Source: app.py
1# app.py 以 Tab 组合产品能力
2with gr.Tab(i18n("Inference")):
3 inference_tab()
4
5with gr.Tab(i18n("Training")):
6 train_tab()
7
8with gr.Tab(i18n("TTS")):
9 tts_tab()
10
11with gr.Tab(i18n("Realtime")):
12 realtime_tab()Source: app.py
Usage Examples
基础:直接调用音频推理编排函数
以下签名和调用逻辑来自 core.py。它展示了产品层如何将 UI 参数交给 VoiceConverter,而不是在 UI 中直接实现模型推理:
1def run_infer_script(
2 pitch: int,
3 index_rate: float,
4 volume_envelope: float,
5 protect: float,
6 f0_method: str,
7 input_path: str,
8 output_path: str,
9 pth_path: str,
10 index_path: str,
11 split_audio: bool,
12 f0_autotune: bool,
13 f0_autotune_strength: float,
14 proposed_pitch: bool,
15 proposed_pitch_threshold: float,
16 clean_audio: bool,
17 clean_strength: float,
18 export_format: str,
19 embedder_model: str,
20 embedder_model_custom: str = None,
21 formant_shifting: bool = False,
22 formant_qfrency: float = 1.0,
23 formant_timbre: float = 1.0,
24 post_process: bool = False,
25 reverb: bool = False,
26 pitch_shift: bool = False,
27 limiter: bool = False,
28 gain: bool = False,
29 distortion: bool = False,
30 chorus: bool = False,
31 bitcrush: bool = False,
32 clipping: bool = False,
33 compressor: bool = False,
34 delay: bool = False,
35 reverb_room_size: float = 0.5,
36 reverb_damping: float = 0.5,
37 reverb_wet_gain: float = 0.5,
38 reverb_dry_gain: float = 0.5,
39 reverb_width: float = 0.5,
40 reverb_freeze_mode: float = 0.5,
41 pitch_shift_semitones: float = 0.0,
42 limiter_threshold: float = -6,
43 limiter_release_time: float = 0.01,
44 gain_db: float = 0.0,
45 distortion_gain: float = 25,
46 chorus_rate: float = 1.0,
47 chorus_depth: float = 0.25,
48 chorus_center_delay: float = 7,
49 chorus_feedback: float = 0.0,
50 chorus_mix: float = 0.5,
51 bitcrush_bit_depth: int = 8,
52 clipping_threshold: float = -6,
53 compressor_threshold: float = 0,
54 compressor_ratio: float = 1,
55 compressor_attack: float = 1.0,
56 compressor_release: float = 100,
57 delay_seconds: float = 0.5,
58 delay_feedback: float = 0.0,
59 delay_mix: float = 0.5,
60 sid: int = 0,
61):
62 kwargs = {
63 "audio_input_path": input_path,
64 "audio_output_path": output_path,
65 "model_path": pth_path,
66 "index_path": index_path,
67 "volume_envelope": volume_envelope,
68 "pitch": pitch,
69 "index_rate": index_rate,
70 "protect": protect,
71 "f0_method": f0_method,
72 "split_audio": split_audio,
73 "f0_autotune": f0_autotune,
74 "f0_autotune_strength": f0_autotune_strength,
75 "proposed_pitch": proposed_pitch,
76 "proposed_pitch_threshold": proposed_pitch_threshold,
77 "clean_audio": clean_audio,
78 "clean_strength": clean_strength,
79 "export_format": export_format,
80 "embedder_model": embedder_model,
81 "embedder_model_custom": embedder_model_custom,上述代码块分别截取了真实函数的签名和参数映射开头;函数后续还会继续加入效果参数并调用缓存的转换器。
实际源代码还会继续将后处理开关和具体效果参数加入 kwargs,并返回成功消息以及按照 export_format 替换扩展名后的输出路径。上面的摘录保留了入口、参数映射和转换器调用三个最能说明产品分层的部分。
高级:TTS 与 Voice Conversion 串联
run_tts_script 是一个真实的复合能力示例:它先调用仓库内 TTS 脚本,再复用相同的 VoiceConverter 完成音色转换。
1tts_script_path = os.path.join("rvc", "lib", "tools", "tts.py")
2
3command_tts = [
4 *map(
5 str,
6 [
7 python,
8 tts_script_path,
9 tts_file,
10 tts_text,
11 tts_voice,
12 tts_rate,
13 output_tts_path,
14 ],
15 ),
16]
17result = subprocess.run(command_tts, capture_output=True, text=True)
18if result.returncode != 0:
19 raise RuntimeError(result.stderr.strip())Source: core.py
生成 TTS 音频后,函数将 output_tts_path 作为输入,并将用户选择的模型、索引、音高、F0、自动调音和导出参数传给转换器:
1infer_pipeline = import_voice_converter()
2infer_pipeline.convert_audio(
3 pitch=pitch,
4 index_rate=index_rate,
5 volume_envelope=volume_envelope,
6 protect=protect,
7 f0_method=f0_method,
8 audio_input_path=output_tts_path,
9 audio_output_path=output_rvc_path,
10 model_path=pth_path,
11 index_path=index_path,
12 split_audio=split_audio,
13 f0_autotune=f0_autotune,
14 f0_autotune_strength=f0_autotune_strength,
15 export_format=export_format,
16 embedder_model=embedder_model,
17 embedder_model_custom=embedder_model_custom,
18 sid=sid,
19)Source: core.py
Configuration Options
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--port | int | 6969 | Gradio 服务端口;代码定义了 DEFAULT_PORT = 6969。 |
--server-name | str | 127.0.0.1 | 服务绑定主机名;默认仅面向本机访问。 |
--share | flag | 关闭 | 请求 Gradio 创建公开分享链接。 |
--open | flag | 关闭 | 请求自动打开浏览器。 |
--client | flag | 关闭 | 启用 client mode,并为 Gradio Blocks 注入 realtime JavaScript。 |
assets/config.json | JSON 文件 | 从模板创建 | 启动时若不存在,则复制 assets/config_template.json。 |
logs/ | 目录 | 当前仓库下 | 训练、预处理和特征提取使用 logs_path 组织模型相关工作目录。 |
代码同时定义 MAX_PORT_ATTEMPTS = 10,但在已读取的入口片段中未看到其具体使用位置;不要把它当作已确认的端口重试行为。完整的端口选择行为需要继续检查 app.py 的后续实现。
API Reference
run_infer_script(...)
这是普通音频转换的核心编排函数。它接收音频路径、模型和索引路径、音高与 F0 参数、切分和自动调音选项、清理与导出参数,以及可选后处理参数。
- 输入:
input_path、output_path、pth_path、index_path与转换控制参数。 - 核心副作用:调用缓存的
VoiceConverter.convert_audio(**kwargs)。 - 返回值:二元组,第一项是成功消息,第二项是将
.wav替换为目标格式扩展名的路径。 - 错误:底层
convert_audio的异常不会在此函数中转换;调用方需要按 UI 层约定处理。
run_tts_script(...)
该函数先使用 subprocess.run 启动 rvc/lib/tools/tts.py,再调用 VoiceConverter.convert_audio。
- 关键输入:
tts_file、tts_text、tts_voice、tts_rate、output_tts_path、output_rvc_path、模型与索引路径,以及转换参数。 - 成功返回:
("Text ... synthesized successfully.", converted_path)形式的二元组。 - 失败行为:当 TTS 子进程返回非零状态时,函数使用
stderr.strip()构造RuntimeError。 - 文件安全行为:如果已有的
output_tts_path位于assets目录下,函数会先删除它;这是为了避免覆盖旧的临时 TTS 文件,但也意味着调用者必须传入明确的临时输出路径。
run_preprocess_script(...) 与 run_extract_script(...)
这两个函数分别把数据预处理和特征提取参数转换为 Python 子进程命令。它们在子进程失败时返回面向 UI 的失败字符串,而不是抛出异常:
- 预处理使用
logs/<model_name>、数据集路径、采样率、CPU 核数、切分、降噪和归一化参数; - 特征提取使用模型目录、F0 方法、CPU/GPU、采样率、embedder 和静音样本参数;
- 两者都要求调用者检查返回字符串,以便在 UI 中呈现失败状态。
Failure Modes, Edge Cases & Concurrency
失败路径
- 配置模板缺失:
app.py只在CONFIG_PATH不存在时复制模板;源代码没有显示模板不存在时的专门恢复策略。 - TTS 子进程失败:直接抛出
RuntimeError,错误内容来自 stderr;这是 TTS 流程与预处理/特征提取流程不同的错误契约。 - 预处理或特征提取失败:返回包含模型名的失败字符串,并提示检查控制台日志。
- Windows 连接关闭异常:入口对
ConnectionResetError做了定向抑制,避免远端连接强制关闭影响 asyncio shutdown。 - 非法 Gradio 数字输入:
gr.Number.preprocess在值为None、低于 minimum 或高于 maximum 时返回None,否则按控件精度舍入。
缓存与并发边界
import_voice_converter() 使用 @lru_cache(maxsize=1),因此进程内最多缓存一个 VoiceConverter 实例;get_config() 也只缓存一个 Config 实例。这样可以避免每次操作都重复加载模型转换器配置,适合本地工作台的重复操作路径。
源代码未显示显式锁、任务队列或并发请求协调机制。由此可以确认缓存存在,但不能推断多个并发推理请求是否安全;如果要把 Applio 作为多用户服务部署,应额外验证 VoiceConverter 的线程安全、GPU 资源竞争以及输出路径冲突。
资源与输出约束
- 训练、预处理和特征提取通过
logs/<model_name>组织中间产物; - TTS 输出和 RVC 输出使用两个路径,便于区分中间音频和最终音频;
run_infer_script和run_tts_script都根据导出格式生成最终路径,但实际转换器对文件格式的支持仍由底层 RVC 实现决定。
Performance and Operational Notes
VoiceConverter和Config的单实例缓存减少了重复初始化成本;- 训练、预处理、特征提取和 TTS 使用子进程,将长任务或外部脚本边界与 Gradio 编排层分开;
- README 明确将 TensorBoard 定义为可选监控能力,适合训练任务而非普通推理路径;
- README 还说明项目已趋于稳定,后续更新主要集中在安全补丁、依赖更新和偶发功能改进;这对维护者意味着扩展应优先保持现有 Tab 和核心函数契约,而不是大规模改写产品入口。
Extension Points
推荐的扩展顺序是:
- 在对应
tabs模块增加或调整用户交互; - 在
core.py增加清晰的编排函数,负责参数校验、路径准备和底层调用; - 若需要新算法或新模型工具,将执行逻辑放在
rvc的对应模块; - 在
app.py只增加 Tab 注册、启动期初始化或全局 UI 行为; - 对跨平台行为同时检查 Windows、macOS 和 Linux 分支,尤其是外部命令、路径和关闭系统调用。
不要直接把底层命令拼接到 UI 回调中;现有结构已经把脚本调用集中在 core.py,这有利于统一错误处理、缓存和输出路径语义。
Related Links
- 项目 README:产品定位、安装、启动和 TensorBoard 入口。
- 应用入口 app.py:配置初始化与平台配置。
- Gradio 参数与 Tab 注册 app.py:运行参数和能力入口。
- 核心编排 core.py:普通推理参数映射和转换器调用。
- TTS 编排 core.py:TTS 子进程与 voice conversion 串联。