Skip to content

필사 모드: 语音与音频 AI 完全指南:Whisper、TTS、说话人识别、音乐生成

中文
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

1. 语音基础:把声音理解为数字

声波与数字音频

声音是空气压力随时间的变化。麦克风将这种压力变化转换为电信号,ADC(模数转换器)按固定间隔采样,并存储为数字数组。

核心概念:

  • 采样率(Sample Rate):每秒采样次数。要覆盖人类可听范围(20Hz~20kHz),根据奈奎斯特定理至少需要 40kHz。语音 AI 中 16kHz 是标准。
  • 位深度(Bit Depth):每个采样点的精度。16-bit = 65,536 级,24-bit = 16,777,216 级。
  • 声道:单声道(1 声道) vs 立体声(2 声道)。语音识别大多使用单声道 16kHz。

FFT 与频谱图

把时域波形转换为频域的 FFT(快速傅里叶变换),是音频分析的核心。

import librosa
import librosa.display
import numpy as np
import matplotlib.pyplot as plt

# 加载音频文件 (16kHz 单声道)
y, sr = librosa.load("speech.wav", sr=16000, mono=True)
print(f"样本数: {len(y)}, 采样率: {sr}Hz, 长度: {len(y)/sr:.2f}秒")

# STFT (短时傅里叶变换)
n_fft = 512        # FFT 窗口大小
hop_length = 128   # 窗口移动间隔

D = librosa.stft(y, n_fft=n_fft, hop_length=hop_length, window="hann")
magnitude = np.abs(D)

# 功率频谱图 (dB 刻度)
S_db = librosa.amplitude_to_db(magnitude, ref=np.max)

fig, axes = plt.subplots(3, 1, figsize=(12, 10))

# 波形
axes[0].plot(np.linspace(0, len(y)/sr, len(y)), y)
axes[0].set_title("波形 (Waveform)")
axes[0].set_xlabel("时间 (秒)")

# 线性频谱图
librosa.display.specshow(S_db, sr=sr, hop_length=hop_length,
                         x_axis="time", y_axis="linear", ax=axes[1])
axes[1].set_title("线性频谱图 (Linear Spectrogram)")

# Mel 频谱图
mel_spec = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=80,
                                           n_fft=n_fft, hop_length=hop_length)
mel_db = librosa.power_to_db(mel_spec, ref=np.max)
librosa.display.specshow(mel_db, sr=sr, hop_length=hop_length,
                         x_axis="time", y_axis="mel", ax=axes[2])
axes[2].set_title("Mel 频谱图 (80 Mel bins)")

plt.tight_layout()
plt.savefig("spectrogram_comparison.png", dpi=150)

MFCC:语音的压缩指纹

MFCC(梅尔频率倒谱系数, Mel-Frequency Cepstral Coefficients)是模拟人类听觉系统的特征。

处理步骤:

  1. 应用预加重(Pre-emphasis)滤波器 — 强调高频成分
  2. 分帧 + 加窗
  3. FFT → 功率谱
  4. 应用 Mel 滤波器组(将频率轴转换为 Mel 刻度)
  5. 取对数
  6. DCT(离散余弦变换) → MFCC 系数
import librosa
import numpy as np

def extract_mfcc_features(audio_path, sr=16000, n_mfcc=13, n_mels=40):
    """
    MFCC 特征提取函数
    返回:形状为 (39, T) 的 mfcc + delta + delta2 特征
    """
    y, sr = librosa.load(audio_path, sr=sr)

    # 预加重
    y_emphasized = np.append(y[0], y[1:] - 0.97 * y[:-1])

    # 提取 MFCC
    mfcc = librosa.feature.mfcc(
        y=y_emphasized, sr=sr,
        n_mfcc=n_mfcc,
        n_mels=n_mels,
        n_fft=512,
        hop_length=160,   # 10ms (以 16kHz 为基准)
        win_length=400,   # 25ms
        window="hann"
    )

    # Delta (一阶导数) — 动态特征
    delta = librosa.feature.delta(mfcc)
    # Delta-Delta (二阶导数)
    delta2 = librosa.feature.delta(mfcc, order=2)

    # 39 维特征向量 (13 + 13 + 13)
    features = np.vstack([mfcc, delta, delta2])

    # CMVN 归一化
    features = (features - features.mean(axis=1, keepdims=True)) / \
               (features.std(axis=1, keepdims=True) + 1e-8)

    return features  # shape: (39, T)

features = extract_mfcc_features("speech.wav")
print(f"MFCC 特征 shape: {features.shape}")

2. 语音识别(ASR):将话语转换为文字

CTC (联结主义时序分类, Connectionist Temporal Classification)

传统 ASR 是声学模型 + 语言模型 + 发音词典的三阶段流水线。CTC 革命性地降低了这种复杂度。

CTC 的核心思想:

  • 输入序列(语音帧)与输出序列(文本)的长度互不相同
  • 引入特殊的 blank 令牌解决对齐问题
  • 通过对所有可能的对齐(alignment)概率求和进行训练(Forward-Backward 算法)
  • 通过合并(collapse)解码去除连续相同标签与 blank

CTC 解码示例: a-a-blank-bab

Seq2Seq with Attention

基于 RNN 的 Seq2Seq 模型与 CTC 不同,内在地包含了语言模型。

  • 编码器:用 BiLSTM/Transformer 把语音帧转换为上下文向量
  • 注意力:在每个解码步骤决定关注编码器输出的哪一部分
  • 解码器:用之前的输出令牌 + 注意力上下文生成下一个令牌

Whisper 架构完全解剖

OpenAI Whisper 是用 680,000 小时的多语言语音训练出来的编码器-解码器 Transformer。

架构细节:

  • 音频编码器:30 秒分块 → 80 通道 log-Mel 频谱图 → 2 个 Conv1D → Transformer 编码器
  • 文本解码器:通过交叉注意力参照音频上下文 → 自回归生成
  • 特殊令牌:语言令牌、任务令牌(transcribe/translate)、时间戳令牌
import whisper
import json

def transcribe_with_timestamps(audio_path, model_size="large-v3", language="ko"):
    """
    使用 Whisper 进行带时间戳的转写
    模型大小: tiny, base, small, medium, large, large-v3
    """
    model = whisper.load_model(model_size)

    result = model.transcribe(
        audio_path,
        language=language,
        task="transcribe",           # 改为 "translate" 则翻译为英语
        word_timestamps=True,        # 按单词的时间戳
        condition_on_previous_text=True,
        temperature=0,
        beam_size=5,
        verbose=False
    )

    print(f"完整转写: {result['text']}")
    print(f"检测到的语言: {result['language']}")

    for seg in result["segments"]:
        start = f"{seg['start']:.2f}s"
        end   = f"{seg['end']:.2f}s"
        text  = seg["text"].strip()
        print(f"[{start} -> {end}] {text}")

        if "words" in seg:
            for word in seg["words"]:
                ws = f"{word['start']:.2f}s"
                we = f"{word['end']:.2f}s"
                print(f"  {word['word']}: {ws}~{we}")

    return result

result = transcribe_with_timestamps("meeting.wav", model_size="large-v3", language="ko")

with open("transcript.json", "w", encoding="utf-8") as f:
    json.dump(result, f, ensure_ascii=False, indent=2)

韩语/日语 ASR 的特殊性

韩语 ASR 的挑战:

  • 黏着语:词尾变化极为多样(먹다/먹어/먹었다/먹겠다)
  • 连音现象:"국어" 发音为 [구거]
  • 硬音化/送气音化:需要处理复杂的音变规则
  • 分写(空格)不规则,需要后处理

日语 ASR 的挑战:

  • 平假名、片假名、汉字三种文字体系混用
  • 长元音/短元音的区分(오코리, 오코리이)
  • 元音清化现象(す、き 等假名的不发声化)

3. 语音合成(TTS):将文字转换为声音

Tacotron 2 → FastSpeech 2 → VITS 的演进

模型架构特点推理速度
Tacotron 2Seq2Seq + Attention韵律自然,推理较慢
FastSpeech 2非自回归 Transformer显式 duration/pitch/energy
VITSVAE + Normalizing Flow + GAN单一模型,音质最佳中等

FastSpeech 2 合成实战

from TTS.api import TTS
import torch

def synthesize_speech_ko(text, output_path, speed=1.0):
    """
    使用 Coqui TTS 进行韩语语音合成
    模型: tts_models/ko/css10/vits
    """
    device = "cuda" if torch.cuda.is_available() else "cpu"
    tts = TTS("tts_models/ko/css10/vits").to(device)

    tts.tts_to_file(
        text=text,
        file_path=output_path,
        speed=speed,
    )
    print(f"合成完成: {output_path}")

# 韩语 TTS 示例
text_ko = "안녕하세요. 음성 AI 기술이 놀랍도록 발전했습니다."
synthesize_speech_ko(text_ko, "output_ko.wav")

# 多语言 TTS (XTTS-v2)
def synthesize_multilang(text, language, speaker_wav, output_path):
    """
    XTTS-v2: 说话人语音克隆 + 多语言合成
    language: "ko", "ja", "en", "zh-cn" 等
    speaker_wav: 3~6 秒参考语音
    """
    tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
    tts.tts_to_file(
        text=text,
        language=language,
        speaker_wav=speaker_wav,
        file_path=output_path,
    )

synthesize_multilang(
    "목소리를 복제하여 다국어로 말할 수 있습니다.",
    language="ko",
    speaker_wav="reference_voice.wav",
    output_path="cloned_ko.wav"
)

VITS:端到端语音合成的革新

VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech,面向端到端 TTS 的对抗学习变分推断)直接从文本生成波形。

核心组成:

  1. Posterior Encoder(后验编码器):目标音频 → 潜在变量 z
  2. Prior Encoder(先验编码器):文本 → 先验分布(包含 normalizing flow)
  3. Decoder(解码器, HiFi-GAN):潜在变量 z → 波形
  4. Stochastic Duration Predictor(随机时长预测器):预测每个音素的持续时间

Normalizing flow 把复杂的语音分布转换为简单的高斯分布,从而提升训练稳定性。相比 Tacotron 2,VITS 支持并行推理,且不需要外部声码器。


4. 说话人识别:谁在说话

x-vector 与 ECAPA-TDNN

i-vector(传统方法):

  • 基于 GMM-UBM 的总变异性空间建模
  • 生成固定长度的说话人嵌入
  • 特征较浅,判别能力有限

x-vector(深度学习方法):

  • 基于 TDNN(时延神经网络, Time Delay Neural Network)
  • 帧级特征 → 统计池化 → 段级嵌入
  • 用 PLDA(概率线性判别分析)打分

ECAPA-TDNN(强调通道注意力、传播与聚合):

  • 多尺度特征聚合
  • 通过通道注意力机制提升说话人区分能力
  • 2020 年 VoxCeleb 挑战赛冠军

用 pyannote.audio 做说话人分离(Diarization)

from pyannote.audio import Pipeline
import torch

def speaker_diarization(audio_path, hf_token, num_speakers=None):
    """
    说话人分离: 识别谁在何时说话
    """
    pipeline = Pipeline.from_pretrained(
        "pyannote/speaker-diarization-3.1",
        use_auth_token=hf_token
    )

    if torch.cuda.is_available():
        pipeline = pipeline.to(torch.device("cuda"))

    params = {}
    if num_speakers:
        params["num_speakers"] = num_speakers
    else:
        params["min_speakers"] = 1
        params["max_speakers"] = 10

    diarization = pipeline(audio_path, **params)

    segments = []
    for turn, _, speaker in diarization.itertracks(yield_label=True):
        seg = {
            "start": round(turn.start, 3),
            "end": round(turn.end, 3),
            "speaker": speaker
        }
        segments.append(seg)
        print(f"[{seg['start']:.3f}s ~ {seg['end']:.3f}s] {speaker}")

    with open("diarization.rttm", "w") as rttm:
        diarization.write_rttm(rttm)

    speakers_found = len(set(s["speaker"] for s in segments))
    print(f"\n共检测到 {speakers_found} 位说话人")
    return segments

segments = speaker_diarization("meeting.wav", hf_token="YOUR_HF_TOKEN")

结合 Whisper + pyannote:按说话人转写

import whisper
from pyannote.audio import Pipeline
import torch

def diarize_and_transcribe(audio_path, hf_token, language="ko"):
    """说话人分离 + 语音识别结合"""
    # 1. 说话人分离
    diarization_pipeline = Pipeline.from_pretrained(
        "pyannote/speaker-diarization-3.1",
        use_auth_token=hf_token
    )
    diarization = diarization_pipeline(audio_path)

    # 2. Whisper 转写
    asr_model = whisper.load_model("large-v3")
    asr_result = asr_model.transcribe(audio_path, language=language,
                                       word_timestamps=True)

    # 3. 单词时间戳与说话人信息映射
    words_with_speakers = []
    for seg in asr_result["segments"]:
        for word in seg.get("words", []):
            word_mid = (word["start"] + word["end"]) / 2
            speaker = "UNKNOWN"
            for turn, _, spk in diarization.itertracks(yield_label=True):
                if turn.start <= word_mid <= turn.end:
                    speaker = spk
                    break
            words_with_speakers.append({
                "word": word["word"],
                "start": word["start"],
                "end": word["end"],
                "speaker": speaker
            })

    # 4. 按说话人分组语句
    grouped = []
    current_speaker = None
    current_text = []

    for item in words_with_speakers:
        if item["speaker"] != current_speaker:
            if current_text:
                grouped.append({
                    "speaker": current_speaker,
                    "text": "".join(current_text).strip()
                })
            current_speaker = item["speaker"]
            current_text = [item["word"]]
        else:
            current_text.append(item["word"])

    if current_text:
        grouped.append({"speaker": current_speaker,
                        "text": "".join(current_text).strip()})

    for entry in grouped:
        print(f"[{entry['speaker']}]: {entry['text']}")

    return grouped

5. 音乐 AI:AudioCraft 与创作性音频

用 MusicGen 生成音乐

Meta 的 AudioCraft 包含用文字描述生成音乐的 MusicGen,以及生成一般音频的 AudioGen。

from audiocraft.models import MusicGen
from audiocraft.data.audio import audio_write
import torch

def generate_music(descriptions, duration=10, model_size="medium"):
    """
    根据文字描述生成音乐
    模型大小: small (300M), medium (1.5B), large (3.3B), melody
    """
    model = MusicGen.get_pretrained(f"facebook/musicgen-{model_size}")
    model.set_generation_params(
        duration=duration,     # 以秒为单位 (最长 30 秒)
        temperature=1.0,       # 控制创造性
        top_k=250,
        cfg_coef=3.0,          # Classifier-Free Guidance 强度
    )

    wav = model.generate(descriptions)
    # shape: (batch, channels, samples)

    for i, (desc, audio) in enumerate(zip(descriptions, wav)):
        audio_write(
            f"music_{i}",
            audio.cpu(),
            model.sample_rate,
            strategy="loudness",
            loudness_compressor=True
        )
        print(f"生成完成: music_{i}.wav")
        print(f"  描述: {desc}")

# 生成多种风格
descriptions = [
    "Upbeat K-pop with synth leads, 120 BPM, energetic and bright",
    "Calm Korean traditional music with gayageum and daegeum, peaceful",
    "Epic orchestral trailer music with powerful drums and brass",
    "Lo-fi hip hop beats with jazz piano, for studying",
]

generate_music(descriptions, duration=15, model_size="medium")

用 AudioGen 生成音效

from audiocraft.models import AudioGen
from audiocraft.data.audio import audio_write

def generate_sound_effects(descriptions, duration=5):
    """生成环境音、音效"""
    model = AudioGen.get_pretrained("facebook/audiogen-medium")
    model.set_generation_params(duration=duration, temperature=1.0)

    wav = model.generate(descriptions)

    for i, (desc, audio) in enumerate(zip(descriptions, wav)):
        audio_write(f"sfx_{i}", audio.cpu(), model.sample_rate)
        print(f"生成: sfx_{i}.wav — {desc}")

sound_descriptions = [
    "Rain falling on a tin roof with distant thunder",
    "Busy city street with cars and people talking",
    "Birds chirping in a forest at dawn",
    "Keyboard typing in a quiet office",
]

generate_sound_effects(sound_descriptions, duration=8)

用 Demucs 做音乐分离

import subprocess
import os

def separate_audio_tracks(audio_path, output_dir="separated", model="htdemucs"):
    """
    将音乐分离为人声/鼓/贝斯/吉他等
    模型: htdemucs (4-stem), htdemucs_6s (6-stem)
    """
    os.makedirs(output_dir, exist_ok=True)

    cmd = [
        "python", "-m", "demucs",
        "--name", model,
        "--out", output_dir,
        "--mp3",
        "--mp3-bitrate", "320",
        audio_path
    ]

    result = subprocess.run(cmd, capture_output=True, text=True)

    if result.returncode == 0:
        base_name = os.path.splitext(os.path.basename(audio_path))[0]
        stems_dir = os.path.join(output_dir, model, base_name)
        stems = os.listdir(stems_dir)
        print(f"分离成功!音轨: {stems}")
        # htdemucs: vocals.mp3, drums.mp3, bass.mp3, other.mp3
        # htdemucs_6s: + guitar.mp3, piano.mp3
    else:
        print(f"错误: {result.stderr}")

    return output_dir

separate_audio_tracks("song.mp3", model="htdemucs_6s")

6. 实时处理:流式 ASR 流水线

look-ahead window 在流式 ASR 中带来一个重要的权衡。看到的未来语音越多,准确率越高,但延迟也会随之增加。

import sounddevice as sd
import numpy as np
import whisper
import queue
import threading
from collections import deque

class RealTimeASR:
    """
    实时流式语音识别
    通过 look-ahead window 调节准确率/延迟的平衡
    """
    def __init__(self, model_size="small", language="ko",
                 chunk_duration=2.0, look_ahead=0.5, sample_rate=16000):
        self.model = whisper.load_model(model_size)
        self.language = language
        self.chunk_duration = chunk_duration
        self.look_ahead = look_ahead
        self.sample_rate = sample_rate
        self.audio_queue = queue.Queue()
        max_buf = int(sample_rate * (chunk_duration + look_ahead) * 3)
        self.buffer = deque(maxlen=max_buf)
        self.is_running = False

    def audio_callback(self, indata, frames, time, status):
        if status:
            print(f"音频状态: {status}")
        self.audio_queue.put(indata.copy())

    def process_audio(self):
        chunk_samples = int(self.sample_rate * self.chunk_duration)

        while self.is_running:
            audio_chunk = []
            while len(audio_chunk) < chunk_samples:
                try:
                    data = self.audio_queue.get(timeout=0.1)
                    audio_chunk.extend(data.flatten())
                except queue.Empty:
                    break

            if len(audio_chunk) < chunk_samples // 2:
                continue

            self.buffer.extend(audio_chunk)
            audio_array = np.array(list(self.buffer), dtype=np.float32)
            audio_array = audio_array / (np.max(np.abs(audio_array)) + 1e-8)

            result = self.model.transcribe(
                audio_array,
                language=self.language,
                temperature=0,
                no_speech_threshold=0.6,
            )

            if result["text"].strip():
                print(f"\r识别: {result['text'].strip()}", end="", flush=True)

    def start(self):
        self.is_running = True
        t = threading.Thread(target=self.process_audio, daemon=True)
        t.start()

        print("麦克风已激活 — 请说话 (Ctrl+C 结束)")
        with sd.InputStream(
            samplerate=self.sample_rate,
            channels=1,
            dtype="float32",
            blocksize=int(self.sample_rate * 0.1),
            callback=self.audio_callback
        ):
            try:
                while True:
                    sd.sleep(100)
            except KeyboardInterrupt:
                self.is_running = False
                print("\n识别结束")

# 运行
asr = RealTimeASR(model_size="small", language="ko",
                  chunk_duration=2.0, look_ahead=0.5)
asr.start()

7. 实战应用:会议自动摘要系统

import whisper
from pyannote.audio import Pipeline
from openai import OpenAI

def auto_meeting_summary(audio_path, hf_token, openai_key, language="ko"):
    """
    会议自动摘要: 说话人分离 + 转写 + LLM 摘要
    """
    client = OpenAI(api_key=openai_key)

    # 1. 说话人分离
    print("正在进行说话人分离...")
    diarization_pipeline = Pipeline.from_pretrained(
        "pyannote/speaker-diarization-3.1",
        use_auth_token=hf_token
    )
    diarization = diarization_pipeline(audio_path)

    # 2. 转写
    print("正在进行语音识别...")
    asr_model = whisper.load_model("large-v3")
    result = asr_model.transcribe(audio_path, language=language,
                                   word_timestamps=True)

    # 3. 说话人-文本映射及对话记录构建
    lines = []
    current_speaker = None
    current_words = []

    for seg in result["segments"]:
        for word in seg.get("words", []):
            mid = (word["start"] + word["end"]) / 2
            speaker = "UNKNOWN"
            for turn, _, spk in diarization.itertracks(yield_label=True):
                if turn.start <= mid <= turn.end:
                    speaker = spk
                    break

            if speaker != current_speaker:
                if current_words:
                    lines.append(f"[{current_speaker}]: {''.join(current_words).strip()}")
                current_speaker = speaker
                current_words = [word["word"]]
            else:
                current_words.append(word["word"])

    if current_words:
        lines.append(f"[{current_speaker}]: {''.join(current_words).strip()}")

    transcript = "\n".join(lines)

    # 4. LLM 摘要
    print("正在生成摘要...")
    prompt = f"""请将以下会议转写记录按下列条目进行摘要:

1. 主要讨论事项
2. 已决定事项
3. Action Items (含负责人)
4. 下次会议安排

转写记录:
{transcript[:4000]}"""

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3
    )

    summary = response.choices[0].message.content
    print("\n=== 会议摘要 ===")
    print(summary)

    return {"transcript": transcript, "summary": summary}

测验

Q1. CTC(联结主义时序分类, Connectionist Temporal Classification) loss 如何在没有对齐信息的情况下实现序列学习?

答案:CTC 通过对输入帧序列与输出标签序列之间所有可能的对齐(单调对齐, monotonic alignment)的概率求和来进行训练。

解析:当从语音的 T 个帧生成 N 个文本标签时,每一帧都会输出一个标签或 blank 令牌。通过去除相同标签的连续重复及 blank 的合并(collapse)解码规则来还原最终文本。Forward-Backward 算法(动态规划)能高效计算所有对齐的概率之和。这样一来,无需音素边界或对齐标注,仅凭文本标签即可完成训练。

Q2. 为什么 Mel 频谱图从听觉感知角度比线性频谱图更适合语音识别?

答案:人类的听觉系统对频率的感知呈对数尺度,而 Mel 刻度正反映了这一点。

解析:人耳的耳蜗(cochlea)在低频区域能更精细地区分频率,而在高频区域相对迟钝。Mel 滤波器组通过在低频区域密集布置滤波器、在高频区域稀疏布置来模拟这一特性。结果是,80 个 Mel bin 比 512 个线性 bin 能更紧凑、更有效地表达与语音相关的信息,使模型能更好地学习语音的声学特性。

Q3. 为什么 VITS 比 Tacotron 2 更适合做端到端训练(与 normalizing flow 相关)?

答案:VITS 通过 normalizing flow 直接建模文本与音频之间复杂的概率分布,从而无需中间表示(mel spectrogram)即可用单一模型完成训练。

解析:Tacotron 2 是文本 → mel spectrogram → 波形的两阶段流水线,每个阶段的误差都会累积。VITS 将 VAE 的潜在空间通过 normalizing flow 转换。Normalizing flow 是一条可逆函数链,能将简单的高斯分布精确转换为复杂的语音分布,反向也能精确计算似然。由此,文本条件先验分布与音频后验分布通过 flow 直接相连,实现了完整的端到端训练。

Q4. 为什么 x-vector 说话人嵌入比 i-vector 更适合用深度学习训练?

答案:x-vector 通过判别式(discriminative)学习直接优化说话人之间的决策边界,而 i-vector 基于生成式(generative)建模。

解析:i-vector 用 GMM-UBM 统计量与总变异性矩阵对说话人空间建模,并未显式优化用于说话人识别的判别边界。x-vector(基于 TDNN)通过 softmax 交叉熵直接学习说话人分类,因此说话人之间的决策边界更清晰。TDNN 的统计池化层将可变长度的语音转换为固定大小的嵌入,深度学习的非线性能捕捉复杂的说话人声学模式。数据充足时,x-vector 在 EER(等错误率, Equal Error Rate)上明显优于 i-vector。

Q5. 在流式 ASR 中,look-ahead window 在识别准确率与延迟之间造成怎样的权衡?

答案:look-ahead window 越大,越能利用未来上下文提升准确率,但结果输出的延迟(latency)也会随之增加。

解析:语音的时间上下文很重要。"배"这个词,是"배가 고프다(肚子饿)"里的"肚子",还是"배를 타다(坐船)"里的"船",要靠后面出现的词才能判断。look-ahead 为 0 时只看当前块,延迟最小,但边界部分的识别错误会增加。look-ahead 越长,准确率越高,但结果输出也越滞后。在实时字幕系统中,200~500ms 的 look-ahead 是实用的平衡点。CIF(Continuous Integrate-and-Fire)或 Emformer 等架构从结构上改善了这一权衡。


结语

语音 AI 是 ASR、TTS、说话人识别、音乐生成彼此关联的广阔而深邃的领域。从 Whisper 的多语言转写,到 pyannote 的说话人分离、VITS 的自然语音合成,直至 MusicGen 的音乐创作——今天介绍的这些工具全部都是开源可用的。将各个组件组合起来,就可以构建呼叫中心 AI、会议摘要、实时翻译、无障碍工具等各种实战系统。

현재 단락 (1/461)

声音是空气压力随时间的变化。麦克风将这种压力变化转换为电信号,ADC(模数转换器)按固定间隔采样,并存储为数字数组。

작성 글자: 0원문 글자: 15,182작성 단락: 0/461