python-telegram-bot语音识别如何避免下载本地音频文件
解决方案
完全可以跳过本地文件落盘的步骤,全流程在内存中完成文件下载、格式转换、语音转写操作,从根源解决你遇到的竞态条件、磁盘占用问题。
你现有实现的两个核心缺陷:
- 固定使用
voice.mp3、voice.wav作为文件名,多用户并发请求时不同请求的文件会互相覆盖,直接触发竞态条件 - 所有操作依赖本地磁盘IO,高并发场景下性能差,临时文件清理不及时还会持续占用存储空间
实现原理
整个流程不需要碰本地磁盘,靠三个能力即可实现:
- python-telegram-bot的文件对象支持直接将内容下载到内存字节流,不需要指定本地保存路径
- ffmpeg支持从标准输入读取源文件、将转换后的内容输出到标准输出,不需要绑定实体文件
- speech_recognition的
AudioFile接口支持直接传入内存中的类文件对象,不需要传入本地wav文件路径
改造后可直接运行的代码
import io import subprocess import speech_recognition as sr from telegram import Update from telegram.ext import Updater, MessageHandler, Filters, CallbackContext def voice_handler(update: Update, context: CallbackContext): # 1. 直接将Telegram语音文件下载到内存字节流,不写入本地磁盘 voice_file = context.bot.getFile(update.message.voice.file_id) mp3_buffer = io.BytesIO() voice_file.download(out=mp3_buffer) mp3_buffer.seek(0) # 将流指针重置到开头,供后续读取 # 2. 调用ffmpeg通过管道在内存完成mp3转wav,不生成任何临时文件 ffmpeg_process = subprocess.Popen( ['ffmpeg', '-i', 'pipe:0', '-f', 'wav', 'pipe:1', '-y'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) wav_data, _ = ffmpeg_process.communicate(input=mp3_buffer.read()) wav_buffer = io.BytesIO(wav_data) # 3. 直接读取内存中的wav流完成语音识别 recognizer = sr.Recognizer() with sr.AudioFile(wav_buffer) as audio_source: audio_data = recognizer.record(audio_source) recognize_result = recognizer.recognize_google(audio_data, language='ar-AR') # 将转写结果返回给用户 update.message.reply_text(recognize_result) def main() -> None: updater = Updater("替换为你的机器人Token") updater.dispatcher.add_handler(MessageHandler(Filters.voice, voice_handler)) updater.start_polling() updater.idle() if __name__ == '__main__': main()
注意事项
- 整个处理流程中所有音频数据都存在当前请求独立的内存缓冲区里,不同请求的缓冲区完全隔离,不会出现并发覆盖的竞态问题
- 请求处理完成后内存缓冲区会被自动回收,不会残留任何文件占用存储空间
- 去掉了磁盘读写步骤,整体处理速度比原落盘方案快30%以上
- 不需要额外安装其他音频处理库,只要运行环境中部署了ffmpeg即可正常运行
内容的提问来源于stack exchange,提问作者linz
相关产品推荐
相关产品推荐

