通过使用藏语语音合成技术,可以把一段藏文文字,快速变成可用的音频,用在短视频、朗读、课件或字幕配音里。本文介绍一套 Python 脚本,可以直接合成藏语三大方言的语音:
- 卫藏方言:
facebook/mms-tts-bod([Hugging Face][1]) - 康巴方言:
facebook/mms-tts-khg([Hugging Face][2]) - 安多方言:
facebook/mms-tts-adx([Hugging Face][3])
它们都属于 Meta 的 MMS-TTS 系列,并且在 Transformers 4.33+ 就能直接调用。([Hugging Face][3])
语音合成技术可以用来干什么?
-
语言学习短视频配音
每行一句藏文文字,批量合成音频;导入剪映等视频编辑工具,配字幕、配画面,快速出片。
-
课件/朗读材料配音
把教材段落放进文本文件,生成"逐句音频 + 合并后的整段音频",课堂或自学都方便。
-
多方言对比
同一段藏文,用卫藏/康巴/安多方言各合成一版,做对比学习或演示。
准备工作
1)安装依赖
在命令行里执行:
bash
pip install -U transformers accelerate torch soundfile numpy
可选(推荐,但没有也能跑):
bash
pip install -U scipy
2)准备一个文本文件(每行一句)
例如:sentences_tbt.txt
- 每行写一条藏文句子
- 空行会自动跳过
- 也可以写代码来把文本分割为句子
最简单的用法:改 3 行就能跑
新建文件:tibetan_tts_easy.py,复制下面全部代码。你只需要改最上面的三行:方言、输入文件名、输出目录。
这份脚本会同时生成:
- 逐句 wav:
adx_0001.wav、adx_0002.wav...- 合并后的整段 wav:
adx_full.wav
并且强制输出 PCM_16,避免"播放器能播但剪映无声"的问题。
python
from transformers import VitsModel, AutoTokenizer
import torch
import soundfile as sf
import numpy as np
import os
from math import gcd
# ========== 你只需要改这 3 行 ==========
DIALECT = "adx" # "bod"(卫藏方言) / "khg"(康巴方言) / "adx"(安多方言)
INPUT_FILE = "sentences_tbt.txt"
OUTPUT_DIR = "wavs_adx"
# ===================================
# 句子之间停顿(秒)
GAP_SECONDS = 0.2
# 为了剪映/剪辑软件兼容:强制写 PCM16
WAV_SUBTYPE = "PCM_16"
# 可选:统一采样率到 48000(更适合剪映/PR)
TARGET_SR = 48000 # 不想重采样可改成 None
DIALECT_MODELS = {
"bod": "facebook/mms-tts-bod", # :contentReference[oaicite:4]{index=4}
"khg": "facebook/mms-tts-khg", # :contentReference[oaicite:5]{index=5}
"adx": "facebook/mms-tts-adx", # :contentReference[oaicite:6]{index=6}
}
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
def read_sentences(path):
out = []
with open(path, "r", encoding="utf-8") as f:
for line in f:
t = line.strip()
if t:
out.append(t)
return out
def normalize(audio, target_peak=0.95):
audio = audio.astype(np.float32, copy=False)
peak = float(np.max(np.abs(audio)) + 1e-12)
if peak > 0:
audio = np.clip(audio / peak * target_peak, -1.0, 1.0)
return audio
def resample_if_needed(audio, orig_sr, target_sr):
if target_sr is None or target_sr == orig_sr:
return audio, orig_sr
try:
import scipy.signal
except ImportError:
print("[WARN] 未安装 scipy,跳过重采样,使用原采样率输出。")
return audio, orig_sr
g = gcd(orig_sr, target_sr)
up = target_sr // g
down = orig_sr // g
audio2 = scipy.signal.resample_poly(audio, up, down).astype(np.float32)
return audio2, target_sr
def main():
model_name = DIALECT_MODELS[DIALECT]
print(f"Loading {model_name} on {DEVICE} ...")
model = VitsModel.from_pretrained(model_name).to(DEVICE)
tokenizer = AutoTokenizer.from_pretrained(model_name)
os.makedirs(OUTPUT_DIR, exist_ok=True)
sents = read_sentences(INPUT_FILE)
print(f"Loaded {len(sents)} lines from {INPUT_FILE}")
if not sents:
return
full_path = os.path.join(OUTPUT_DIR, f"{DIALECT}_full.wav")
full_writer = None
full_sr = None
for i, text in enumerate(sents, start=1):
inputs = tokenizer(text, return_tensors="pt").to(DEVICE)
with torch.no_grad():
wav = model(**inputs).waveform.squeeze().cpu().numpy()
wav = wav.reshape(-1) # 保证一维
wav = normalize(wav)
sr = int(model.config.sampling_rate)
wav, sr = resample_if_needed(wav, sr, TARGET_SR)
if full_writer is None:
full_sr = sr
gap = np.zeros(int(full_sr * GAP_SECONDS), dtype=np.float32)
full_writer = sf.SoundFile(
full_path, mode="w", samplerate=full_sr, channels=1,
subtype=WAV_SUBTYPE, format="WAV"
)
print("FULL:", full_path)
seg_path = os.path.join(OUTPUT_DIR, f"{DIALECT}_{i:04d}.wav")
sf.write(seg_path, wav, full_sr, subtype=WAV_SUBTYPE)
full_writer.write(wav)
if GAP_SECONDS > 0:
full_writer.write(gap)
print(f"[{i}/{len(sents)}] {seg_path}")
full_writer.close()
print("Done.")
if __name__ == "__main__":
main()
运行:
bash
python tibetan_tts_easy.py
导入剪映的最稳设置(避免"无声")
你只要用上面脚本输出的 WAV(PCM_16),一般直接导入就会有波形和声音。原因是模型页本身给的是波形输出示例,但很多人保存时会写成 float WAV,剪辑软件兼容性不稳定;而 MMS 模型在 Transformers 4.33+ 可直接推理,这点在模型页也写得很清楚。([Hugging Face][3])
常见问题
1)能不能选"男声/女声/不同音色"?
就这三个 MMS 藏语方言 checkpoint 来说,你可以理解为:每个方言模型基本就是一个固定声音风格。它们主要提供"能把文本读出来"的能力,而不是"内置很多音色可选"的商业 TTS 音色库。([Hugging Face][3])
2)能不能控制语速?
对非技术用户,最稳的方式是:合成完再变速(不会影响能不能合成)。例如把音频加速 1.15 倍:
bash
ffmpeg -y -i input.wav -filter:a "atempo=1.15" output.wav
3)同一句话每次合成略有差别,正常吗?
正常。VITS 合成本身有非确定性;如果你希望"每次一样",可以固定随机种子(Transformers 的 VITS 文档也专门提醒了这点)。([Hugging Face][4])
使用许可提醒(建议写在文末,避免踩坑)
这几个模型页面都标注了许可证为 CC BY-NC 4.0(非商业)。如果你用于商业用途(付费课程、付费 App、广告变现等),务必先确认许可范围。([Hugging Face][3])