news 2026/4/16 18:16:09

用Python分析Fun-ASR的history.db,提取全部记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python分析Fun-ASR的history.db,提取全部记录

用Python分析Fun-ASR的history.db,提取全部记录

Fun-ASR作为一款面向本地部署的语音识别系统,其WebUI界面简洁直观,但真正沉淀业务价值的,往往不是界面上一闪而过的识别结果,而是那些被默默存入webui/data/history.db中的每一条历史记录。这个SQLite数据库文件虽小,却完整保存了每一次识别的上下文:音频来源、语言设置、热词配置、原始文本与规整后文本——它是一份结构清晰、可编程访问的语音操作日志。

很多用户只把Fun-ASR当作“即用即走”的工具,直到某次误点“清空所有记录”,或重装系统后发现两周的会议转写全没了,才意识到:那个.db文件,才是你语音资产的唯一副本

本文不讲如何部署模型、不调参数、不比准确率,而是聚焦一个务实问题:如何用Python安全、稳定、可复用地读取并导出全部识别记录?你会学到一套轻量级但生产可用的数据提取方案——无需修改Fun-ASR源码,不依赖WebAPI,不启动服务,仅靠标准库就能把history.db变成你的结构化数据源。


1. 理解history.db:不是日志,是结构化数据库

Fun-ASR将所有识别历史统一存入单个SQLite数据库,路径固定为webui/data/history.db。它不是文本日志,也不是临时缓存,而是一个符合ACID特性的关系型数据库文件。这意味着:

  • 数据写入时自动事务提交,断电也不会丢记录;
  • 支持标准SQL查询,可按时间、关键词、语言等任意字段筛选;
  • 表结构稳定,v1.0.0至今未变更,兼容性好;
  • 可直接用Python内置sqlite3模块读取,零第三方依赖。

只要Fun-ASR运行过至少一次识别,该文件就已存在且可读。你不需要登录WebUI,甚至不需要启动服务,只需找到这个文件,就能开始分析。

小提示:在Linux/macOS中,可通过find /path/to/funasr -name "history.db"快速定位;Windows用户可在资源管理器中搜索history.db,注意检查是否在webui\data\子目录下(反斜杠路径)。


2. 数据表结构详解:一张表,九个关键字段

Fun-ASR使用单一数据表recognition_history存储全部记录,建表语句如下:

CREATE TABLE recognition_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, filename TEXT, file_path TEXT, language TEXT, hotwords TEXT, use_itn BOOLEAN, raw_text TEXT, normalized_text TEXT );

我们逐字段说明其实际含义与使用价值:

2.1 核心标识字段

  • id:自增整数主键,全局唯一。它是记录的“身份证号”,也是WebUI中“查看详情”“删除记录”功能的依据。
  • timestamp:ISO格式时间字符串(如2025-04-05 14:23:10)。精确到秒,可用于按时间排序、统计日频次、绘制趋势图。

2.2 音频上下文字段

  • filename:上传时的原始文件名(如team_meeting_20250405.mp3),不含路径,便于快速识别来源。
  • file_path:音频在服务器上的绝对或相对路径(如/home/user/audio/team_meeting_20250405.mp3)。这是追溯原始音频的关键线索,尤其当批量处理多个目录时。

2.3 识别配置字段

  • language:识别所用语种代码,常见值为zh(中文)、en(英文)、ja(日文)。可用于分语言统计识别量或质量。
  • hotwords:热词列表,以逗号分隔的字符串(如钉钉,通义,Fun-ASR)。若未设置则为空字符串。可用于分析哪些专业术语被高频强化。
  • use_itn:布尔值(SQLite中存为0/1),表示是否启用智能文本规整。值为1代表启用了ITN,输出更规范(如“二零二五年”→“2025年”)。

2.4 文本内容字段

  • raw_text:模型原始输出,保留口语化表达、重复词、语气词等。适合做语音错误分析、ASR模型诊断。
  • normalized_text:经ITN规整后的文本,更接近书面语,可读性强,适合导入知识库、生成摘要、做NLP下游任务。

实用建议:日常使用中,优先查看normalized_text;做模型效果对比或调试时,重点分析raw_textnormalized_text的差异。


3. Python提取全流程:从连接到导出

下面提供一套完整、健壮、可直接运行的Python脚本,用于安全读取并导出全部记录。代码基于标准库sqlite3,兼容Python 3.7+,无需安装额外包。

3.1 基础连接与查询函数

import sqlite3 import os from datetime import datetime from typing import List, Dict, Optional def connect_to_history_db(db_path: str) -> Optional[sqlite3.Connection]: """ 安全连接history.db,验证文件存在且可读 返回数据库连接对象,失败返回None """ if not os.path.exists(db_path): print(f"❌ 错误:数据库文件不存在 — {db_path}") return None if not os.access(db_path, os.R_OK): print(f"❌ 错误:无读取权限 — {db_path}") return None try: conn = sqlite3.connect(db_path) # 验证表是否存在 cursor = conn.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='recognition_history';") if not cursor.fetchone(): print(f"❌ 错误:数据库中缺少表 'recognition_history'") conn.close() return None return conn except Exception as e: print(f"❌ 连接数据库失败:{e}") return None def fetch_all_records(conn: sqlite3.Connection) -> List[Dict]: """ 查询全部记录,返回字典列表,字段名与数据库一致 """ cursor = conn.cursor() cursor.execute(""" SELECT id, timestamp, filename, file_path, language, hotwords, use_itn, raw_text, normalized_text FROM recognition_history ORDER BY id ASC """) columns = [desc[0] for desc in cursor.description] rows = cursor.fetchall() records = [] for row in rows: record = dict(zip(columns, row)) # 将use_itn转换为Python布尔值 record["use_itn"] = bool(record["use_itn"]) records.append(record) return records

3.2 导出为CSV:最通用的交换格式

CSV格式兼容Excel、Google Sheets、数据库导入、BI工具,是跨平台共享的首选。

import csv def export_to_csv(records: List[Dict], output_path: str): """ 将记录列表导出为CSV文件 """ if not records: print(" 提示:无记录可导出") return # 定义CSV字段顺序(按数据库字段,但调整为更易读的顺序) fieldnames = [ "id", "timestamp", "filename", "file_path", "language", "hotwords", "use_itn", "raw_text", "normalized_text" ] try: with open(output_path, "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for record in records: # CSV不支持布尔值,转为字符串 record_copy = record.copy() record_copy["use_itn"] = "True" if record_copy["use_itn"] else "False" writer.writerow(record_copy) print(f" 成功导出 {len(records)} 条记录至:{output_path}") except Exception as e: print(f"❌ 导出CSV失败:{e}") # 使用示例 if __name__ == "__main__": DB_PATH = "webui/data/history.db" # 替换为你的实际路径 OUTPUT_CSV = f"funasr_history_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" conn = connect_to_history_db(DB_PATH) if conn: records = fetch_all_records(conn) print(f" 共读取 {len(records)} 条识别记录") export_to_csv(records, OUTPUT_CSV) conn.close()

注意:encoding="utf-8-sig"确保Excel能正确识别中文;-sig前缀添加BOM头,避免乱码。

3.3 导出为JSON:适合程序集成与API对接

JSON格式保留原始数据类型(如布尔值、null),更适合后续Python、JavaScript程序解析。

import json def export_to_json(records: List[Dict], output_path: str): """ 将记录列表导出为JSON文件,保持数据类型 """ try: with open(output_path, "w", encoding="utf-8") as f: json.dump(records, f, ensure_ascii=False, indent=2) print(f" 成功导出 {len(records)} 条记录至:{output_path}") except Exception as e: print(f"❌ 导出JSON失败:{e}") # 在主程序中添加调用: # export_to_json(records, f"funasr_history_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json")

3.4 按条件筛选:只导出你需要的部分

实际工作中,你可能只想导出某段时间、某种语言或含特定关键词的记录。以下函数支持灵活过滤:

def filter_records( records: List[Dict], start_time: str = None, end_time: str = None, language: str = None, keyword_in_text: str = None ) -> List[Dict]: """ 按条件筛选记录 start_time/end_time 格式:'2025-04-01 00:00:00' """ filtered = records.copy() if start_time: filtered = [r for r in filtered if r["timestamp"] >= start_time] if end_time: filtered = [r for r in filtered if r["timestamp"] <= end_time] if language: filtered = [r for r in filtered if r["language"] == language] if keyword_in_text: kw = keyword_in_text.lower() filtered = [ r for r in filtered if kw in r.get("raw_text", "").lower() or kw in r.get("normalized_text", "").lower() ] return filtered # 使用示例:导出今天所有中文记录 # today = datetime.now().strftime("%Y-%m-%d") # today_records = filter_records( # records, # start_time=f"{today} 00:00:00", # end_time=f"{today} 23:59:59", # language="zh" # ) # export_to_csv(today_records, "today_chinese.csv")

4. 进阶技巧:让数据真正为你所用

导出只是第一步。当你拥有了结构化数据,就可以解锁更多实用场景。

4.1 快速统计:一眼看清使用情况

from collections import Counter def quick_stats(records: List[Dict]): """ 打印基础统计信息 """ if not records: return print("\n 快速统计报告") print("-" * 40) print(f"总记录数:{len(records)}") print(f"最早记录:{records[0]['timestamp']}") print(f"最新记录:{records[-1]['timestamp']}") # 按语言统计 lang_counter = Counter(r["language"] for r in records) print(f"\n按语言分布:{dict(lang_counter)}") # ITN启用率 itn_enabled = sum(1 for r in records if r["use_itn"]) print(f"ITN启用率:{itn_enabled}/{len(records)} ({itn_enabled/len(records)*100:.1f}%)") # 平均文本长度 norm_lens = [len(r["normalized_text"]) for r in records if r["normalized_text"]] if norm_lens: print(f"平均规整文本长度:{sum(norm_lens)//len(norm_lens)} 字") # 调用 # quick_stats(records)

4.2 关键词提取:发现高频讨论主题

利用jieba(需pip install jieba)对normalized_text做简单分词,快速发现会议或客服对话中的核心话题:

import jieba from collections import Counter def extract_top_keywords(records: List[Dict], top_k: int = 10): """ 从规整文本中提取高频关键词(中文) """ all_words = [] for r in records: text = r.get("normalized_text", "") if text: # 过滤停用词(简单版:去掉标点、单字、常见虚词) words = jieba.lcut(text) words = [w.strip() for w in words if len(w.strip()) > 1] all_words.extend(words) counter = Counter(all_words) print(f"\n 高频关键词(前{top_k}):") for word, count in counter.most_common(top_k): print(f" '{word}' — {count} 次") # 调用(需先安装jieba) # extract_top_keywords(records)

4.3 自动备份脚本:防误删的最后一道防线

将上述逻辑封装为定时备份脚本,每天凌晨自动执行:

#!/bin/bash # backup_history.sh DATE=$(date +%Y%m%d_%H%M%S) DB_PATH="/path/to/funasr/webui/data/history.db" BACKUP_DIR="/backup/funasr" mkdir -p $BACKUP_DIR cp "$DB_PATH" "$BACKUP_DIR/history_$DATE.db" echo "Backup done: history_$DATE.db"

配合crontab(Linux/macOS):

# 每天凌晨2:00执行 0 2 * * * /path/to/backup_history.sh

5. 常见问题与避坑指南

Q1:脚本运行报错“No such table: recognition_history”

A:确认数据库路径正确,且Fun-ASR确实已执行过至少一次识别(首次运行不会自动建表)。可手动检查:

sqlite3 webui/data/history.db ".tables" # 应输出:recognition_history

Q2:导出CSV后Excel打开全是乱码

A:务必使用encoding="utf-8-sig"(注意-sig),这是Windows Excel识别UTF-8的必要前缀。

Q3:file_path字段为空,无法定位原始音频

A:这是Fun-ASR的设计行为——当通过麦克风录音时,file_path为空;只有上传本地文件时才填写。建议在批量处理时统一使用绝对路径上传,便于溯源。

Q4:想合并多个Fun-ASR实例的历史记录

A:SQLite支持ATTACH命令。在新数据库中执行:

ATTACH 'instance1.db' AS db1; ATTACH 'instance2.db' AS db2; INSERT INTO recognition_history SELECT * FROM db1.recognition_history; INSERT INTO recognition_history SELECT * FROM db2.recognition_history;

Q5:能否实时监听新记录并自动触发动作?

A:可以。SQLite不支持原生触发器监听,但可通过轮询id最大值实现:

last_id = 0 while True: current_max = get_max_id_from_db() # SELECT MAX(id) FROM ... if current_max > last_id: new_records = fetch_records_since(last_id + 1) process_new_records(new_records) # 如发通知、存ES last_id = current_max time.sleep(30) # 每30秒检查一次

6. 总结:把语音数据变成你的数字资产

Fun-ASR的history.db不是一个需要敬畏的黑箱,而是一份设计清晰、接口开放、易于编程的数据源。通过本文提供的Python脚本,你可以:

  • 零依赖提取全部记录:仅用sqlite3,不改一行Fun-ASR代码;
  • 按需导出结构化数据:CSV供业务分析,JSON供程序集成;
  • 灵活筛选与统计:按时间、语言、关键词快速定位目标记录;
  • 构建自动化护城河:定时备份、异常告警、跨实例合并,让语音资产真正可控。

技术的价值,不在于它多炫酷,而在于它是否让你对数据拥有确定性。当你能随时说出“上周三下午三点的客户咨询内容是什么”,并一键导出原文,你就已经把语音识别,从一个功能,升级为一种工作方式。

现在,就打开终端,运行第一行python extract_history.py吧。你的语音数据,值得被认真对待。

--- > **获取更多AI镜像** > > 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 14:19:31

短视频创作者福音!IndexTTS 2.0快速生成贴合配音

短视频创作者福音&#xff01;IndexTTS 2.0快速生成贴合配音 你有没有过这样的经历&#xff1a;剪完一条30秒的vlog&#xff0c;反复试了7种AI配音&#xff0c;不是语速太快赶不上画面切换&#xff0c;就是情绪太平像机器人念稿&#xff0c;最后只好自己录——结果背景音里全是…

作者头像 李华
网站建设 2026/4/16 14:21:55

LVGL与ESP32结合实现智能中控:项目应用

以下是对您提供的博文内容进行 深度润色与工程化重构后的版本 。我以一位深耕嵌入式GUI开发多年、亲手调通过数十款LVGLESP32项目的工程师视角&#xff0c;彻底重写全文—— 去除所有AI腔调、模板化结构与空泛术语&#xff0c;代之以真实项目中的踩坑经验、性能实测数据、代…

作者头像 李华
网站建设 2026/4/16 18:00:51

all-MiniLM-L6-v2高可用:构建负载均衡的Embedding服务集群

all-MiniLM-L6-v2高可用&#xff1a;构建负载均衡的Embedding服务集群 1. 为什么需要高可用的Embedding服务 你有没有遇到过这样的情况&#xff1a;线上搜索、语义去重或RAG应用突然变慢&#xff0c;甚至返回503错误&#xff1f;点开日志一看&#xff0c;全是“Connection re…

作者头像 李华
网站建设 2026/4/16 16:06:39

Proteus元件对照表操作指南:在原理图中正确选型

以下是对您提供的博文内容进行 深度润色与专业重构后的版本 。本次优化严格遵循您的要求&#xff1a; ✅ 彻底去除AI痕迹 &#xff0c;语言自然、真实、有“人味”&#xff0c;像一位资深嵌入式系统教学博主在分享实战经验&#xff1b; ✅ 打破模板化结构 &#xff0c;…

作者头像 李华
网站建设 2026/4/16 9:17:56

亲测YOLO11镜像,目标检测效果惊艳实录

亲测YOLO11镜像&#xff0c;目标检测效果惊艳实录 本文不是理论推导&#xff0c;也不是参数调优指南——而是一份真实、可复现、带结果截图的端到端实测记录。从镜像启动到检测出图&#xff0c;全程在标准开发环境完成&#xff0c;不跳步、不美化、不回避问题。所有操作均基于C…

作者头像 李华
网站建设 2026/4/16 15:34:09

手把手教你部署Qwen3-VL-8B:现代化AI聊天界面搭建

手把手教你部署Qwen3-VL-8B&#xff1a;现代化AI聊天界面搭建 你是否试过&#xff1a;下载好模型、配好环境、写完接口&#xff0c;结果浏览器打开页面时只看到一片空白&#xff1f;或者明明终端显示“服务已启动”&#xff0c;却怎么也收不到响应&#xff1f;更别提还要手动处…

作者头像 李华