Python语音转文本实战:从本地Whisper到云端API的完整指南

📅 2026/8/11 3:23:09
Python语音转文本实战:从本地Whisper到云端API的完整指南
1. 项目概述为什么用Python做语音转文本如果你手头有一段会议录音、一段播客音频或者想给自己的视频自动生成字幕手动敲字绝对是场噩梦。这时候语音转文本ASR技术就是你的救星。而Python凭借其丰富的库和社区生态成了实现这个功能最顺手、门槛也相对较低的工具。这不仅仅是调用一个API那么简单从本地轻量级处理到对接高精度商用服务Python都能给你搭好桥梁。今天我就结合自己踩过的坑和实际项目经验来拆解用Python实现语音转文本的完整路径从核心原理、工具选型到实战代码和避坑指南让你不仅能跑通Demo更能理解背后的门道做出适合自己需求的选择。2. 核心方案选型从本地库到云端API面对语音转文本的需求你面前通常有三条路使用纯本地的开源库、调用大厂的云端API或者采用混合方案。没有绝对的好坏只有是否适合你的场景。2.1 本地开源库方案这类方案完全在本地运行不依赖网络数据隐私性好适合处理敏感音频或网络不便的环境。但通常对硬件尤其是CPU有一定要求且识别精度和语言模型丰富度可能不及顶尖的云端服务。1. Vosk离线识别的瑞士军刀Vosk是我在离线项目中用得最多的库。它的核心优势是模型多支持几十种语言包括中文、体积相对小巧并且提供了多种规模的模型从几十MB的小模型到几个GB的大模型方便在精度和资源消耗间权衡。它的API设计也很Pythonic几行代码就能跑起来。不过Vosk的模型是“静态”的你无法用自己的数据去微调它对于非常专业的领域词汇比如某些医疗或工程术语可能会识别不准。2. WhisperOpenAI平衡精度与易用性的新星虽然来自OpenAI但Whisper是一个开源项目你完全可以在本地部署。它大概是近年来对开发者最友好的ASR工具了。使用简单默认模型base或small在英语识别上就有不错的效果而且自带多语言识别和翻译能力。缺点是模型较大最小的tiny模型也有几百MB推理速度较慢尤其是在没有GPU的机器上。但对于不追求实时性、又希望有较好精度的个人项目或研究Whisper是首选。3. SpeechRecognition封装多引擎的“胶水”库这个库本身不提供识别引擎而是一个统一的接口背后可以对接Google Web Speech API、CMU Sphinx、Wit.ai等多个服务。其中对接Sphinx引擎时可以离线使用。它的价值在于其接口的统一性方便你快速切换不同的后端进行对比。但正因如此其能力完全取决于后端引擎。离线模式下使用的Sphinx引擎其识别精度尤其是中文现在来看已经比较落后了更适合作为教学或简单场景的入门工具。注意选择本地库时务必考虑你的部署环境。在树莓派或低配云服务器上一个几GB的Whisper模型可能会让你寸步难行。Vosk的轻量级模型往往是更务实的选择。2.2 云端API服务方案当你需要生产级的高精度、高稳定性并且音频数据不涉密时云端API是更专业的选择。它们通常按处理时长收费但提供了99%以上的准确率、持续的模型更新以及额外的功能如说话人分离、情绪分析等。1. 阿里云/腾讯云语音识别国内项目首选。它们对中文的优化非常好特别是带有各种口音的普通话和常见方言。集成过程就是典型的云服务模式注册、开通服务、获取API Key和Secret然后按照SDK文档调用。优势是延迟低因为服务器在国内、文档和客服支持中文、符合国内数据合规要求。你需要仔细阅读它们的计价方式通常有免费额度超出后按分钟计费。2. Google Cloud Speech-to-Text / Microsoft Azure Speech Services如果你是做全球化应用或者需要支持的语言特别多这两家是国际市场的标杆。Google在长音频和嘈杂环境下的识别很强大Azure则在说话人分离和实时转录方面有独特优势。它们的Python SDK都非常成熟但调用延迟会受网络影响且需要处理跨境数据合规的问题。3. 其他商用API如科大讯飞像科大讯飞这样的专业语音公司也提供非常出色的ASR API。它们在特定垂直领域如教育、司法的定制化能力可能更强。选择时除了精度和价格还要考虑SDK的易用性、服务的SLA服务等级协议以及是否支持你需要的一些高级功能。2.3 混合与自定义方案对于有特殊需求的场景你可能需要混合方案。例如预处理云端API先用pydub这样的库对音频进行降噪、分割再将清晰的片段发送给API以提升识别率并控制成本。本地初筛云端精校对实时性要求高的场景可以先在本地用Vosk进行快速但粗略的识别同时将音频发送到云端进行高精度识别云端结果返回后再做替换或融合。微调定制模型如果你有大量领域特定的标注数据如医疗问诊录音可以考虑使用像NVIDIA NeMo这样的工具包在开源基础模型如Whisper上进行微调得到一个专属于你领域的离线模型。这条路技术门槛和资源投入最高但能形成核心壁垒。3. 实战演练三大经典场景代码实现光说不练假把式。下面我们针对三个最典型的场景给出可直接运行的代码示例和详细解说。3.1 场景一使用Whisper进行本地高精度转录假设你有一个长达一小时的会议录音meeting.mp3你想把它转成文字稿。Whisper是最简单的选择。首先安装Whisper它依赖Python 3.8和ffmpegpip install openai-whisper # 确保系统安装了ffmpeg # Ubuntu/Debian: sudo apt update sudo apt install ffmpeg # macOS: brew install ffmpeg # Windows: 从官网下载exe并添加至环境变量PATH核心转录代码import whisper import warnings warnings.filterwarnings(ignore) # 可选忽略一些提示信息 def transcribe_with_whisper(audio_path, model_sizebase): 使用Whisper转录音频文件 :param audio_path: 音频文件路径 :param model_size: 模型大小可选 tiny, base, small, medium, large print(f正在加载 {model_size} 模型...) # 加载模型首次运行会自动下载 model whisper.load_model(model_size) print(开始转录...) # transcribe方法会进行VAD语音活动检测、解码等全套流程 result model.transcribe(audio_path) # 输出完整文本 print(转录完成文本内容) print(result[text]) # 如果你需要带时间戳的段落用于字幕可以访问segments print(\n【带时间戳的段落】) for segment in result[segments]: start segment[start] end segment[end] text segment[text] print(f[{start:.2f}s - {end:.2f}s]: {text}) return result # 使用示例 if __name__ __main__: # 使用base模型在精度和速度间取得平衡 audio_file meeting.mp3 transcribe_with_whisper(audio_file, model_sizebase)参数选择与调优心得model_size选择tiny和base速度最快适合英语或质量高的音频。small和medium是精度和速度的较好平衡。large最准但也最慢内存消耗大非必要不使用。transcribe方法可选参数language指定语言如zh能提升识别精度和速度。task可选transcribe转录或translate翻译成英语。fp16是否使用半精度浮点数默认True在GPU上能提速但某些CPU上可能不稳定可设为False。实操坑点Whisper对音频长度没有硬性限制但过长的音频如2小时以上可能会一次性占用大量内存。对于超长音频更稳妥的做法是先用pydub分割成30分钟左右的片段分别识别后再合并文本。3.2 场景二使用Vosk进行实时离线语音识别假设你要开发一个离线的语音指令工具需要实时识别麦克风的输入。Vosk的流式识别能力非常适合。首先安装Vosk并下载模型pip install vosk # 前往Vosk官网模型仓库下载适合的中文模型例如vosk-model-small-cn-0.22 # 解压后得到一个文件夹记住路径如 ./models/vosk-model-small-cn-0.22核心实时识别代码import json import queue import sys import sounddevice as sd # 用于录音 from vosk import Model, KaldiRecognizer class RealtimeASR: def __init__(self, model_path, sample_rate16000): 初始化实时ASR引擎 :param model_path: 下载的Vosk模型目录路径 :param sample_rate: 音频采样率必须与模型匹配通常为16000 print(f加载模型从: {model_path}) self.model Model(model_path) self.recognizer KaldiRecognizer(self.model, sample_rate) self.sample_rate sample_rate self.audio_queue queue.Queue() def audio_callback(self, indata, frames, time, status): 声音输入回调函数将音频数据放入队列 if status: print(f音频输入错误: {status}, filesys.stderr) self.audio_queue.put(bytes(indata)) def start_listening(self): 开始实时监听麦克风并识别 print(开始实时语音识别请说话... (按 CtrlC 停止)) try: # 打开音频输入流 with sd.RawInputStream(samplerateself.sample_rate, blocksize8000, # 每次处理的音频块大小 dtypeint16, channels1, callbackself.audio_callback): while True: # 从队列中获取音频数据 data self.audio_queue.get() # 喂给识别器 if self.recognizer.AcceptWaveform(data): # AcceptWaveform返回True表示识别出一句完整的话 result json.loads(self.recognizer.Result()) text result.get(text, ) if text: print(f\n识别结果: {text}) else: # 部分结果可以用于实时反馈如打字机效果 partial_result json.loads(self.recognizer.PartialResult()) partial_text partial_result.get(partial, ) if partial_text: # 在同一行刷新显示模拟实时效果 sys.stdout.write(f\r部分结果: {partial_text:50}) sys.stdout.flush() except KeyboardInterrupt: print(\n\n监听已停止。) finally: # 获取最终结果 final_result json.loads(self.recognizer.FinalResult()) print(f最终识别文本: {final_result.get(text, )}) # 使用示例 if __name__ __main__: # 替换为你的模型实际路径 MODEL_PATH ./models/vosk-model-small-cn-0.22 asr_engine RealtimeASR(MODEL_PATH) asr_engine.start_listening()关键细节与避坑指南采样率必须匹配Vosk模型通常要求16000Hz的单声道PCM音频。如果你的麦克风默认是44100Hz需要在sounddevice输入流中指定samplerate16000它会自动重采样。blocksize的选择这个值影响延迟和CPU占用。太小如1024会导致频繁回调增加开销太大如16000会导致识别延迟明显。8000或4000是常用值代表每次处理0.5秒或0.25秒的音频。AcceptWaveform与PartialResultVosil的核心是增量解码。AcceptWaveform返回True时表示检测到一句话的结束通常是静音段这时Result()里是最终文本。而PartialResult提供的是中间结果适合做实时字幕反馈。性能瓶颈在树莓派等设备上运行模型大小和blocksize是关键。使用vosk-model-small-*系列模型并适当增大blocksize如16000可以减少计算压力。3.3 场景三调用阿里云语音识别API当你的音频可以上传到云端且需要最好的中文识别效果时国内云服务是首选。这里以阿里云为例。准备工作注册阿里云账号开通“智能语音交互”服务。在控制台创建AccessKey ID和AccessKey Secret。在“项目列表”中创建一个项目并记下appkey。安装SDKpip install aliyun-python-sdk-core # 核心库 pip install aliyun-python-sdk-nls-cloud-meta # 语音识别元数据 # 注意阿里云SDK包名可能更新请以官方文档为准核心代码以文件识别为例from aliyunsdkcore.client import AcsClient from aliyunsdknls.cloudmeta.request.v20180518 import CreateTokenRequest from aliyunsdknls.cloudmeta.request.v20180518 import FileTransRequest import json import time class AliyunASR: def __init__(self, access_key_id, access_key_secret, appkey): 初始化阿里云ASR客户端 self.access_key_id access_key_id self.access_key_secret access_key_secret self.appkey appkey self.client AcsClient(access_key_id, access_key_secret, cn-shanghai) self.token None self.token_expire_time 0 def _get_token(self): 获取或刷新访问令牌令牌有效期为24小时 current_time int(time.time()) if self.token and current_time self.token_expire_time - 300: # 提前5分钟刷新 return self.token request CreateTokenRequest.CreateTokenRequest() request.set_accept_format(json) response self.client.do_action_with_exception(request) result json.loads(response.decode(utf-8)) if result.get(Token) and result.get(ExpireTime): self.token result[Token][Id] self.token_expire_time result[Token][ExpireTime] print(fToken获取成功过期时间戳: {self.token_expire_time}) else: raise Exception(f获取Token失败: {result}) return self.token def transcribe_file(self, audio_file_path, formatwav, sample_rate16000): 提交音频文件进行识别异步 :param audio_file_path: 本地音频文件路径 :param format: 音频格式支持 wav, mp3, aac, amr 等 :param sample_rate: 采样率如 8000, 16000 :return: 识别任务ID token self._get_token() request FileTransRequest.FileTransRequest() request.set_Token(token) request.set_AppKey(self.appkey) # 设置音频文件参数 file_link ffile://{audio_file_path} # 本地文件前缀 request.set_FileLink(file_link) request.set_Format(format) request.set_SampleRate(sample_rate) # 其他可选参数 # request.set_EnableWords(True) # 是否开启词级时间戳 # request.set_EnableInverseTextNormalization(True) # 是否开启ITN将“一二三”转为“123” response self.client.do_action_with_exception(request) result json.loads(response.decode(utf-8)) if result.get(TaskId): task_id result[TaskId] print(f文件识别任务已提交任务ID: {task_id}) return task_id else: raise Exception(f提交识别任务失败: {result}) def get_transcription_result(self, task_id, max_retries30, interval2): 轮询获取识别结果 :param task_id: 任务ID :param max_retries: 最大轮询次数 :param interval: 轮询间隔秒 :return: 识别文本 request FileTransRequest.GetFileTransResultRequest() request.set_TaskId(task_id) for i in range(max_retries): print(f轮询结果中... ({i1}/{max_retries})) time.sleep(interval) response self.client.do_action_with_exception(request) result json.loads(response.decode(utf-8)) status result.get(Status) if status RUNNING: continue elif status SUCCESS: sentences result.get(Result, {}).get(Sentences, []) full_text .join([s.get(Text, ) for s in sentences]) print(识别成功) return full_text elif status FAILED: error_msg result.get(Result, {}).get(ErrorMessage, 未知错误) raise Exception(f识别任务失败: {error_msg}) else: # 可能是QUEUING等状态 continue raise Exception(f轮询超时未获取到结果。最后状态: {result.get(Status)}) # 使用示例 if __name__ __main__: # 替换为你的实际信息 ACCESS_KEY_ID your-access-key-id ACCESS_KEY_SECRET your-access-key-secret APP_KEY your-appkey AUDIO_FILE test.wav asr_client AliyunASR(ACCESS_KEY_ID, ACCESS_KEY_SECRET, APP_KEY) try: # 1. 提交识别任务 task_id asr_client.transcribe_file(AUDIO_FILE, formatwav, sample_rate16000) # 2. 轮询获取结果对于长音频这可能需要几十秒 text asr_client.get_transcription_result(task_id, max_retries30, interval3) print(\n最终识别文本) print(text) except Exception as e: print(f处理过程中发生错误: {e})云端API调用核心经验音频预处理是关键云端API虽然强大但“垃圾进垃圾出”。在上传前最好用pydub进行预处理统一转换为单声道、16kHz采样率、去除首尾静音。这能显著提升识别准确率和降低处理时间。理解异步操作文件识别通常是异步的提交任务后立即返回一个TaskId你需要用这个ID去轮询结果。设计程序时要考虑网络超时和重试机制。费用与配额管理务必在控制台设置用量告警。对于测试可以使用EnableWordTime词级时间戳等高级功能但要清楚这些功能可能会产生额外费用。错误处理要周全网络超时、认证失败、音频格式不支持、服务端内部错误……必须用try...except包裹核心调用并给用户明确的错误提示。4. 音频预处理与后处理提升精度的关键步骤很多新手拿到识别结果后觉得不准第一反应是换模型或API但其实问题可能出在音频本身或文本后处理上。4.1 预处理让模型“听清”一个干净的音频输入是高质量识别的前提。使用pydub可以轻松完成常见预处理。from pydub import AudioSegment from pydub.effects import normalize, compress_dynamic_range import os def preprocess_audio(input_path, output_path, target_formatwav): 音频预处理流水线 # 1. 加载音频 print(f加载音频: {input_path}) audio AudioSegment.from_file(input_path) # 2. 转换为单声道大多数ASR模型要求 if audio.channels 1: print(f 转换为单声道 (原 {audio.channels} 声道)) audio audio.set_channels(1) # 3. 重采样至16kHz标准采样率 if audio.frame_rate ! 16000: print(f 重采样至16kHz (原 {audio.frame_rate}Hz)) audio audio.set_frame_rate(16000) # 4. 标准化音量防止声音过小或过大 print( 音量标准化) audio normalize(audio) # 5. 可选压缩动态范围让小声部分变大大声部分变小 # 适用于音量起伏很大的录音如采访 # audio compress_dynamic_range(audio, threshold-20.0, ratio4.0) # 6. 去除首尾静音非常重要 print( 去除首尾静音) # 设置静音阈值单位dBFS和最小静音长度毫秒 silence_thresh -40 # 低于-40dBFS被认为是静音 min_silence_len 500 # 持续500ms以上的静音段 # 使用detect_silence找到静音段然后切片去除 non_silent_parts pydub.silence.detect_nonsilent(audio, min_silence_lenmin_silence_len, silence_threshsilence_thresh) if non_silent_parts: start_ms non_silent_parts[0][0] end_ms non_silent_parts[-1][1] audio audio[start_ms:end_ms] print(f 去除静音后音频时长从 {len(audio)/1000:.1f}s 变为 {len(audio)/1000:.1f}s) # 7. 导出为WAV格式PCM编码兼容性最好 print(f导出处理后的音频至: {output_path}) audio.export(output_path, formattarget_format, parameters[-ac, 1, -ar, 16000]) return output_path # 使用示例 processed_file preprocess_audio(raw_recording.m4a, processed_audio.wav)预处理心得静音切除是性价比最高的操作模型把开头漫长的静音当成有效内容去“理解”会浪费算力且可能引入奇怪错误。pydub.silence.detect_nonsilent参数需要根据你的音频调整。嘈杂环境下的“静音”阈值silence_thresh要设得高一些如-30甚至-25。格式转换虽然很多API支持mp3、aac但最保险的格式永远是单声道、16kHz、PCM编码的WAV。这是所有语音识别引擎的“通用语言”。批量处理如果有很多文件可以用glob获取文件列表然后循环调用预处理函数。注意控制并发避免内存耗尽。4.2 后处理让文本“读顺”识别出来的原始文本通常存在一些通病没有标点、中英文混杂、数字读法不符合习惯等。简单的规则后处理能极大提升可读性。import re def postprocess_text(raw_text): 对ASR原始结果进行后处理 if not raw_text: return text raw_text.strip() # 1. 简单句子分割根据常见句末词 # 这是一个非常基础的规则对于复杂文本效果有限可以考虑用punct库或训练一个简单的标点恢复模型 sentence_enders r([。\.\?!;]) text re.sub(sentence_enders, r\1\n, text) # 2. 修复常见的中英文混写空格问题模型有时会把“Python代码”识别成“Python 代码” # 移除中文和英文/数字之间多余的空格 text re.sub(r([\u4e00-\u9fff])\s([a-zA-Z0-9]), r\1\2, text) text re.sub(r([a-zA-Z0-9])\s([\u4e00-\u9fff]), r\1\2, text) # 但保留英文单词之间的空格 # 在英文单词和中文之间增加一个空格视觉上更美观 text re.sub(r([a-zA-Z0-9])([\u4e00-\u9fff]), r\1 \2, text) text re.sub(r([\u4e00-\u9fff])([a-zA-Z0-9]), r\1 \2, text) # 3. 数字格式化例如将“一二三”转为“123”但需要谨慎可能误伤 # 此处演示一个简单版本仅处理纯中文数字的短序列 # num_map {一:1, 二:2, 三:3, 四:4, 五:5, 六:6, 七:7, 八:8, 九:9, 零:0, 十:10} # 更复杂的数字处理建议使用专门库或利用云服务自带的ITN逆文本归一化功能。 # 4. 去除重复的换行和空格 text re.sub(r\n, \n, text) text re.sub(r[ \t], , text) # 5. 首字母大写针对英文可选 # 将每个句子的第一个英文字母大写简单规则 def capitalize_sentence(match): return match.group(1) match.group(2).capitalize() text re.sub(r([。\.\?!;\n]\s*)([a-z]), capitalize_sentence, text) return text.strip() # 使用示例 raw_result 你好今天我们要学习python编程 请打开代码编辑器 第一课是打印helloworld processed postprocess_text(raw_result) print(原始文本, raw_result) print(后处理后, processed) # 输出可能为 # 原始文本 你好今天我们要学习python编程 请打开代码编辑器 第一课是打印helloworld # 后处理后 你好今天我们要学习Python编程。请打开代码编辑器。第一课是打印helloworld。后处理进阶思路标点恢复上述基于规则的句末分割很弱。对于中文可以尝试pypinyin结合语言模型或者直接使用如BART等预训练模型微调一个标点恢复模型这是目前效果最好的方法。数字与单位标准化将“一百二十”转为“120”“三点五公斤”转为“3.5公斤”。这需要构建一个复杂的规则引擎或使用序列标注模型。领域术语纠正如果你处理的是特定领域如医疗、法律的音频可以构建一个该领域的术语词典用模糊匹配如fuzzywuzzy库将识别出的近似词纠正为标准术语。5. 性能优化与常见问题排查在实际部署中你会遇到性能、稳定性等各种问题。这里记录一些典型场景和解决方案。5.1 性能优化策略1. 模型选择与量化本地模型在资源受限环境下模型大小就是生命线。Vosk提供small和tiny模型Whisper也有tiny和base。一个经验法则是先试用最小的模型如果精度不可接受再换大一号的。模型量化如果你使用PyTorch加载Whisper可以考虑使用torch.quantization进行动态量化能在几乎不损失精度的情况下减少内存占用并提升CPU推理速度。2. 音频流处理与分块对于实时或长音频处理不要一次性加载整个音频文件到内存。# 使用生成器流式读取大音频文件 def audio_chunk_generator(file_path, chunk_duration_ms30000): 将长音频按固定时长分块生成 audio AudioSegment.from_file(file_path) length_ms len(audio) for start in range(0, length_ms, chunk_duration_ms): end min(start chunk_duration_ms, length_ms) chunk audio[start:end] # 导出为临时WAV文件或直接使用字节流 yield chunk # 然后遍历生成器对每个chunk进行识别3. 并发与批处理I/O密集型云端API使用concurrent.futures.ThreadPoolExecutor进行并发调用可以显著缩短处理多个文件的总时间。但要注意API的速率限制QPS。CPU密集型本地模型使用multiprocessing池将音频文件列表分给多个进程并行处理。注意大型模型加载到每个进程内存中会成倍增加总内存消耗需要权衡进程数和内存容量。5.2 常见问题与排查清单当你遇到识别效果差、程序崩溃等问题时可以按以下清单排查问题现象可能原因排查步骤与解决方案识别结果全是乱码或单个字重复音频格式或编码不匹配1. 用ffprobe your_audio.mp3检查音频实际编码、采样率、声道数。2. 确保传递给API或库的参数sample_rate,format与实际音频一致。3. 使用pydub统一转换为标准格式单声道16kHzPCM WAV再试。识别速度极慢本地模型模型过大或硬件不足1. 检查CPU和内存使用情况top或任务管理器。2. 换用更小的模型如Vosk的small而非large。3. 确认是否意外使用了GPU版本但未安装CUDA导致回退到CPU。云端API返回“Invalid audio”或任务失败音频文件损坏或参数错误1. 用音频播放器确认文件能正常播放。2. 检查文件头是否完整尝试用pydub重新导出一次。3. 仔细核对API文档确保所有必填参数如AppKey,Token正确且未过期。实时识别延迟高、漏字音频缓冲区设置不当或系统负载高1. 调整sounddevice的blocksize更小的值降低延迟但增加CPU负担。2. 关闭其他占用声卡或CPU的程序。3. 对于Vosk尝试在AcceptWaveform之前对音频数据进行简单的VAD语音活动检测只传入有声音的片段。中文识别中夹杂英文单词错误模型语言设置或音频质量问题1. 明确指定语言参数如Whisper的languagezh。2. 如果确实是中英文混杂的音频可以尝试使用支持混合语言的模型或先分句再判断每句的语言进行识别。3. 提升音频质量特别是信噪比。内存使用不断增长直至崩溃内存泄漏常见于长时间运行的流式服务1. 检查代码中是否有全局列表或字典在不断累积数据而未清理。2. 如果是Whisper确保没有在循环中重复加载模型。3. 使用tracemalloc等工具定位内存增长点。5.3 一个实用的调试技巧可视化音频当识别结果不理想时直接“看”音频往往比听更有用。用librosa或matplotlib可以快速绘制波形和频谱图检查是否有 clipping削顶、持续噪声或音量过低的问题。import librosa import librosa.display import matplotlib.pyplot as plt import numpy as np def visualize_audio(file_path): 绘制音频波形和频谱图 y, sr librosa.load(file_path, srNone) # 保持原始采样率 duration len(y) / sr fig, ax plt.subplots(2, 1, figsize(12, 8)) # 1. 波形图 times librosa.times_like(y, srsr) ax[0].plot(times, y) ax[0].set(titlefWaveform - {file_path}, xlabelTime (s), ylabelAmplitude) ax[0].axhline(y0.8, colorr, linestyle--, alpha0.5, labelPossible Clipping (0.8)) ax[0].axhline(y-0.8, colorr, linestyle--, alpha0.5) ax[0].legend() ax[0].grid(True) # 2. 频谱图语谱图 D librosa.amplitude_to_db(np.abs(librosa.stft(y)), refnp.max) img librosa.display.specshow(D, y_axislog, x_axistime, srsr, axax[1]) ax[1].set(titleSpectrogram, xlabelTime (s), ylabelFrequency (Hz)) fig.colorbar(img, axax[1], format%2.0f dB) plt.tight_layout() plt.show() # 打印基础信息 print(fDuration: {duration:.2f} seconds) print(fSample Rate: {sr} Hz) print(fMax Amplitude: {np.max(np.abs(y)):.4f} (接近1.0表示可能削顶)) print(fAverage Amplitude (RMS): {np.sqrt(np.mean(y**2)):.4f}) # 使用 visualize_audio(your_audio.wav)通过波形图你可以一眼看出音量是否均匀是否有 clipping波形被“削平”。通过频谱图你可以看到背景噪声通常是低频或高频的连续横线和语音的清晰度。一个干净的、音量适中的音频其识别成功率会高很多。