概述

在語音轉文本ASR工具合集彙總介紹過幾款語音識別模型和項目,其中就包括OpenAI開源的Whisper。

論文,OpenAI開源的支持多語言的通用ASR。在68萬小時的標註數據上進行訓練,有很強的泛化能力;作為一個多任務模型,可執行多語言語音識別、語音翻譯和口語識別。通過使用分塊算法,也可用於轉錄任意長度的音頻樣本。分塊是通過在實例化管道時設置chunk_length_s=30啓用。

Whisper共提供5種不同參數大小的模型,其中4種有專一的英文模型,在速度與準確性做平衡。

Size

Parameters

English-only model

Multilingual model

Required VRAM

Relative speed

tiny

72M

tiny.en

tiny

~1GB

~32x

base

138M

base.en

base

~1GB

~16x

small

-M

small.en

small

~2GB

~6x

medium

-M

medium.en

medium

~5GB

~2x

large

-M

N/A

large

~10GB

1x

注:largev1v2v3三個版本,v3還有個openai/whisper-large-v3-turbo版本。

對於本地部署的模型,WAV和TS(Transport Stream,一種流媒體容器格式,用於在數字電視廣播中傳輸音頻和視頻數據)文件都可直接使用,但TS文件在OpenAI付費接口上不行,需要提前通過FFMPEG將TS文件轉為mp3文件。

技術

核心工作流

五步完成語音轉文本的蜕變,Whisper的成功關鍵,在於精準的預處理與高效Transformer二者之間的協同作用。許多人僅僅關注Transformer架構本身,卻忽略其前置處理環節中那些精巧的設計——正是80通道的梅爾頻譜圖,經過兩次卷積操作,並結合GELU激活函數,才為Transformer的高效運行,打下堅實的基礎。整個處理流程,可劃分為五個核心步驟:

  1. 音頻標準化:將任意採樣率的原始音頻統一重採樣至16kHz(模型標準輸入);
  2. 梅爾頻譜轉換:將標準化音頻,轉為80通道對數幅度梅爾頻譜圖(v3版本升級為128通道),把波形信號,變成符合人耳特性的特徵圖像;
  3. 特徵精煉:通過兩層卷積提取局部語音特徵,GELU(Gaussian Error Linear Unit)注入非線性,完成降維提效;
  4. 編碼階段:加入旋轉位置編碼(RoPE),經Transformer編碼器捕捉全局依賴;
  5. 解碼與後處理:結合CTC(Connectionist Temporal Classification)與自迴歸解碼生成文本,自動完成語言識別、標點與時間戳標註。

OpenAI Whisper:技術、實戰、生態_數據

架構基石

Transformer雖擅長於捕捉長序列的全局關係,但卻無法直接對原始音頻進行處理——它既不善於提取局部特徵,也難以應付海量冗餘的數據。Whisper的80通道梅爾頻譜圖、經過兩次的卷積以及GELU,恰恰是為了解決這一矛盾而誕生的三重前置處理模塊,構成模型架構的底層重要基礎。

第一重魔法:80通道梅爾頻譜圖

原始音頻,它是連續的波形(在16kHz的採樣率下,10秒之中包含16萬個振幅的數據點),倘若直接進行輸入,這樣就會致使數據爆炸和特徵冗餘。梅爾頻譜圖的核心作用在於模擬人耳的聽覺特性,以此來達成信號提純的目的。

  • 設計邏輯:人耳對於低頻(100-400Hz,此為説話基音)較為敏感,而對高頻(>8000Hz,乃是環境噪聲)不太敏感。80個通道恰好能夠覆蓋人類語音的核心頻率範圍,這樣既不會丟失關鍵信息,與此同時又能夠壓縮數據量(10秒音頻數據量從16萬降低至8萬)。
  • 技術細節:經短時傅里葉變換(STFT轉頻譜→梅爾濾波器組提能量→取對數放大弱信號,最終得到時間-頻率二維特徵圖
  • 架構意義:將波形信號轉化為模型易理解的頻率特徵,為後續處理奠定基礎

核心代碼:梅爾頻譜圖生成(關鍵參數標註)

import librosa
import numpy as np

def generate_whisper_mel(audio_path: str):
	# 1. 加載音頻並統一採樣率為16kHz
	waveform, _ = librosa.load(audio_path, sr=16000)
	# 2. 按Whisper標準參數生成80通道梅爾譜
	mel_spec = librosa.feature.melspectrogram(
		y=waveform, sr=16000, n_fft=400, hop_length=160, n_mels=80, fmax=8000
	)
	# 3. 對數轉換+歸一化(Whisper必填步驟)
	log_mel = np.log(np.clip(mel_spec, a_min=1e-10, a_max=None))
	return (log_mel - log_mel.mean()) / (log_mel.std() + 1e-6)

mel_feature = generate_whisper_mel("sample_audio.wav")
print(f"梅爾譜形狀: {mel_feature.shape}") # 輸出(80, 時間步長)

第二重魔法:兩次卷積

梅爾頻譜圖,仍含有局部冗餘,兩次卷積所構成的特徵提取詞幹,核心作用在於提取局部語音特徵,與此同時降低時間維度,以便為Transformer輸送精煉素材。

  • 層級分工
  • 第一次卷積:16個3×3核,提取聲帶振動濁音、摩擦音清音等基礎特徵,80通道→16通道;
  • 第二次卷積:32個3×3核步長2,將其整合為音素級特徵;在此期間,把時間維度壓縮至12,減少Transformer計算量;
  • 架構意義:幫Transformer提前完成局部特徵提取,避免其在原始頻譜中大海撈針

第三重魔法:GELU激活函數——給模型注入非線性理解能力

卷積輸出,需經激活函數,這樣能產生非線性變換,從而才能夠理解複雜語音規律,(例如升調、輕音)。Whisper選擇GELU而非ReLU,其核心之處在於精準地把捉語音裏的細微細節。

  • 關鍵區別
  • ReLU是硬開關:輸入若小於等於0,則便直接將其置為0,如此這般容易丟失像那輕聲音節這般較弱的特徵;
  • GELU是漸變開關,基於高斯誤差函數來動態地保留特徵,能夠以一種温和的方式保留那些較弱的信號。
  • 架構意義:讓模型不遺漏細節、不誇大噪聲,是複雜場景識別準確率領先的關鍵

核心代碼:預處理模塊整合(含卷積+GELU)

import torch
import torch.nn as nn

class WhisperPreprocessStem(nn.Module):
	"""Whisper Transformer前的核心預處理模塊"""
	def __init__(self, out_dim: int = 512):
		super().__init__()
		# 兩次卷積+GELU特徵提取
		self.conv_block = nn.Sequential(
			nn.Conv2d(1, 16, 3, padding=1), # 1→16通道(輸入為單通道梅爾譜)
			nn.GELU(),
			nn.Conv2d(16, 32, 3, padding=1, stride=(2,1)), # 16→32通道,時間降維1/2
			nn.GELU()
		)
		# 映射到Transformer輸入維度
		self.fc = nn.Linear(32 * 80 * 500, out_dim) # 假設輸入時間步1000,降維後500
	
	def forward(self, mel_spec: torch.Tensor):
		# 梅爾譜形狀:(batch, 時間步, 80) → (batch, 1, 時間步, 80)(適配卷積)
		mel_spec = mel_spec.unsqueeze(1)
		conv_out = self.conv_block(mel_spec).flatten(1) # 展平卷積結果
		return self.fc(conv_out).permute(1, 0, 2) # 轉成Transformer需要的(seq_len, batch, d_model)

fake_mel = torch.randn(1, 1000, 80) # 1個batch、1000時間步、80通道
preprocessor = WhisperPreprocessStem()
print(f"預處理後輸出形狀: {preprocessor(fake_mel).shape}")

架構精髓

多任務聯合訓練的底層邏輯,完成“三重預處理”後精煉的特徵,會輸入Transformer編碼器-解碼器架構。Whisper以單一模型來承載語音識別、翻譯以及語言檢測這三大任務,其核心在於多任務的聯合訓練以及統一的文本生成接口。

核心代碼:Transformer位置編碼(時序建模關鍵)

import torch
import math

class PositionalEncoding(nn.Module):
	def __init__(self, d_model: int, max_len: int = 5000):
		super().__init__()
		# 預計算位置編碼(不參與梯度更新)
		pe = torch.zeros(max_len, d_model)
		position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
		div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model))
		pe[:, 0::2] = torch.sin(position * div_term)
		pe[:, 1::2] = torch.cos(position * div_term)
		self.register_buffer('pe', pe)
	
	def forward(self, x: torch.Tensor):
		return x + self.pe[:x.size(0)] # 按輸入序列長度截取編碼

未來演進

Whisper未來可能的演進方向:

  • 低資源語言突破:從英語優先到全球覆蓋
  • 接入Mozilla Common Voice等多語言數據集,豐富方言樣本
  • 用高資源語言預訓練知識,通過語言嵌入適配低資源語言
  • 多模態融合:不止聽聲辨字,更能理解語境
  • 結合視頻唇動信號優化嘈雜環境識別,
  • 聯動GPT-4o實現語音理解生成閉環,支持複雜指令
  • 邊緣部署深化:從雲端依賴到設備原生
  • 微型模型(如ggml-base-tdrz內存<100MB,支持手機、嵌入式設備
  • 實時流處理優化,端到端延遲降至200ms以內

實戰

有多種安裝方式,最簡單的就是:pip install -U openai-whisper

源碼安裝:

git clone https://github.com/openai/whisper.git
python -m venv whisper-env
source whisper-env/bin/activate

可選:

pip install torch torchaudio librosa

簡單使用:

import whisper

# 加載模型,以Windows為例,下載路徑C:\Users\johnny\.cache\whisper
model = whisper.load_model("base")
# load audio and pad/trim it to fit 30 seconds
audio = whisper.load_audio("ok.wav")
audio = whisper.pad_or_trim(audio)
# make log-Mel spectrogram and move to the same device as the model
mel = whisper.log_mel_spectrogram(audio).to(model.device)
# detect the spoken language
_, probs = model.detect_language(mel)
print(f"Detected language: {max(probs, key=probs.get)}")

本地模型:

OpenAI Whisper:技術、實戰、生態_#whisper_02


運行效果:

OpenAI Whisper:技術、實戰、生態_#whisper_03


使用CPU:

model = whisper.load_model("tiny")
result = model.transcribe("ok.wav")
print(result["text"])

OpenAI Whisper:技術、實戰、生態_卷積_04


使用GPU加速:

import torch
torch.cuda.is_available()
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
model = whisper.load_model("tiny", device=DEVICE)
result = model.transcribe("ok.wav")
print(result["text"])

轉錄實例:

import whisper
import time

# 轉錄
def basic_transcribe(audio_path: str, model_size: str = "base"):
	model = whisper.load_model(model_size)
	start = time.time()
	# 核心轉錄(內部自動執行梅爾譜+卷積+GELU預處理)
	result = model.transcribe(
		audio_path, language="zh", task="transcribe", word_timestamps=True
	)
	return {
		"text": result["text"],
		"word_level": [{"word": w["word"], "time": (w["start"], w["end"])} for w in result["segments"][0]["words"]],
		"耗時": f"{time.time()-start:.2f}秒"
	}

print(basic_transcribe("meeting.wav", "large-v3-turbo"))

結合PyAnnote實現會議轉錄:

from pyannote.audio import Pipeline
import whisper

def meeting_transcribe(audio_path: str, hf_token: str):
	# 1. 説話人分離
	diarize = Pipeline.from_pretrained("pyannote/speaker-diarization-3.1", use_auth_token=hf_token)
	speaker_segments = diarize(audio_path)
	# 2. Whisper轉錄全量音頻
	model = whisper.load_model("medium")
	result = model.transcribe(audio_path, word_timestamps=True)
	# 3. 文本與説話人對齊
	meeting_notes = []
	for text_seg in result["segments"]:
		# 匹配該時間段的説話人
		speaker = next((spk for turn, _, spk in speaker_segments.itertracks() 
	                  if turn.start <= text_seg["start"] <= turn.end), "未知")
		meeting_notes.append({"speaker": speaker, "text": text_seg["text"]})
	return meeting_notes

print(meeting_transcribe("team_meeting.wav", "xxx"))

量化模型低延遲推理

import torch
from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor

def industrial_whisper_infer(audio_tensor: torch.Tensor):
	# 加載8-bit量化模型,顯存佔用降低45%
	processor = AutoProcessor.from_pretrained("openai/whisper-large-v3-turbo")
	model = AutoModelForSpeechSeq2Seq.from_pretrained(
		"openai/whisper-large-v3-turbo", load_in_8bit=True, device_map="auto", torch_dtype=torch.float16
	)
	# 低延遲推理參數
	inputs = processor(audio_tensor, sampling_rate=16000, return_tensors="pt").to("cuda")
	with torch.no_grad():
		gen_ids = model.generate(**inputs, max_new_tokens=256, do_sample=False, temperature=0.0)
	return processor.batch_decode(gen_ids, skip_special_tokens=True)[0]

實踐建議

  • 選型策略:邊緣場景選tinysmall量化,桌面端選medium,工業級選largev3-turbo+GPU
  • 性能優化:優先8-bit量化+混合精度計算,複雜場景可裁剪高頻噪聲進一步降維
  • 場景拓展:基礎轉錄用官方API,會議場景加PyAnnote,工業場景固化預處理流程

集成HuggingFace:

import torch
from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor, pipeline
device = "cuda:0" if torch.cuda.is_available() else "cpu"
torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
model_id = "openai/whisper-large-v2"
model = AutoModelForSpeechSeq2Seq.from_pretrained(
	model_id, torch_dtype=torch_dtype, low_cpu_mem_usage=True, use_safetensors=True
)
model.to(device)
processor = AutoProcessor.from_pretrained(model_id)
pipe = pipeline(
	"automatic-speech-recognition",
	model=model,
	tokenizer=processor.tokenizer,
	feature_extractor=processor.feature_extractor,
	torch_dtype=torch_dtype,
	device=device,
)
generate_kwargs = {
    "max_new_tokens": 448
}

命令行使用:

# 使用medium模型識別音頻,生成json、srt、tsv、txt、vtt文本文件
whisper --model medium dataset/9s.wav

解讀:

  • srt:用於存儲音視頻文件的字幕信息
  • tsv:存儲表格數據,類似於CSV
  • vtt:用於存儲視頻文件的字幕信息

使用付費API:

import openai
CHATGPT_KEY = "OpenAI API Key"
openai.api_key = CHATGPT_KEY
audio_file = open("9s.wav", "rb")
transcription = openai.audio.transcriptions.create(
  model="whisper-1", 
  file=audio_file, 
  response_format="text"
)
print(transcription)