使用 Whisper 和 Deepgram 进行语音转文本
实时转写与批量转写、语言检测和标点处理。
使用 Whisper 和 Deepgram 进行语音转文本 是 CoddyKit 上的免费 AI Agents 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
语音代理中的语音转文本
语音代理必须先将语音音频转换为文本,LLM 才能进行处理。此步骤称为语音转文本(STT)或自动语音识别(ASR)。
目前有两种主流选择:OpenAI Whisper(基于文件、批量处理)和Deepgram(流式、实时,并支持说话人分离和词级时间戳)。
OpenAI Whisper:基础转写
通过 OpenAI 接口使用 Whisper 可以转写音频文件。支持的格式包括:mp3、mp4、wav、webm、m4a 和 flac。文件大小上限为 25MB。
import openai
import os
client = openai.OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
def transcribe_file(audio_path, language=None):
with open(audio_path, 'rb') as audio_file:
params = {
'model': 'whisper-1',
'file': audio_file,
'response_format': 'json' # or 'text', 'srt', 'vtt', 'verbose_json'
}
if language:
params['language'] = language # e.g., 'en', 'fr', 'de'
transcript = client.audio.transcriptions.create(**params)
return transcript.text
# Basic usage
text = transcribe_file('meeting_recording.mp3')
print('Transcribed:', text[:200])带词级时间戳的 Whisper
使用 response_format='verbose_json' 可获取每个单词和片段的时间戳。这对于查找录音中的特定时刻、实现卡拉 OK 式高亮,以及将转写文本与音频播放对齐都很有用。
import openai
import os
client = openai.OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
def transcribe_with_timestamps(audio_path):
with open(audio_path, 'rb') as f:
result = client.audio.transcriptions.create(
model='whisper-1',
file=f,
response_format='verbose_json',
timestamp_granularities=['word', 'segment'] # get both word and segment times
)
segments = []
for seg in result.segments:
segments.append({
'start': seg.start,
'end': seg.end,
'text': seg.text
})
words = []
if hasattr(result, 'words'):
for word in result.words:
words.append({'word': word.word, 'start': word.start, 'end': word.end})
return {'text': result.text, 'segments': segments, 'words': words}Deepgram SDK:异步流式传输
Deepgram 针对实时流式转写进行了优化。音频会在录制过程中以分块形式发送;说话人尚未说完一句话时,就可以先返回部分转写结果。
使用 pip install deepgram-sdk 安装。
import asyncio
import os
from deepgram import DeepgramClient, PrerecordedOptions
client = DeepgramClient(os.getenv('DEEPGRAM_API_KEY'))
async def transcribe_with_deepgram(audio_path):
with open(audio_path, 'rb') as f:
audio_data = f.read()
options = PrerecordedOptions(
model='nova-2', # Deepgram's best accuracy model
language='en',
smart_format=True, # auto-add punctuation and formatting
utterances=True, # segment by speaker turns
punctuate=True,
diarize=True # speaker identification
)
response = await client.listen.asyncrest.v('1').transcribe_file(
{'buffer': audio_data},
options
)
return response.results.channels[0].alternatives[0].transcript说话人分离
说话人分离用于识别每个时刻是谁在说话,并将片段标记为说话人 0、说话人 1等。这对于会议转写和多人对话至关重要。
async def transcribe_with_diarization(audio_path):
from deepgram import DeepgramClient, PrerecordedOptions
import os
dg_client = DeepgramClient(os.getenv('DEEPGRAM_API_KEY'))
options = PrerecordedOptions(
model='nova-2',
diarize=True,
utterances=True,
smart_format=True
)
with open(audio_path, 'rb') as f:
audio_data = f.read()
response = await dg_client.listen.asyncrest.v('1').transcribe_file(
{'buffer': audio_data}, options
)
utterances = []
for utt in response.results.utterances:
utterances.append({
'speaker': f'Speaker {utt.speaker}',
'start': round(utt.start, 2),
'end': round(utt.end, 2),
'text': utt.transcript
})
return utterances
# Output:
# [{'speaker': 'Speaker 0', 'start': 0.0, 'end': 3.2, 'text': 'Hello everyone.'},
# {'speaker': 'Speaker 1', 'start': 3.5, 'end': 6.1, 'text': 'Good morning!'}]语言检测
当不知道用户使用哪种语言时,Whisper 和 Deepgram 都可以自动检测所说的语言。Whisper 会根据音频开头的 30 秒来检测语言。
import openai
import os
client = openai.OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
def detect_language(audio_path):
with open(audio_path, 'rb') as f:
# Use translations endpoint to get verbose JSON with language detection
result = client.audio.transcriptions.create(
model='whisper-1',
file=f,
response_format='verbose_json'
)
return {
'detected_language': result.language,
'text': result.text
}
result = detect_language('user_audio.wav')
print(f"Language: {result['detected_language']}")
print(f"Text: {result['text'][:100]}")
# Deepgram: set language='auto' in options
from deepgram import PrerecordedOptions
options = PrerecordedOptions(model='nova-2', language='auto', detect_language=True)长音频文件分块
由于 Whisper 的大小限制为 25MB,较长的录音(例如 1 小时的会议)需要进行分块。使用 pydub 根据静音切分音频,然后分别转写每个分块并将结果拼接起来。
使用 pip install pydub 安装。需要 ffmpeg。
from pydub import AudioSegment
from pydub.silence import split_on_silence
import io
def transcribe_long_audio(audio_path, chunk_length_ms=60000):
audio = AudioSegment.from_file(audio_path)
# Split on silence
chunks = split_on_silence(
audio,
min_silence_len=1000, # 1 second of silence
silence_thresh=-40, # dBFS
keep_silence=500 # keep 500ms at each end
)
# If no silence splitting worked, use fixed-length chunks
if len(chunks) <= 1:
chunks = [
audio[i:i + chunk_length_ms]
for i in range(0, len(audio), chunk_length_ms)
]
full_transcript = []
for i, chunk in enumerate(chunks):
print(f'Transcribing chunk {i+1}/{len(chunks)}')
buf = io.BytesIO()
chunk.export(buf, format='mp3')
buf.seek(0)
buf.name = f'chunk_{i}.mp3'
result = client.audio.transcriptions.create(model='whisper-1', file=buf)
full_transcript.append(result.text)
return ' '.join(full_transcript)Deepgram 实时流式传输
对于实时语音对话,请使用 Deepgram 的 WebSocket 实时流式传输接口。音频分块会在录制过程中发送;中间转写结果和最终转写结果会在数毫秒内到达。
import asyncio
import os
from deepgram import DeepgramClient, LiveTranscriptionEvents, LiveOptions
async def live_transcribe(on_transcript_callback):
dg_client = DeepgramClient(os.getenv('DEEPGRAM_API_KEY'))
connection = dg_client.listen.asynclive.v('1')
async def on_message(self, result, **kwargs):
sentence = result.channel.alternatives[0].transcript
is_final = result.is_final
if sentence:
await on_transcript_callback(sentence, is_final)
connection.on(LiveTranscriptionEvents.Transcript, on_message)
options = LiveOptions(
model='nova-2',
language='en',
smart_format=True,
interim_results=True, # get partial results before sentence ends
endpointing=500 # ms of silence before finalizing
)
await connection.start(options)
return connection # caller sends audio chunks via connection.send(audio_chunk)错误处理与重试
音频转写接口可能因网络问题、不支持的格式或速率限制而失败。请使用指数退避实现重试,并在发送前验证音频。
import time
import os
MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024 # 25MB
SUPPORTED_FORMATS = ('.mp3', '.mp4', '.wav', '.webm', '.m4a', '.flac', '.ogg')
def validate_audio_file(audio_path):
if not os.path.exists(audio_path):
raise FileNotFoundError(f'Audio file not found: {audio_path}')
size = os.path.getsize(audio_path)
if size > MAX_FILE_SIZE_BYTES:
raise ValueError(f'File too large: {size / 1024 / 1024:.1f}MB (max 25MB)')
ext = os.path.splitext(audio_path)[1].lower()
if ext not in SUPPORTED_FORMATS:
raise ValueError(f'Unsupported format: {ext}. Supported: {SUPPORTED_FORMATS}')
def transcribe_with_retry(audio_path, max_retries=3):
validate_audio_file(audio_path)
for attempt in range(max_retries):
try:
return transcribe_file(audio_path)
except Exception as e:
if attempt < max_retries - 1:
wait = 2 ** attempt
print(f'Retry {attempt + 1} after error: {e}. Waiting {wait}s')
time.sleep(wait)
else:
raise在 Whisper 与 Deepgram 之间进行选择
这两种工具分别适用于不同场景。请使用下面的决策矩阵,为您的语音代理选择合适的工具。
COMPARISON = '''
Whisper (OpenAI API):
- Best for: batch transcription, podcast processing, meeting notes
- Latency: file upload latency + ~1-5 seconds processing
- Strengths: excellent multilingual, high accuracy, cheap
- Word timestamps: yes (verbose_json)
- Diarization: NO (must use separate tool)
- Use when: accuracy > speed, offline processing
DeeGram:
- Best for: real-time voice agents, call center transcription
- Latency: <300ms for streaming, ~1s for file upload
- Strengths: streaming, diarization, custom vocabulary
- Word timestamps: yes, with confidence scores
- Diarization: YES (built-in, up to 10 speakers)
- Use when: speed > accuracy, real-time required
Rule of thumb:
Agent voice conversation -> Deepgram live streaming
Batch audio files -> Whisper API
Meeting transcripts with speakers -> Deepgram with diarize=True
'''
print(COMPARISON)音频格式转换
Whisper 和 Deepgram 支持常见的音频格式,但用户音频可能以不常见的格式到达(例如浏览器生成的 ogg、opus、webm,以及来自 iOS 的 m4a)。在发送到接口之前,请将其转换为标准 WAV 或 MP3。
from pydub import AudioSegment
import os
SUPPORTED_FORMATS = {'.mp3', '.wav', '.flac', '.m4a', '.ogg', '.webm', '.opus'}
def convert_to_wav(input_path, output_path=None):
ext = os.path.splitext(input_path)[1].lower()
if ext not in SUPPORTED_FORMATS:
raise ValueError(f'Unsupported audio format: {ext}')
if output_path is None:
output_path = input_path.rsplit('.', 1)[0] + '.wav'
# pydub handles format detection automatically
audio = AudioSegment.from_file(input_path)
# Normalize to 16kHz mono (optimal for Whisper)
audio = audio.set_frame_rate(16000).set_channels(1)
audio.export(output_path, format='wav')
print(f'Converted {input_path} -> {output_path} ({len(audio) / 1000:.1f}s)')
return output_path
def ensure_compatible_audio(audio_path):
ext = os.path.splitext(audio_path)[1].lower()
if ext in {'.mp3', '.wav', '.m4a', '.flac'}:
return audio_path # already compatible
return convert_to_wav(audio_path)知识检查
在语音转文本的语境中,说话人分离是什么?
回顾:使用 Whisper 和 Deepgram 进行语音转文本
Whisper(OpenAI 接口)适合批量转写:准确率高,支持多种语言,并可通过 verbose_json 提供词级时间戳。当延迟不是关键因素时,可以使用它进行基于文件的处理。
Deepgram专为实时流式传输而设计:通过 WebSocket 实时转写,提供中间结果、内置说话人分离,并将延迟控制在 300 毫秒以内。对于交互式语音代理,请使用 Deepgram。这两种工具都支持语言检测,在生产环境中都需要重试逻辑和文件验证。
常见问题解答
「使用 Whisper 和 Deepgram 进行语音转文本」课时是免费的吗?
是的 — 「使用 Whisper 和 Deepgram 进行语音转文本」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「使用 Whisper 和 Deepgram 进行语音转文本」这节课中我会学到什么?
实时转写与批量转写、语言检测和标点处理。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「使用 Whisper 和 Deepgram 进行语音转文本」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 Whisper 和 Deepgram 进行语音转文本
- 代理回复中的文本转语音
- 构建语音对话循环
- 优化语音代理的延迟