浏览器端多语言音色迁移工程实践:OpenVoice V2 FP16 ONNX、WebGPU 与 ModelScope 模型分发

简介: Timeline Studio 是一款浏览器端多语言声音克隆与音色迁移工具,基于 OpenVoice V2 FP16 ONNX 模型,集成 ONNX Runtime Web、WebGPU/WASM 加速、双源模型分发(ModelScope/HF)、Cache Storage 缓存及 IndexedDB 声音档案。支持中文等11种语言,实现TTS语音生成+音色独立迁移,全程本地处理,无需服务器依赖。(239字)

本文记录 Timeline Studio 在浏览器中实现多语言声音克隆与音色迁移的工程方案,主要涉及:

  • OpenVoice V2 FP16 ONNX 模型组织
  • 浏览器音频预处理
  • ONNX Runtime Web 推理
  • WebGPU 与 WASM 执行
  • ModelScope 与 Hugging Face 双源分发
  • Cache Storage 模型缓存
  • IndexedDB 声音档案
  • 多语言 TTS 与音色迁移工作流
  • 音频尾部清理与输出增益
  • 时间线音频替换与恢复

项目仓库:

https://github.com/MartinDelophy/ai-video-editor

在线体验:

https://video-editor.ai-creator.top

一、功能工作流

Timeline Studio 将声音克隆拆分为两个独立阶段:

阶段一:生成目标语言语音
文本 → 基础 TTS → 中文、英文或其他语言音频

阶段二:迁移目标音色
源音频 → OpenVoice V2 → 克隆音色结果

完整浏览器工作流为:

录制或上传参考声音
        ↓
统一解码并重采样
        ↓
提取 256 维音色 Embedding
        ↓
生成所选语言的基础语音
        ↓
提取源音频音色
        ↓
执行 OpenVoice V2 音色迁移
        ↓
清理尾部填充与低幅噪声
        ↓
应用输出增益和软限幅
        ↓
试听并保存到 IndexedDB
        ↓
用于配音生成或时间线音频片段

语言由基础 TTS 决定,OpenVoice V2 负责音色迁移。

这样,同一个声音档案可以应用于多个语言,不需要在音色档案中绑定固定语言。

二、模型文件

浏览器版本使用两个 FP16 ONNX 文件:

文件 大小 用途
reference-encoder.onnx 1,637,269 Bytes 提取参考声音音色
converter.onnx 64,314,222 Bytes 执行音色迁移
合计 65,951,491 Bytes 完整浏览器运行模型

模型目录:

openvoice-v2-converter-fp16/
├── LICENSE
├── README.md
├── config.json
├── reference-encoder.onnx
└── converter.onnx

ModelScope 固定版本:

https://www.modelscope.cn/models/martindelophy/timeline-studio-voice-models/files?version=226b24270b69b38781a35566c7d442061f9e3b81&subpath=openvoice-v2-converter-fp16

Hugging Face 固定版本:

https://huggingface.co/haixin/timeline-studio-voice-models/tree/d9e0542e0e4e8fcfb849240f7e8e7fa8147df1a3/openvoice-v2-converter-fp16

生产代码不从 main 动态加载模型,而是固定到不可变 revision。

这样可以保证:

  • 模型文件不会被远端更新静默替换
  • 浏览器缓存身份保持稳定
  • 两个模型平台可以对应到同一运行版本
  • 出现问题时能够定位到具体模型快照

三、浏览器音频预处理

用户上传的参考音频可能来自不同设备和编码格式。

浏览器首先通过:

AudioContext.decodeAudioData()

将音频解码,再使用:

OfflineAudioContext

统一重采样。

内部音频格式固定为:

参数 数值
采样率 22,050 Hz
声道 单声道
内部数据 Float32 PCM
输出格式 16-bit PCM WAV

数据流如下:

WAV / MP3 / M4A / WebM
          ↓
AudioContext 解码
          ↓
OfflineAudioContext 重采样
          ↓
22.05 kHz Mono Float32Array

参考声音、基础 TTS 音频和音色迁移输出都使用相同的内部采样率。

四、STFT 与频谱输入

OpenVoice Converter 需要频谱输入。

浏览器 Worker 中实现了 Hann Window、FFT 和 STFT。

参数为:

参数 数值
FFT Size 1024
Hop Size 256
Frequency Bins 513

Reference Encoder 的输入形状:

[1, FrameCount, 513]

Converter 的频谱输入形状:

[1, 513, FrameCount]

音频长度决定 FrameCount,因此 ONNX Session 需要处理动态时间维度。

频谱计算、转置和张量构造均在 Worker 中完成,不占用 React 主线程。

五、音色 Embedding

参考音频经过 Reference Encoder 后生成:

speaker_embedding: [1, 256, 1]

保存声音时,系统会保存:

{
   
  id,
  name,
  sourceKind,
  referenceBlob,
  testBlob,
  embedding,
  favorite,
  authorized,
  createdAt,
  updatedAt
}

其中:

  • referenceBlob:原始参考声音
  • testBlob:克隆测试结果
  • embedding:256 维音色特征
  • sourceKind:录制或上传
  • authorized:授权确认状态

再次使用这个声音时,可以直接读取 Embedding,不需要重新运行 Reference Encoder。

六、Converter 输入

Converter 使用以下张量:

spectrogram:       [1, 513, T]
frame_mask:        [1, 1, T]
source_embedding:  [1, 256, 1]
target_embedding:  [1, 256, 1]
noise:             [1, 192, T]

其中:

  • source_embedding 来自需要转换的源音频
  • target_embedding 来自用户保存的参考声音
  • frame_mask 标记有效频谱区域
  • noise 使用固定种子生成

固定种子保证相同输入具有可复现性,便于浏览器调试和结果验证。

七、Web Worker 运行时

OpenVoice Runtime 运行在独立 Worker 中:

Main Thread
   ├── React 界面
   ├── AudioContext 解码
   ├── IndexedDB
   └── Timeline State
          ↓
     postMessage
          ↓
OpenVoice Worker
   ├── 模型下载
   ├── ONNX Session
   ├── FFT / STFT
   ├── Embedding
   ├── Converter
   └── 尾部处理

PCM 数据使用 Transferable ArrayBuffer 传输:

worker.postMessage(payload, [samples.buffer]);

这样可以避免浏览器在线程之间复制完整音频数组。

取消任务时直接终止 Worker:

worker.terminate();

同时拒绝所有尚未完成的请求,防止旧任务继续更新界面。

八、ONNX Runtime Web

浏览器使用:

import * as ort from "onnxruntime-web/webgpu";

WASM 配置:

ort.env.wasm.simd = true;

ort.env.wasm.numThreads = crossOriginIsolated
  ? Math.max(
      1,
      Math.min(4, navigator.hardwareConcurrency || 1)
    )
  : 1;

WebGPU 配置:

ort.env.webgpu.powerPreference = "high-performance";

Session 策略:

Reference Encoder
└── WASM

Converter
├── WebGPU
└── WASM Fallback

Converter 首先尝试:

ort.InferenceSession.create(modelBytes, {
   
  executionProviders: ["webgpu", "wasm"],
  graphOptimizationLevel: "all",
});

如果初始化失败,则重新创建 WASM Session。

模型文件采用并行下载:

Promise.all([
  loadReferenceEncoder(),
  loadConverter(),
]);

Session 顺序初始化,避免两个 ONNX 图同时编译造成瞬时内存峰值。

九、ModelScope 与 Hugging Face 双源分发

模型分发不是简单准备两个 URL。

系统为两个平台定义统一模型身份:

Repository
Revision
Relative Path
Cache Identity

路由逻辑为:

中文界面或国内网络环境
        ↓
ModelScope 优先
        ↓
失败后切换 Hugging Face

其他语言环境
        ↓
Hugging Face 优先
        ↓
失败后切换 ModelScope

第一次成功的模型来源会成为当前会话的优先线路。

如果网络环境发生变化或当前线路失败,运行时会清除会话线路记录,并尝试另一个来源。

两个平台使用相同缓存身份,因此不会出现:

ModelScope 缓存一份
+
Hugging Face 再缓存一份

十、Cache Storage

模型加载前会请求浏览器持久化存储:

navigator.storage.persist()

但是浏览器可能拒绝,因此缓存不能成为推理的前置条件。

实际策略为:

检查统一缓存
    ↓
命中:加载本地模型
    ↓
未命中:访问模型镜像
    ↓
下载成功:尝试写入缓存
    ↓
缓存写入失败:继续以内存运行

发生 QuotaExceededError 时:

  • 不终止推理
  • 不向用户显示原始异常
  • 跳过当前持久化写入
  • 继续使用已经下载到内存的模型
  • 后续重新检查缓存和模型源

预发布阶段产生的重复缓存会在新 Worker 初始化时删除,避免多个缓存版本争用浏览器存储空间。

十一、FP16 部署记录

当前发布模型固定使用 FP16。

FP16 在当前工程中的作用包括:

  • 降低模型下载大小
  • 降低权重在 GPU Buffer 中的占用
  • 保留 WebGPU 浮点执行路径
  • 允许浏览器使用 WASM 回退
  • 避免额外的反量化节点

FP8 没有进入当前生产链路。

虽然 ONNX 文件格式可以表达 Float8 类型,但浏览器 WebGPU 目前缺少稳定的通用 FP8 原生计算路径。

FP8 权重进入浏览器后,可能需要:

FP8
 ↓
Cast / Dequantize
 ↓
FP16 或 FP32
 ↓
WebGPU Kernel

这会增加:

  • 类型转换节点
  • 图切分概率
  • WASM 回退概率
  • CPU/GPU 数据交换
  • 浏览器兼容验证范围
  • 音频质量验证成本

因此,当前版本只保留已经验证的 FP16 模型。

FP8 作为后续独立实验,不进入当前生产模型目录和缓存身份。

十二、尾部低幅噪声处理

音色迁移结果的末尾可能包含模型填充区域。

随机噪声输入可能让这些区域产生轻微呼吸声或低幅噪声。

我们根据源音频 RMS 判断真实结束位置。

参数如下:

参数 数值
RMS Window 20 ms
RMS Hop 10 ms
最低有效峰值 0.0025
活动阈值 max(0.0015, peakRms × 0.035)
尾部保留 160 ms
淡出 40 ms

流程:

计算源音频分段 RMS
        ↓
找到最后一个活动窗口
        ↓
保留 160 ms 自然尾部
        ↓
裁掉后续模型填充
        ↓
应用 40 ms 余弦淡出

对于非常安静的输入,如果峰值不足以可靠判断活动边界,则保留原始长度,不主动裁剪。

十三、输出增益

音色迁移结果支持 0% 至 400% 增益。

高增益情况下使用 tanh 软限幅:

const amplified = sample * gain;

const output =
  Math.tanh(amplified * 1.35) /
  Math.tanh(1.35);

处理后的音频重新编码为:

RIFF WAV
PCM
Mono
22,050 Hz
16-bit

十四、IndexedDB 声音档案

声音档案保存到 IndexedDB。

IndexedDB 可以保存:

  • Blob
  • Float32Array
  • 字符串和时间戳
  • 收藏状态
  • 授权状态

保存成功后,克隆声音会出现在:

  • 声音克隆
  • 语音合成声音列表
  • 收藏声音
  • 音频片段音色属性

用户可以取消收藏或彻底删除档案。

十五、时间线集成

选中音频片段后,属性面板包含独立的“音色”页面。

操作链路:

选择音频片段
      ↓
打开音色属性
      ↓
选择已保存声音
或上传/录制临时声音
      ↓
转换当前片段
      ↓
试听转换结果
      ↓
保存到 My assets
      ↓
替换当前片段

替换前会保留原始音频地址和元数据。

因此可以执行:

替换为克隆音色
        ↓
继续编辑
        ↓
恢复原始声音

生成结果不会自动插入时间线,必须由用户明确确认。

十六、多语言界面

声音克隆工作流已经覆盖:

  • 中文
  • English
  • 日本語
  • 한국어
  • Español
  • Français
  • Deutsch
  • Português
  • ไทย
  • Tiếng Việt
  • Русский

本地化内容包括:

  • 录制与上传
  • 音色提取
  • 模型准备
  • 克隆试听
  • 保存声音
  • 收藏与删除
  • 转换失败
  • 本地处理说明
  • 授权确认
  • 片段替换与恢复

不同语言根据实际文本长度调整 Tab 和卡片排版,避免直接翻译后产生溢出。

十七、工程文件

核心运行文件:

src/lib/openVoiceRuntime.js
src/workers/openvoice.worker.js
src/lib/baseVoiceSynthesis.js
src/lib/voiceProfileStorage.js
src/hooks/useVoiceProfiles.js
src/hooks/useVoiceGeneration.js
src/components/VoicePanel.jsx
src/components/panels.jsx
src/config/voiceModels.js
public/model-cache-sw.js

本文用于归档 Timeline Studio 浏览器本地多语言音色迁移的当前生产实现。后续模型版本、ONNX Runtime Web、WebGPU 后端或缓存策略发生变化时,将继续按照固定 revision 和 Git 提交记录更新。

ModelScope #OpenVoice V2 #ONNX #Runtime Web #WebGPU #WASM #FP16 #声音克隆 #浏览器 AI #IndexedDB #开源视频编辑器

相关文章
|
1月前
|
监控 Shell API
Qoder CLI /loop 大升级:Agent 自调节奏,盯盘场景交给它就行了
Loop Engineering 新增动态唤醒机制:`/loop` 不再依赖固定间隔,Agent 可自主决定检查频率、触发时机与终止条件。支持 Monitor 事件秒级响应、三模式自动路由、TUI 管理面板及持久化任务,让盯盘、告警监控等弹性场景真正实现“交出判断权”。
299 0
|
1月前
|
人工智能 编解码 缓存
Timeline Studio 重大升级:安装一个 Skill,让 AI 在一杯咖啡的时间里完成视频剪辑,并交付可编辑工程
Timeline Studio 是一款AI视频编辑工具,支持从图片/视频/网址自动生成专业视频,并交付可编辑的`.timeline`工程文件。它兼顾自动剪辑与人工精修,实现“一杯咖啡成片,随时局部修改”。开源免费,浏览器本地运行。
|
2月前
|
人工智能 前端开发 数据库
一人用 Qoder 开十二个对话,五天写完全部代码
瑕玉Xiayu 在 AdventureX 黑客松比赛中开发了多智能体决策系统 Ludus,5 天时间 + 12 个 Qoder Agent 并行完成。系统以“可追溯、可审计、可复盘”为核心,通过规则先行、跨会话记忆、契约卡点保障质量,实现结构化决策支持。
311 0
|
Java 数据库连接 mybatis
【Spring常见错误】No qualifying bean of type
📋📋 精彩摘要:MyBatis 核心配置文件(xxxConfig.xml),该文件配置了MyBatis的一些全局信息,,包含数据库连接信息和MyBatis运行时所需的各种特性,以及设置和响应MyBatis行为的一些属性。本文将深入浅出的介绍MyBatis核心配置文件中常用的标签配置。
7286 0
|
1月前
|
人工智能 安全 语音技术
当语言被困住:我们和 Qoder 跑通了一条有尊严的表达链路
MeantByMe是一款由Qoder赋能的语音补全产品,专为失语患者设计:实时补全含糊话语,经用户确认后播报,守护表达权与尊严。五天内,三人小队借助Qoder知识引擎与多Agent协作,高效完成全栈开发。
168 0
当语言被困住:我们和 Qoder 跑通了一条有尊严的表达链路
|
1月前
|
机器学习/深度学习 人工智能 缓存
如何用 Agent Skill 构建一套可编辑、可验证的 AI 视频生产流水线
Timeline Studio 是开源AI视频编辑系统,支持从自然语言需求出发,自动完成素材分析、剪辑决策、时间线修改、浏览器端本地AI推理(Whisper/VITS等)及成片+可编辑`.timeline`工程双重交付,实现专业级自动化视频生产。
|
2月前
|
编解码 缓存 人工智能
从 ffmpeg.wasm 到 WebCodecs:浏览器视频编辑器导出架构的演进与实践
本文介绍了一种混合架构的浏览器视频编辑器导出方案:以Canvas+WebCodecs逐帧合成与编码、OfflineAudioContext混音为核心,ffmpeg.wasm仅负责音频提取、格式标准化及MP4转码等专项任务,兼顾预览一致性、性能与容错性。(239字)
从 ffmpeg.wasm 到 WebCodecs:浏览器视频编辑器导出架构的演进与实践
|
2月前
|
人工智能 缓存 编解码
把 AI 视频剪辑搬进浏览器:Timeline Studio 的本地优先架构与工程实践
视频剪辑、语音合成、自动字幕和 AI 视觉处理,过去往往意味着桌面客户端、服务端转码集群以及漫长的素材上传。Timeline Studio 尝试了另一条路线:以浏览器为完整运行环境,把多轨时间线、ONNX 端侧推理、Canvas 合成、离线音频混音和 WebCodecs 编码连接成一个可用的 AI 视频编辑器。本文结合项目实践,拆解这套架构为何成立、最难的三个工程问题,以及我们如何处理预览与导出一致性、模型缓存、时间线精度和兼容回退
|
4月前
|
人工智能 自然语言处理 机器人
[开源框架-实战]用 Hermes Agent 搭一个微信播报机器人
30 分钟,零 Python 代码,搭出一个每天早上 9 点把 GitHub Trending 推送到你微信的机器人。顺带把 Hermes 的 Skill、Gateway、Cron 四个招牌能力全用上。
1232 8

热门文章

最新文章