AI 工具

把会议录音交给 Gemini,自动生成会议纪要

把会议录音交给 Gemini,自动生成会议纪要:摘要、已定结论、待办事项(负责人、截止日期、录音中的时间点)、未决问题,同时输出 Markdown 和 JSON。录音不需要先转文字,Gemini 直接“听”。

BINBHO · 图文教程

把会议录音交给 Gemini,自动生成会议纪要:摘要、已定结论、待办事项(负责人、截止日期、录音中的时间点)、未决问题,同时输出 Markdown 和 JSON。录音不需要先转文字,Gemini 直接“听”。

先看清成品

成品是 minutes.py。本文已用模拟客户端实际运行测试并通过:请求里包含音频和参会人名单,生成的 Markdown 待办表格、空列表占位、JSON 文件都正确。本文环境没有有效的 Gemini API 密钥,也没有真实会议录音,转写和总结质量没有实测。

注意:Gemini API 和 Google AI Studio 只在官方“可用地区”列表中的国家和地区提供,请在可用地区合规使用,不要用代理绕过地区限制。Gemini API 条款写明,使用免费服务时提交的内容可能被用于改进 Google 产品,不要上传含身份证号、银行卡号、他人隐私的材料。价格和免费额度以官方价格页为准。

注意:录音前要告知并征得所有参会人同意,遵守公司规定和当地关于录音的法律。涉及商业秘密的会议请先确认公司是否允许上传到外部服务。

做完之后你会得到什么?

成果 说明
音频上传 Files API,单个文件最大 2 GB,48 小时后自动删除
结构化纪要 摘要、决定、待办、未决问题
时间点定位 每个待办标注录音中的大致位置,方便回听核对
两种输出 给人看的 Markdown,给程序用的 JSON

需要准备哪些环境?

项目 要求 说明
Gemini API 密钥 在 Google AI Studio 创建 保存为环境变量 GEMINI_API_KEY
Python 3.10 或更高
依赖 pip install google-genai pydantic pytest 本文使用 google-genai 2.32.0
模型 gemini-3.8-flash 官方模型页 2026-10-19 更新时列为稳定版
录音 mp3、wav、m4a 等常见格式 手机录音即可

官方音频文档说明:每秒音频约 32 个 token(1 分钟约 1,920 个),单次请求最长 9.5 小时音频。一小时会议大约 11.5 万 token,费用以价格页为准。

第一步:代码怎么写?

1. 项目结构

meeting-minutes/
├── minutes.py
├── test_minutes.py
└── recordings/

2. minutes.py

"""把会议录音交给 Gemini,生成结构化会议纪要(Markdown + JSON)。
用法:python minutes.py 会议.mp3 [--attendees 张三,李四]
"""
import argparse
import json
from pathlib import Path
from typing import List, Optional

from pydantic import BaseModel, Field

MODEL = "gemini-3.8-flash"


class Action(BaseModel):
    owner: str = Field(description="负责人姓名,录音里没提到就写“待定”")
    task: str = Field(description="具体要做的事")
    due: Optional[str] = Field(description="截止日期,录音里明确说了才填,格式 YYYY-MM-DD")
    quote_time: str = Field(description="这项任务在录音中被提到的大致时间点,格式 MM:SS")


class Minutes(BaseModel):
    title: str = Field(description="会议主题,10 个字以内")
    summary: str = Field(description="三到五句话的会议摘要")
    decisions: List[str] = Field(description="会上已经确定的结论")
    actions: List[Action]
    open_questions: List[str] = Field(description="讨论了但没有结论的问题")


def prompt(attendees):
    p = ("你是会议记录员。仔细听这段中文会议录音,按给定 JSON 结构整理纪要。\n"
         "只记录录音里真实说过的内容,不要补充或推测;任务的负责人和截止日期必须是录音里明确提到的。")
    if attendees:
        p += f"\n参会人:{'、'.join(attendees)}。请用这些名字标注负责人。"
    return p


def summarize(path: Path, client, attendees=()) -> Minutes:
    f = client.files.upload(file=str(path))
    it = client.interactions.create(
        model=MODEL,
        input=[{"type": "text", "text": prompt(attendees)},
               {"type": "audio", "uri": f.uri, "mime_type": f.mime_type}],
        response_format={"type": "text", "mime_type": "application/json", "schema": Minutes.model_json_schema()},
    )
    return Minutes.model_validate_json(it.output_text)


def to_markdown(m: Minutes) -> str:
    lines = [f"# {m.title}", "", "## 摘要", "", m.summary, "", "## 决定", ""]
    lines += [f"- {d}" for d in m.decisions] or ["- (无)"]
    lines += ["", "## 待办", "", "| 负责人 | 事项 | 截止 | 录音位置 |", "| :--- | :--- | :--- | :--- |"]
    lines += [f"| {a.owner} | {a.task} | {a.due or '未定'} | {a.quote_time} |" for a in m.actions]
    lines += ["", "## 待讨论", ""] + ([f"- {q}" for q in m.open_questions] or ["- (无)"])
    return "\n".join(lines) + "\n"


def main(argv=None, client=None):
    ap = argparse.ArgumentParser()
    ap.add_argument("audio")
    ap.add_argument("--attendees", default="")
    a = ap.parse_args(argv)
    if client is None:
        from google import genai
        client = genai.Client()
    names = [x for x in a.attendees.split(",") if x]
    m = summarize(Path(a.audio), client, names)
    stem = Path(a.audio).with_suffix("")
    Path(f"{stem}-纪要.md").write_text(to_markdown(m), encoding="utf-8")
    Path(f"{stem}-纪要.json").write_text(m.model_dump_json(indent=2), encoding="utf-8")
    print(f"已生成 {stem}-纪要.md,待办 {len(m.actions)} 项")
    return m


if __name__ == "__main__":
    main()
要点 说明
{"type": "audio", ...} 官方音频文档的输入写法
quote_time 让模型给出时间点,方便你回听确认
“只记录真实说过的” 减少模型自行补充
参会人名单 帮助模型把“老张”对应到正确的人

第二步:怎样测试和运行?

1. 离线测试

import json
from types import SimpleNamespace

from minutes import main

SAMPLE = {"title": "官网改版周会", "summary": "确认了上线时间。", "decisions": ["11 月 1 日上线"],
          "actions": [{"owner": "张三", "task": "完成首页设计稿", "due": "2026-10-25", "quote_time": "03:12"},
                      {"owner": "待定", "task": "联系 CDN 供应商", "due": None, "quote_time": "15:40"}],
          "open_questions": []}


class Fake:
    def __init__(self):
        self.calls = []
        self.files = SimpleNamespace(upload=lambda file: SimpleNamespace(uri="files/x", mime_type="audio/mpeg"))
        self.interactions = SimpleNamespace(create=lambda **kw: self.calls.append(kw) or SimpleNamespace(output_text=json.dumps(SAMPLE, ensure_ascii=False)))


def test_outputs(tmp_path):
    audio = tmp_path / "周会.mp3"
    audio.write_bytes(b"")
    c = Fake()
    m = main([str(audio), "--attendees", "张三,李四"], client=c)
    assert c.calls[0]["input"][1]["type"] == "audio"
    assert "张三、李四" in c.calls[0]["input"][0]["text"]
    md = (tmp_path / "周会-纪要.md").read_text(encoding="utf-8")
    assert "| 待定 | 联系 CDN 供应商 | 未定 | 15:40 |" in md
    assert "## 待讨论\n\n- (无)" in md
    assert json.loads((tmp_path / "周会-纪要.json").read_text(encoding="utf-8"))["actions"][0]["owner"] == "张三"
    assert len(m.actions) == 2
python -m pytest -q

本文实际输出 1 passed。

2. 用真实录音运行

export GEMINI_API_KEY="你的密钥"
python minutes.py recordings/周会.mp3 --attendees 张三,李四,王五

期望输出 已生成 recordings/周会-纪要.md,待办 N 项。生成的 Markdown 结构如下(内容取决于录音):

# 官网改版周会

## 摘要

……

## 待办

| 负责人 | 事项 | 截止 | 录音位置 |
| :--- | :--- | :--- | :--- |
| 张三 | 完成首页设计稿 | 2026-10-25 | 03:12 |

3. 核对

检查项 做法
待办是否真实 按“录音位置”回听几条
负责人是否正确 对照参会人名单
截止日期 只有会上明确说了才应出现

纪要发出前一定要人工过一遍。

出问题时该怎么调?

1. 人名识别错

传入 --attendees;口音重或多人同时说话时效果会下降,尽量用靠近说话人的麦克风。

2. 时间点不准

模型给出的时间点是大致位置,可能有偏差,用来辅助定位,不作为精确时间戳。

3. 上传很慢或失败

先把录音压缩成单声道 mp3:

ffmpeg -i 会议.m4a -ac 1 -b:a 64k 会议.mp3

常见问题怎么处理?

现象 原因 解决方法
纪要太笼统 提示词太宽泛 在提示词里说明你关心的重点
编造了没说过的待办 模型幻觉 按时间点回听,删除不实内容
文件超过 2 GB Files API 单文件上限 压缩或分段
想要逐字稿 本脚本只做纪要 另写提示词要求输出带时间戳的转写
User location is not supported 地区不可用 只能在可用地区使用

项目资源

用途 地址
音频理解 https://ai.google.dev/gemini-api/docs/audio
Files API https://ai.google.dev/gemini-api/docs/files
结构化输出 https://ai.google.dev/gemini-api/docs/structured-output
模型列表 https://ai.google.dev/gemini-api/docs/models
Google AI Studio API 密钥 https://aistudio.google.com/apikey
价格 https://ai.google.dev/gemini-api/docs/pricing
可用地区 https://ai.google.dev/gemini-api/docs/available-regions
API 条款 https://ai.google.dev/gemini-api/terms

建议先用一段 5 分钟左右、你自己录的测试对话跑一次,对照录音检查每一条待办。

确认效果可靠后,再用于真实会议,并且每次发出前人工审核。