Repository Wiki
IAHispano/Applio

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

Loading diagram...

Source: app.py Source: core.py

图中的关键边界来自实际代码: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 参数。

启动阶段还会执行:

  1. 将 uvicorn 和 httpx 日志级别调到 warning;
  2. 在 Windows 上抑制特定的 ConnectionResetError;
  3. 修正 Gradio 数字控件对越界值和 None 的预处理;
  4. 导入所有能力 Tab;
  5. 调用 run_prerequisites_script(pretraineds_hifigan=True, models=True, exe=True);
  6. 初始化国际化、可选 Discord presence、安装检查和主题;
  7. 创建 gr.Blocks,并按产品能力注册 Tab。

这种启动顺序的设计意图是先准备运行环境,再构建 UI。模型或可执行依赖缺失时,问题会在用户进入具体能力前暴露,而不是在第一次推理时才失败。

Tab 组织

当前 app.py 明确注册了 Inference、Training、TTS、Voice Blender、Realtime、Plugins、Download、Report a Bug、Extra、Settings 和 TensorBoard。因此,Applio 的产品定位不是单一“转换按钮”,而是围绕语音模型生命周期组织的工作台:推理消费模型,训练生产模型,TTS 和实时能力扩展输入形态,下载和设置解决运行准备,TensorBoard 支持训练观察。

核心数据流

Loading diagram...

Source: core.py Source: core.py

对于普通推理,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 或核心编排函数调用。
python
1# app.py 在应用启动前执行运行前置条件 2run_prerequisites_script( 3 pretraineds_hifigan=True, 4 models=True, 5 exe=True, 6)

Source: app.py

python
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 中直接实现模型推理:

python
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,

Source: core.py Source: core.py

上述代码块分别截取了真实函数的签名和参数映射开头;函数后续还会继续加入效果参数并调用缓存的转换器。

实际源代码还会继续将后处理开关和具体效果参数加入 kwargs,并返回成功消息以及按照 export_format 替换扩展名后的输出路径。上面的摘录保留了入口、参数映射和转换器调用三个最能说明产品分层的部分。

高级:TTS 与 Voice Conversion 串联

run_tts_script 是一个真实的复合能力示例:它先调用仓库内 TTS 脚本,再复用相同的 VoiceConverter 完成音色转换。

python
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、自动调音和导出参数传给转换器:

python
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

选项类型默认值说明
--portint6969Gradio 服务端口;代码定义了 DEFAULT_PORT = 6969。
--server-namestr127.0.0.1服务绑定主机名;默认仅面向本机访问。
--shareflag关闭请求 Gradio 创建公开分享链接。
--openflag关闭请求自动打开浏览器。
--clientflag关闭启用 client mode,并为 Gradio Blocks 注入 realtime JavaScript。
assets/config.jsonJSON 文件从模板创建启动时若不存在,则复制 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

失败路径

  1. 配置模板缺失:app.py 只在 CONFIG_PATH 不存在时复制模板;源代码没有显示模板不存在时的专门恢复策略。
  2. TTS 子进程失败:直接抛出 RuntimeError,错误内容来自 stderr;这是 TTS 流程与预处理/特征提取流程不同的错误契约。
  3. 预处理或特征提取失败:返回包含模型名的失败字符串,并提示检查控制台日志。
  4. Windows 连接关闭异常:入口对 ConnectionResetError 做了定向抑制,避免远端连接强制关闭影响 asyncio shutdown。
  5. 非法 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

推荐的扩展顺序是:

  1. 在对应 tabs 模块增加或调整用户交互;
  2. 在 core.py 增加清晰的编排函数,负责参数校验、路径准备和底层调用;
  3. 若需要新算法或新模型工具,将执行逻辑放在 rvc 的对应模块;
  4. 在 app.py 只增加 Tab 注册、启动期初始化或全局 UI 行为;
  5. 对跨平台行为同时检查 Windows、macOS 和 Linux 分支,尤其是外部命令、路径和关闭系统调用。

不要直接把底层命令拼接到 UI 回调中;现有结构已经把脚本调用集中在 core.py,这有利于统一错误处理、缓存和输出路径语义。

Sources

(3 files)