Paraformer-large数据库持久化:MySQL存储识别结果实战
1. 引言:从语音识别到数据落地
你有没有遇到过这种情况:用语音识别工具转写了一堆会议录音、课程讲座或者客户访谈,结果发现识别完的内容只能看、不能存?每次重启服务,历史记录全没了。这在实际工作中简直是个灾难。
本文要解决的就是这个问题——如何把Paraformer-large语音识别的结果,自动保存进MySQL 数据库,实现真正的“一次识别,永久留存”。我们基于自带 Gradio 界面的离线版镜像,在不破坏原有交互体验的前提下,增加数据库持久化能力,让整个系统更接近生产级应用。
这不是简单的模型调用教程,而是一次完整的工程化改造实践。你会学到:
- 如何在现有 Gradio 应用中接入 MySQL
- 设计合理的数据表结构来存储音频元信息和识别文本
- 实现识别结果自动入库
- 添加查询功能,回溯历史记录
整个过程无需复杂配置,代码改动极小,但价值巨大。适合正在做语音处理项目、需要长期积累语音数据的同学。
2. 环境准备与依赖安装
2.1 前置条件确认
确保你的运行环境满足以下要求:
- 已部署
Paraformer-large离线语音识别镜像(含 FunASR + Gradio) - GPU 实例(推荐 RTX 4090D 或更高)
- Python 3.9+,PyTorch 2.5 环境已激活
- 可访问本地或远程 MySQL 服务
如果你使用的是 AutoDL 类平台,MySQL 可以选择本地安装或连接云端实例。为简化演示,本文采用本地安装方式。
2.2 安装数据库驱动
进入工作目录并激活环境后,安装 Python 操作 MySQL 所需的库:
source /opt/miniconda3/bin/activate torch25 pip install pymysql sqlalchemy说明:
pymysql是纯 Python 的 MySQL 客户端实现,轻量且兼容性好sqlalchemy提供 ORM 支持,便于后续扩展
2.3 创建数据库与表结构
登录 MySQL 并创建专用数据库:
CREATE DATABASE IF NOT EXISTS asr_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE asr_db; CREATE TABLE asr_records ( id INT AUTO_INCREMENT PRIMARY KEY, filename VARCHAR(255) NOT NULL, filepath TEXT, duration DECIMAL(6,2), text_result LONGTEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );这个表设计考虑了实用性:
filename存文件名,方便检索filepath记录完整路径,便于后期关联原始音频duration存时长,可用于统计分析text_result用 LONGTEXT,支持超长文本存储- 时间字段自动维护,减少代码负担
3. 修改主程序:集成数据库写入逻辑
我们将原app.py进行升级,在保留原有 UI 功能的基础上,加入数据库操作模块。
3.1 新增数据库连接配置
在文件顶部添加配置项:
import gradio as gr from funasr import AutoModel import os import pymysql from datetime import datetime from sqlalchemy import create_engine, text # === 数据库配置 === DB_CONFIG = { 'host': 'localhost', 'user': 'root', 'password': 'your_password', # 替换为真实密码 'database': 'asr_db', 'charset': 'utf8mb4' } # 创建数据库连接引擎 engine = create_engine( f"mysql+pymysql://{DB_CONFIG['user']}:{DB_CONFIG['password']}@" f"{DB_CONFIG['host']}/{DB_CONFIG['database']}?charset={DB_CONFIG['charset']}" )⚠️ 安全提示:生产环境中建议将密码放入环境变量或配置文件,不要硬编码。
3.2 封装数据库操作函数
定义一个简洁的插入函数:
def save_asr_result(filename, filepath, duration, text): try: with engine.connect() as conn: sql = text(""" INSERT INTO asr_records (filename, filepath, duration, text_result) VALUES (:filename, :filepath, :duration, :text) """) conn.execute(sql, { 'filename': filename, 'filepath': filepath, 'duration': duration, 'text': text }) conn.commit() return True except Exception as e: print(f"数据库写入失败: {e}") return False3.3 升级识别处理函数
修改原来的asr_process函数,使其支持返回音频信息并触发存储:
def asr_process(audio_path): if audio_path is None: return "请先上传音频文件" # 获取文件基本信息 filename = os.path.basename(audio_path) filepath = os.path.abspath(audio_path) # 获取音频时长(可通过 ffmpeg 获取,这里简化处理) # 实际项目中可用 pydub 或 librosa 精确计算 try: import subprocess result = subprocess.run( ['ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', audio_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) duration = float(result.stdout.strip()) except: duration = 0.0 # 执行识别 res = model.generate(input=audio_path, batch_size_s=300) if len(res) > 0: text = res[0]['text'] # 自动保存到数据库 if save_asr_result(filename, filepath, duration, text): status = "✅ 识别完成,结果已保存至数据库" else: status = "⚠️ 识别完成,但数据库保存失败" return f"{status}\n\n---\n{text}" else: return "❌ 识别失败,请检查音频格式"这样改的好处是:
- 不影响原有输出展示
- 用户能直观看到“是否成功入库”
- 错误有明确反馈,便于排查
4. 扩展功能:增加历史记录查询面板
为了让系统更实用,我们在界面上加一个“查看历史”功能,让用户可以随时回顾之前的识别内容。
4.1 添加查询函数
def list_history(): try: with engine.connect() as conn: result = conn.execute(text("SELECT id, filename, created_at FROM asr_records ORDER BY created_at DESC LIMIT 50")) rows = result.fetchall() return [[r[0], r[1], r[2].strftime("%Y-%m-%d %H:%M")] for r in rows] except Exception as e: return [["错误", str(e), ""]]4.2 更新 Gradio 界面布局
重构with gr.Blocks()部分,加入新功能区:
with gr.Blocks(title="Paraformer 语音转文字控制台") as demo: gr.Markdown("# 🎤 Paraformer 离线语音识别转写系统") gr.Markdown("支持长音频上传,自动添加标点符号和端点检测,并持久化存储至 MySQL。") with gr.Tabs(): with gr.Tab("实时转写"): with gr.Row(): with gr.Column(scale=1): audio_input = gr.Audio(type="filepath", label="上传音频或直接录音") submit_btn = gr.Button("开始转写", variant="primary") with gr.Column(scale=2): text_output = gr.Textbox(label="识别结果", lines=15) submit_btn.click(fn=asr_process, inputs=audio_input, outputs=text_output) with gr.Tab("历史记录"): gr.Markdown("### 📚 最近50条识别记录") history_table = gr.Dataframe( headers=["ID", "文件名", "识别时间"], datatype=["number", "str", "str"], col_count=(3, "fixed") ) refresh_btn = gr.Button("刷新列表") refresh_btn.click(fn=list_history, outputs=history_table)现在用户可以在两个标签页之间切换:
- “实时转写”:继续使用原有功能
- “历史记录”:查看所有已保存的识别条目
虽然目前还不能点击查看具体内容,但你可以轻松扩展list_history查询语句,把text_result也带出来。
5. 启动脚本与自动化部署
5.1 更新启动命令
将新的app.py放入/root/workspace/目录,并设置开机自启:
source /opt/miniconda3/bin/activate torch25 && cd /root/workspace && python app.py确保该命令已在平台“服务启动命令”中填写,以便实例重启后自动运行。
5.2 测试流程验证
- 上传一段
.wav或.mp3音频文件 - 点击“开始转写”
- 查看输出框是否有“✅ 结果已保存”提示
- 切换到“历史记录”标签页,点击“刷新列表”,确认新记录出现
如果一切正常,说明你的语音识别系统已经具备数据持久化能力!
6. 总结:打造可落地的语音处理系统
6.1 我们完成了什么?
通过本文的实战改造,你已经将一个“玩具级”的语音识别 Demo,升级成了一个具备生产潜力的系统。关键改进包括:
- ✅结果持久化:识别内容自动存入 MySQL,永不丢失
- ✅结构化存储:设计合理表结构,支持后续数据分析
- ✅用户体验提升:新增历史查询功能,操作闭环
- ✅低侵入式改造:仅新增不到 100 行代码,不影响核心逻辑
这套方案特别适合用于:
- 企业内部会议纪要自动化归档
- 教学视频字幕生成与管理
- 客服通话内容结构化存储
- 科研语音数据采集平台搭建
6.2 下一步优化方向
如果你想进一步完善这个系统,可以考虑以下几个方向:
- 🔐安全增强:使用
.env文件管理数据库密码 - 📈功能扩展:支持按日期、关键词搜索历史记录
- 💾文件管理:自动清理旧音频,保留文本即可
- 🔄批量处理:添加文件夹批量导入功能
- 📊可视化统计:展示每日识别时长、字数趋势图
这些都不是必须的,但在真实项目中会非常有用。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。