开会录音丢进去,自动转出文字稿、生成摘要、提取待办事项。告别会后整理噩梦,30秒拿到完整会议纪要。
你有没有这种经历:开了两小时会,录音录得满满当当,但回去整理纪要能磨蹭一整天。
更惨的是,开会时只顾着听,根本没记下来。散会了才想起来——刚才说的下个月要干啥,谁负责啥,完全没记录。
今天做一个会议录音整理器。录好的音频丢进去,自动转文字、生成摘要、提取待办。整个过程全自动,你只管开会。
项目背景
开会、开会、还是开会。每天三五个会,会后整理纪要是最头疼的事。
市面上的工具要么收费(Otter.ai、讯飞听见),要么要联网(飞书妙记)。本地跑一个,数据不出公司,还能随时改 prompt 适配你的会议风格。
核心流程就三步:
- 语音转文字(Whisper)
- AI 总结内容(本地 Ollama)
- 提取待办事项 + 责任人
全程在本地运行,隐私安全,零月费。
技术选型
| 组件 | 选型 | 理由 |
|---|---|---|
| 语音转文字 | Whisper(openai-whisper) | 开源免费,中文效果好 |
| 文本总结 | Ollama + qwen2.5 | 本地运行,不依赖外部 API |
| 音频处理 | moviepy / pydub | 支持各种音频格式 |
| 结果保存 | Markdown | 方便后续编辑和版本管理 |
不需要数据库。每个会议一个 Markdown 文件,按日期归档,随时可查。
实现步骤
第一步:安装依赖
pip install openai-whisper pydub moviepy
如果你用 Ubuntu/Debian,还需要:
sudo apt install ffmpeg libavcodec-extra
Ollama 部分:
# 安装 Ollama(如果还没装)
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型(7B 够用,8GB 显存/内存就能跑)
ollama pull qwen2.5:7b
第二步:编写核心脚本 meeting_organizer.py
#!/usr/bin/env python3
"""
会议录音整理器
自动转文字 → AI 总结 → 提取待办
"""
import os
import json
import re
import subprocess
from pathlib import Path
from datetime import datetime
import whisper
import requests
# ============ 配置区 ============
AUDIO_DIR = Path.home() / "meetings" / "raw"
OUTPUT_DIR = Path.home() / "meetings" / "output"
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL = "qwen2.5:7b"
WHISPER_MODEL = "base" # medium / large 效果更好但更慢
# 会议摘要 prompt
SUMMARY_PROMPT = """你是一个专业的会议记录员。请对以下会议录音转写文本进行整理。
输出格式(严格按照以下 JSON 格式,不要添加其他内容):
{{
"title": "会议主题标题(20字以内)",
"date": "会议日期(YYYY-MM-DD)",
"summary": "会议核心内容总结(100字以内)",
"key_points": ["要点1", "要点2", "要点3"],
"action_items": [
{{"owner": "负责人姓名", "task": "待办事项", "due": "截止日期(如有)"}}
],
"decisions": ["会议中做出的重要决定"],
"next_meeting": "下次会议安排(如有)"
}}
会议文本:
{text}
"""
def transcribe_audio(audio_path: str, model_name: str = WHISPER_MODEL) -> str:
"""使用 Whisper 转录音频"""
print(f"🎙️ 正在转录: {audio_path}")
model = whisper.load_model(model_name)
result = model.transcribe(audio_path, language="zh")
return result["text"]
def summarize_with_ollama(text: str) -> dict:
"""调用 Ollama 生成会议摘要"""
prompt = SUMMARY_PROMPT.format(text=text[:4000]) # 限制长度避免超限
try:
resp = requests.post(
OLLAMA_URL,
json={"model": MODEL, "prompt": prompt, "stream": False},
timeout=120
)
response_text = resp.json().get("response", "")
# 提取 JSON
start = response_text.find("{")
end = response_text.rfind("}") + 1
if start >= 0 and end > start:
return json.loads(response_text[start:end])
# 降级:返回原文
return {"raw_output": response_text}
except Exception as e:
print(f"⚠️ Ollama 请求失败: {e}")
return {"error": str(e)}
def save_meeting_report(data: dict, date: str) -> Path:
"""保存会议报告为 Markdown"""
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
filename = f"{date}_{data.get('title', '未命名')}.md"
filepath = OUTPUT_DIR / filename
content = f"""# {data.get('title', '会议记录')}
**日期**: {data.get('date', date)}
**整理时间**: {datetime.now().strftime('%Y-%m-%d %H:%M')}
---
## 📋 会议摘要
{data.get('summary', '暂无摘要')}
## 🔑 关键要点
"""
for i, point in enumerate(data.get("key_points", []), 1):
content += f"{i}. {point}\n"
content += "\n## ✅ 待办事项\n\n"
for item in data.get("action_items", []):
due = f"(截止:{item.get('due', '待定')})" if item.get("due") else ""
content += f"- [ ] {item.get('task', '未命名任务')} — {item.get('owner', '未知')}{due}\n"
content += "\n## 📌 重要决定\n\n"
for decision in data.get("decisions", []):
content += f"- {decision}\n"
if data.get("next_meeting"):
content += f"\n## 📅 下次会议\n\n{data['next_meeting']}\n"
filepath.write_text(content, encoding="utf-8")
return filepath
def process_meeting(audio_path: str):
"""处理单个会议音频文件"""
audio_path = Path(audio_path)
date_str = datetime.now().strftime("%Y-%m-%d")
# 步骤1:语音转文字
transcript = transcribe_audio(str(audio_path))
print(f"✅ 转录完成,共 {len(transcript)} 字")
# 保存原始转写文本
transcript_dir = OUTPUT_DIR / "transcripts"
transcript_dir.mkdir(parents=True, exist_ok=True)
transcript_file = transcript_dir / f"{date_str}_{audio_path.stem}.txt"
transcript_file.write_text(transcript, encoding="utf-8")
# 步骤2:AI 总结
print("🤖 正在生成摘要...")
summary = summarize_with_ollama(transcript)
# 步骤3:保存报告
report_path = save_meeting_report(summary, date_str)
print(f"✅ 会议报告已保存: {report_path}")
return report_path
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("用法: python meeting_organizer.py <音频文件路径>")
print("支持格式: mp3, wav, m4a, mp4, webm")
print("\n示例:")
print(' python meeting_organizer.py ./录音.mp3')
print(' python meeting_organizer.py ~/meetings/raw/2026-08-06.mp3')
sys.exit(1)
process_meeting(sys.argv[1])
第三步:批量处理多个会议文件
如果你想一次性处理多个录音,用这个批量脚本:
# batch_process.py
#!/usr/bin/env python3
import sys
from pathlib import Path
from meeting_organizer import process_meeting
AUDIO_DIR = Path.home() / "meetings" / "raw"
if __name__ == "__main__":
audio_files = list(AUDIO_DIR.glob("*.mp3")) + \
list(AUDIO_DIR.glob("*.m4a")) + \
list(AUDIO_DIR.glob("*.wav"))
print(f"📂 找到 {len(audio_files)} 个音频文件\n")
for audio_file in audio_files:
print(f"\n{'='*50}")
print(f"处理: {audio_file.name}")
print('='*50)
try:
process_meeting(str(audio_file))
except Exception as e:
print(f"❌ 处理失败: {e}")
print("\n🎉 全部处理完成!")
第四步:设置定时整理
把脚本加入 cron,每周自动整理一次:
crontab -e
# 每周日晚上 22:00 整理本周所有会议录音
0 22 * * 0 /usr/bin/python3 ~/meetings/batch_process.py >> ~/meetings/process.log 2>&1
运行效果
python meeting_organizer.py ./meetings/2026-08-06-产品评审.mp3
输出:
🎙️ 正在转录: ./meetings/2026-08-06-产品评审.mp3
✅ 转录完成,共 2847 字
🤖 正在生成摘要...
✅ 会议报告已保存: /home/user/meetings/output/2026-08-06_产品功能评审会.md
生成的 Markdown 报告:
# 产品功能评审会
**日期**: 2026-08-06
**整理时间**: 2026-08-06 15:30
---
## 📋 会议摘要
讨论了 Q3 产品路线图,确定了三个核心功能优先级,分配了各模块负责人。
## 🔑 关键要点
1. 用户反馈系统重构,预计 2 周完成
2. 数据分析看板新增实时指标
3. 移动端适配方案确定
## ✅ 待办事项
- [ ] 完成用户反馈系统 API 设计 — 张三(截止:2026-08-20)
- [ ] 输出数据分析看板原型 — 李四
- [ ] 编写移动端适配技术方案 — 王五(截止:2026-08-15)
## 📌 重要决定
- 用户反馈系统优先级调整为 P0
- 数据分析看板接入实时数据流
优化方向
这个基础版本已经能用了。想进一步打磨可以加这些:
- 说话人分离:用
pyannote.audio识别不同说话人,区分谁说了什么。 - 多语言支持: Whisper 支持 99 种语言,自动检测语言类型。
- 飞书/钉钉推送:整理完成后自动发送 Markdown 报告到团队群。
- 历史对比:记录每周会议内容变化,生成趋势分析。
- 关键词提取:自动提取会议中的高频词,生成话题标签。
- Web 界面:用 Streamlit 搭个上传页面,手机也能传录音。
成本对比
| 方案 | 月费 | 隐私 | 准确度 |
|---|---|---|---|
| 飞书妙记 | 免费版有限 | 数据上云 | ⭐⭐⭐⭐ |
| 讯飞听见 | ¥0.13/分钟 | 数据上云 | ⭐⭐⭐⭐⭐ |
| 本方案 | ¥0 | 完全本地 | ⭐⭐⭐ |
本方案完全本地运行,录音数据不离开你的电脑。准确度略低于商业服务,但胜在免费、隐私、可定制。
把今天的会议录音丢进去,看看能省多少整理时间。你公司的会议通常多久?两小时的会,整理纪要至少要半小时吧。
这篇文章对你有帮助吗?