FSMN VAD输出结果导出:JSON转CSV批量处理脚本
1. 为什么需要这个脚本?
你刚用FSMN VAD WebUI跑完一批会议录音,页面上漂亮地显示着一串JSON结果:
[ {"start": 70, "end": 2340, "confidence": 1.0}, {"start": 2590, "end": 5180, "confidence": 1.0} ]但问题来了——领导要你把所有音频的语音片段起止时间整理成Excel表格,方便导入到标注平台;同事想用Python做后续统计分析;而你手头有37个音频文件,每个都得手动复制粘贴、改格式、加文件名……光是点开37次网页就让人头皮发麻。
别折腾了。这篇脚本就是为你写的——一行命令,把几十个JSON结果自动合并成一个带文件名标记的CSV表格,字段清晰、时间可读、开箱即用。
它不依赖WebUI后台,不修改原系统,纯本地运行,5分钟就能部署好。你甚至不用懂Python,复制粘贴就能跑通。
2. 脚本能做什么?(小白一眼看懂)
这个脚本不是“又一个转换工具”,而是专为FSMN VAD工作流设计的轻量级生产力补丁。它解决的是真实场景里的三个卡点:
- 自动识别文件归属:不用手动给每个JSON加文件名。脚本会根据JSON文件名(如
meeting_01.json)自动提取音频名,并写入CSV第一列 - 时间单位人性化转换:原始JSON里全是毫秒(
start: 70),脚本自动转成秒(0.07)和标准时间格式(00:00:00.070),Excel里直接可排序、可计算时长 - 一键批量合并:把分散在
/results/目录下的37个JSON,合成一个vad_summary.csv,结构像这样:
| audio_name | start_ms | end_ms | duration_ms | start_sec | end_sec | duration_sec | start_time | end_time | confidence |
|---|---|---|---|---|---|---|---|---|---|
| meeting_01 | 70 | 2340 | 2270 | 0.07 | 2.34 | 2.27 | 00:00:00.070 | 00:00:02.340 | 1.0 |
| meeting_01 | 2590 | 5180 | 2590 | 2.59 | 5.18 | 2.59 | 00:00:02.590 | 00:00:05.180 | 1.0 |
注意:同一音频可能有多段语音,所以
audio_name会重复出现——这正是你做分段统计需要的结构。
它不生成图片、不调用API、不连数据库,就是一个干净的.py文件,双击或命令行运行即可。连Python环境都不用额外装(只要你的WebUI能跑起来,说明环境已经齐了)。
3. 快速上手:三步完成部署
3.1 准备工作:确认你的文件结构
脚本默认从./vad_results/目录读取所有.json文件。请先确保你的FSMN VAD WebUI导出的JSON按如下方式存放:
your_project/ ├── vad_results/ │ ├── interview_01.json │ ├── interview_02.json │ └── call_center_20240512.json └── convert_json_to_csv.py ← 你将创建的脚本小技巧:WebUI的“批量文件处理”功能还在开发中,但你可以用它的单文件模式,把每个音频单独处理,然后把结果JSON手动保存到
vad_results/目录——这是目前最稳的落地方式。
3.2 创建转换脚本(复制即用)
新建一个文件,命名为convert_json_to_csv.py,粘贴以下内容(已实测兼容Python 3.8+,无需额外安装包):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ FSMN VAD JSON to CSV Batch Converter Author: 科哥 | 支持 FSMN VAD WebUI 输出格式 Input: ./vad_results/*.json (each contains list of {"start", "end", "confidence"}) Output: ./vad_summary.csv (with readable time columns) """ import os import json import csv from datetime import timedelta def ms_to_time_str(ms): """Convert milliseconds to HH:MM:SS.mmm format""" if ms < 0: return "00:00:00.000" td = timedelta(milliseconds=ms) hours, remainder = divmod(td.seconds, 3600) minutes, seconds = divmod(remainder, 60) return f"{hours:02d}:{minutes:02d}:{seconds:02d}.{ms%1000:03d}" def main(): input_dir = "./vad_results" output_file = "./vad_summary.csv" # Collect all JSON files json_files = [f for f in os.listdir(input_dir) if f.endswith(".json")] if not json_files: print(f"❌ 错误:未在 '{input_dir}' 目录下找到任何 .json 文件") print("请确认文件路径正确,且至少有一个 JSON 结果文件") return print(f" 发现 {len(json_files)} 个 JSON 文件,开始处理...") # Prepare CSV headers fieldnames = [ "audio_name", "start_ms", "end_ms", "duration_ms", "start_sec", "end_sec", "duration_sec", "start_time", "end_time", "confidence" ] with open(output_file, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() processed_count = 0 for json_file in json_files: try: # Extract audio name (remove .json extension) audio_name = os.path.splitext(json_file)[0] # Load JSON with open(os.path.join(input_dir, json_file), "r", encoding="utf-8") as jf: data = json.load(jf) # Process each segment for seg in data: start_ms = int(seg.get("start", 0)) end_ms = int(seg.get("end", 0)) conf = float(seg.get("confidence", 0.0)) duration_ms = end_ms - start_ms start_sec = round(start_ms / 1000, 3) end_sec = round(end_ms / 1000, 3) duration_sec = round(duration_ms / 1000, 3) start_time = ms_to_time_str(start_ms) end_time = ms_to_time_str(end_ms) writer.writerow({ "audio_name": audio_name, "start_ms": start_ms, "end_ms": end_ms, "duration_ms": duration_ms, "start_sec": start_sec, "end_sec": end_sec, "duration_sec": duration_sec, "start_time": start_time, "end_time": end_time, "confidence": conf }) processed_count += 1 print(f" ✔ 已处理 {json_file} ({len(data)} 段语音)") except Exception as e: print(f" ❌ 处理 {json_file} 失败:{str(e)}") continue print(f"\n 全部完成!共处理 {processed_count}/{len(json_files)} 个文件") print(f" 结果已保存至:{output_file}") print(" 提示:用 Excel 或 WPS 打开 CSV,'start_time' 列可直接排序查看语音顺序") if __name__ == "__main__": main()3.3 运行脚本并验证结果
打开终端(Linux/macOS)或命令提示符(Windows),进入你的项目目录,执行:
python convert_json_to_csv.py你会看到类似这样的输出:
发现 3 个 JSON 文件,开始处理... ✔ 已处理 meeting_a.json (2 段语音) ✔ 已处理 meeting_b.json (3 段语音) ✔ 已处理 call_2024.json (1 段语音) 全部完成!共处理 3/3 个文件 结果已保存至:./vad_summary.csv 提示:用 Excel 或 WPS 打开 CSV,'start_time' 列可直接排序查看语音顺序打开生成的vad_summary.csv,你应该能看到整齐的表格,时间列已自动格式化,可以直接用于汇报、分析或导入其他工具。
常见问题直答:
Q:报错ModuleNotFoundError: No module named 'csv'?
A:不可能。csv是Python标准库,只要能运行WebUI,这个脚本一定可以跑。检查是否输错了文件名,或路径里有中文空格。Q:CSV里时间显示乱码?
A:用Excel打开时,选择“UTF-8编码”;WPS用户请右键→“以编码方式打开”→选UTF-8。
4. 进阶用法:按需定制你的输出
脚本设计为“开箱即用,按需可调”。如果你有特殊需求,只需改几行代码,无需重写逻辑。
4.1 修改输入/输出路径(两处)
找到脚本中的这两行:
input_dir = "./vad_results" output_file = "./vad_summary.csv"改成你实际的路径,例如:
input_dir = "/home/user/fsnm_vad_outputs" output_file = "/home/user/reports/vad_all_2024.csv"4.2 过滤低置信度片段(加一行判断)
如果你只关心置信度≥0.8的语音段,在for seg in data:循环内加入:
conf = float(seg.get("confidence", 0.0)) if conf < 0.8: # 跳过置信度低于0.8的片段 continue4.3 添加音频时长字段(扩展分析维度)
想同时知道原始音频总时长?只需在writer.writerow({...})前加一行:
# 假设你有 audio_duration_ms 字段(需提前获取,例如从FFmpeg) # 这里演示如何添加:audio_duration_ms = 120000 # 2分钟 # 然后在 writer.writerow 中加入: # "audio_duration_ms": audio_duration_ms,实用建议:真正需要音频总时长的场景,推荐用FFmpeg批量提取,再用pandas合并——但这已超出本脚本范围。本脚本专注做好一件事:把VAD结果变成可分析的表格。
5. 为什么这个方案比其他方法更可靠?
市面上有各种JSON转CSV工具,但它们对FSMN VAD场景普遍存在三个硬伤:
| 对比项 | 通用在线转换器 | Excel“从文本导入” | 本脚本 |
|---|---|---|---|
| 文件归属识别 | ❌ 需手动为每个JSON加列 | ❌ 同样需手动 | 自动提取文件名,一目了然 |
| 毫秒转时间格式 | ❌ 只做数值转换 | ❌ 公式复杂易错 | 内置ms_to_time_str(),精准到毫秒 |
| 多段语音展开 | ❌ 把整个JSON当一整行 | ❌ 无法自动拆分数组 | 每段语音独立成行,结构规整 |
| 错误容忍度 | ❌ JSON格式稍错就崩溃 | ❌ 编码错误常导致乱码 | try/except包裹,单文件失败不影响全局 |
| 零依赖部署 | ❌ 需联网、有隐私风险 | ❌ Windows/Mac行为不一致 | 纯本地,无网络,无第三方服务 |
更重要的是——它和你的工作流无缝咬合。你不需要改变现有操作习惯:照常在WebUI里点“开始处理”,照常把结果存成JSON,最后跑一次脚本。没有学习成本,没有流程切换,没有新工具要适应。
它不是炫技的工程,而是帮你每天省下15分钟的务实工具。
6. 总结:让VAD结果真正可用
FSMN VAD本身是个强大的模型,但再好的技术,如果结果不能被业务方快速理解、不能被下游工具直接消费,它的价值就会大打折扣。
这个脚本做的,就是打通从“模型输出”到“业务可用”的最后一公里:
- 它把冷冰冰的毫秒数字,变成Excel里可排序、可筛选、可求和的时间戳;
- 它把散落的37个JSON文件,聚合成一张清晰的总览表,让项目经理一眼看清每段语音归属;
- 它用最朴素的Python标准库实现,不引入任何新依赖,确保在你现有的服务器、笔记本、甚至树莓派上都能稳定运行。
你不需要成为Python专家,也不需要理解FSMN的内部结构。你只需要记住:
下次导出一堆JSON时,cd进目录,敲python convert_json_to_csv.py,喝口茶,回来就有一张 ready-to-use 的CSV。
这才是AI工具该有的样子——不制造新麻烦,只默默解决老问题。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。