mcpField
M
meeting-brief

meeting-brief

github.com/marks97生产力0343 次安装4 周前更新
代码仓库

关于 meeting-brief

meeting-brief 是处理会议录音并生成归档报告的技能,也支持以音频而非文字回复。它包含私有 S3 收件箱录音的导入流程,并强调转录归档、说话人核对和录音隐私保护。

主要功能

  1. 01转录并整理会议报告
  2. 02按说话人分组并标注时间
  3. 03将原始录音与转录归档
  4. 04从私有 S3 收件箱导入录音
  5. 05以音频形式回复

适用场景

  1. 01将会议录音整理成行动项与决策
  2. 02处理浏览器扩展上传的会议录音
  3. 03为重要会议建立可核验的归档
  4. 04需要音频回复而非文字时使用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/marks97/meeting-brief --skill meeting-brief

安装后在 Claude Code 中输入/meeting-brief确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

keyterms.txt
extension/
background.js
capture.main.js
content.js
manifest.json
offscreen.html
offscreen.js
options.html
options.js
popup.html
popup.js
README.md
ui.css
ingest/
ingest.sh
ingest/presign-lambda/
deploy.sh
index.mjs
package.json
scripts/
aws-env.sh
extension-icons.mjs
format-transcript.mjs
lib.sh
say.sh
share.sh
transcribe.sh
unshare.sh

详细介绍

会议简报

两项功能相结合:将录音转换为归档会议报告,并用音频而非文字回复你。

两者也可以单独使用。在包含 .m4a 文件的文件夹上运行 /meeting-brief 可完成第一项。说“以后用音频回答我”可完成第二项。

严格规则

  • 绝不将用户的音频上传到公共主机。 不能上传到 tmpfiles、0x0.st、transfer.sh,也不能使用临时隧道。这些录音可能包含机密信息:薪资谈判、股权条款、收入、客户姓名。唯一获准的渠道是私有存储桶中的预签名 S3 URL。之所以设定这条规则,是因为之前曾有人违反过。
  • 只能使用预签名 URL,ACL 必须为私有。 绝不使用 --acl public-read,绝不更改存储桶策略,也绝不使用名称中包含 public 或 assets 的存储桶。
  • 用户回复后,删除对应片段。 用户的下一条消息表示他们已经听过。该轮处理任何其他事项之前,先对上一个对象运行 unshare.sh。
  • 绝不在转录文本中输出 API 密钥或机密。 脚本从环境变量或 .env 读取这些内容,绝不会将它们打印出来。

AWS 凭证来自项目,绝不来自全局配置文件

项目可以使用自己的 .env 和 AWS 账户,因此凭证会从项目而非全局配置文件解析。scripts/aws-env.sh 会从工作目录向上查找,直到找到第一个能提供有效凭证的 .env。

变量名并不总是标准化的。解析器会先尝试标准的 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY,然后尝试简写形式 AWS_ACCESS_KEY / AWS_ACCESS_SECRET。区域默认为 us-east-1,之后会通过 get-bucket-location 按存储桶进行校正。

将 MEETING_BRIEF_BUCKET 设为要存放音频的私有存储桶。该存储桶必须禁用公共访问;此技能使用私有 ACL 上传,并仅通过预签名 URL 分享,绝不会将任何内容设为全网可读。

流程 A:将录音转为归档报告

S=.claude/skills/meeting-brief/scripts
OUT=/tmp/claude/<project>/meeting-<date>

$S/transcribe.sh $OUT *.m4a                     # parallel, diarised, resumable
$S/format-transcript.mjs $OUT/raw-<x>.json \
    --map speaker_0=Alice,speaker_1=Bob          # speaker-grouped, timestamped

然后阅读转录文本,根据上下文辨认各人身份,并撰写报告。

务必传入关键词。 keyterms.txt 随此技能一同提供,transcribe.sh 会自动发送其中的内容。如果没有这些关键词,Scribe v2 会把不常见的产品、公司或工具名称误听成发音相似的常见词,进而影响后续所有摘要。遇到项目相关名词时,将其添加到该文件中。

说话人分离会给出 speaker_0、speaker_1 等标签,而不是姓名。撰写内容前,先根据上下文确定标签与人物的对应关系。对于重要事实(谁负责跟进、谁明天休假、个人背景),如果对应关系有任何不确定之处,请在保存前向用户确认身份,并将草稿写成“我把 X 认作 speaker A,把 Y 认作 speaker B;如果反了,请调换”,方便他们快速纠正。

配额(quota_exceeded)

Scribe v2 每秒音频约消耗 1.1 个额度。遇到 quota_exceeded 时,不要放弃:大多数长会议都包含无声间隔(会前准备、静默片段、长时间停顿)。使用 ffmpeg 去除静音后重试:

ffmpeg -y -i input.m4a \
  -af "silenceremove=stop_periods=-1:stop_duration=2:stop_threshold=-40dB" \
  -c:a aac -b:a 64k trimmed.m4a

这样可以缩短 20-40% 的时长,同时不损失任何语音。重新检查时长(ffprobe),并重新计算所需额度,然后再提交。归档原始音频,绝不能归档裁剪后的副本:裁剪只是转录时的处理产物,并非事实来源。

录音归档(确定日期、排序、优先归档)

录音会以项目提供的各种方式送达:放在工作区根目录、导出到 ~/Downloads、手机文件,或自动上传到 S3 收件箱。文件名通常很普通(meet.m4a、rec.m4a、audio 3.m4a),不包含可靠的日期。无论来源如何,都要遵守以下四条规则:

  • 始终先归档,再总结。 转录成功后,立即将 <audio> + .txt 文件对写入 arch/transcripts/,然后再撰写报告、行动事项或处理其他内容,即使用户只问了“他们决定了什么”也不例外。绝不能让用户开口索要归档。要验证文件已归档(将副本与源文件进行校验和比对),不要想当然。
  • 日期必须是录制日期,绝不是今天,也不是下载日期。 文件的修改时间是复制或导出时间:如果是当天收到的新文件,它可能与会议日期一致,但导出的文件或重新分享的文件可能相差数天,而且同一时段导出的多个文件修改时间都相同。要结合转录内容交叉核对(提到的星期几、“昨天我们发布了 X”、近期变更日志),并与 arch/transcripts/ 中上一份文件的间隔比较。只有在证据相互矛盾时才询问用户。如果源文件是 Apple Voice Memos 原件(20260806 104557.m4a),文件名就是录制开始时间:按字节大小再按校验和,将共享副本与原件匹配;匹配即为证明,无需询问。
  • 序号: 找出 arch/transcripts/ 中最大的现有 rec-NNN 序号,并使用下一个整数;在聊天中说明这一点,以便用户纠正跳过的序号。如果导出文件名中已有序号(Mi grabación 202.m4a -> rec-202),则保留该序号。绝不能仅因序号不确定就不归档录音。
  • 投放目录不是存储空间。 录音放入共享投放位置(工作区根目录、Downloads 文件夹、S3 收件箱)后,归档副本通过校验和验证后,就将文件移入 arch/transcripts/,然后删除源文件,确保下一次投放时不会产生歧义。如果同时有两个或更多音频文件待处理,说明有多场会议:按时间从早到晚处理,或询问用户要处理哪一个,绝不能合并。
归档约定

归档是一种可选约定。在工作区根目录下保留一个 arch/ 目录树,涵盖该工作区中的所有仓库。如果项目中已有 arch/README.md,请遵循其布局;否则,可以采用以下默认布局:

arch/
  README.md
  meetings/     YYYY-MM-DD-<counterpart>-<topic>.md
  transcripts/  YYYY-MM-DD-rec-<N>.txt  +  the original .m4a alongside
  reports/      YYYY-MM-DD-<topic>.md

报告通常包含以下部分:TL;DR、行动事项、决策、需记住的事项、待解决问题、已完成 / 进行中事项、主题。以下两项约定值得遵守:

  • 任何地方都不要使用 em dash。 使用连字符、冒号、句号或括号。
  • 每项行动都必须指定明确的负责人。 “应该有人做”不算行动事项。
  • 绝不要将完整转录稿粘贴到报告中。请链接到 transcripts/ 下的文件。

使用 ffprobe 获取实际时长,不要根据文件大小估算:

ffprobe -v error -show_entries format=duration -of csv=p=0 file.m4a

Flow C:从 S3 收件箱导入(浏览器扩展)

此处的 extension/ 文件夹是一个浏览器扩展,可自动录制网络会议(Google Meet、Zoom 网页版、Teams 网页版),并将其上传到私有 S3 收件箱,因此你无需用手机录音或移交文件。录音会以 inbox/<workspace>/<ts>-<title>.webm 及其 .json 伴随文件的形式存入(平台、标题、会议 URL、参与者、开始/结束时间、是否采集麦克风、contentType)。录制相关内容请参阅 extension/README.md,端点请参阅 ingest/presign-lambda/。

每当用户提到通话时,收件箱都是首要查找位置,不只是用户说“检查收件箱”时才查。“我刚开完一个会”“我们在会上决定了什么” “转录我最近的会议”“处理我的会议”都应从这里开始,然后再询问文件。只有收件箱里没有合适的内容时,才回退到项目的文件投放位置(Flow A),然后再询问。

I=.claude/skills/meeting-brief/ingest/ingest.sh   # set MEETING_INBOX_BUCKET + AWS creds (env or AWS_PROFILE)

$I list                                        # pending clips, newest first: title | start | participants
$I pull inbox/<ws>/<file>.webm /tmp/claude/<project>/meeting-in

首先按时间挑选片段(“刚开完”的通话结束时间在最近一两个小时内; startedAt/endedAt 位于伴随文件中),然后再根据标题/参与者是否与用户提到的人匹配来挑选。如果有两个或更多片段符合条件,列出来并询问用户选哪一个,不要猜。

始终先转换为 .m4a,然后对 .m4a 执行常规 Flow A:

ffmpeg -v error -i clip.webm -vn -c:a aac -b:a 64k clip.m4a   # then transcribe clip.m4a

这不是可选步骤,原因有两个。如果通话期间关闭了标签页(伴随文件中的 reason: tab_closed 或 stalled),收到的 webm 会没有正常结尾(“文件提前结束”):ffmpeg 可以正常解码,但 Scribe 可能不行。而手动录制如果开启了视频,格式会是 video/webm;-vn 会去掉视频。只有用户想重看时才保留原始视频。伴随文件中的 capture 说明录制方式:page 表示自动录制(在会议页面内采集通话音频和用户的麦克风音频),tab 表示通过弹出窗口手动录制。

路由:由会议主题决定归档位置,而不是当前所在的会话,也不是标签。 workspace 标签只是录制会议的浏览器上设置的默认值(一个浏览器可以录制多个项目的通话),因此通话很容易被打上错误的标签。根据会议内容判断:参会人员、标题、转录文本中的主题。在聊天中说明你将其归档到哪个项目以及原因,然后直接归档到该项目的 arch/。

如果无法根据伴随文件判断,又不想花费额度在错误的项目中转录,请原样移交:$I retag <key> <workspace>。归档前先用 ffmpeg 转码为 .m4a,使归档符合常用的 .m4a 规范。配对文件归档并通过校验和验证后:

$I done inbox/<ws>/<file>.webm                 # deletes the clip + sidecar from the inbox

收件箱是投递箱,不是存储空间(与 Flow A 中任何投放的录音遵循同一规则): 只有在确认 arch/transcripts/ 中的副本无误后,才删除每个片段。

录制端:安装、发布更改、调试
  • 录制方式,以及唯一不可撤销的更改。 自动录制发生在会议页面内(extension/capture.main.js,一个包装 RTCPeerConnection 和 getUserMedia 的 world: MAIN 内容脚本)。绝不要把自动启动改回 chrome.tabCapture:Chrome 只允许在点击扩展程序后进行标签页录制,因此它无法自行启动;v0.1/v0.2 正是因此在第一次真实 Meet 通话中什么都没录到。标签页录制仅用于弹出窗口中的手动启动,也是获取视频的唯一方式。完整设计见 extension/README.md。

  • 安装或更新: 运行部署输出的安装单行命令(curl -fsSL <your-endpoint>/install | sh),然后前往 chrome://extensions -> 加载已解压的扩展程序(首次安装;按 Cmd+Shift+G 并粘贴),或点击重新加载箭头(更新)。从稳定文件夹加载已解压的扩展程序后,更新时扩展程序会保持相同的 ID,因此 Options 中的令牌会保留。绝不要从 Downloads 加载。

  • 发布扩展程序更改: 编辑 extension/,递增 manifest.json 中的 version,然后运行 cd ingest/presign-lambda && BUCKET=<your-inbox-bucket> TOKEN=<current> ./deploy.sh (环境中需有你账户的 AWS 凭据;令牌位于 Lambda 环境变量中,参见 extension/README.md)。这会重新打包 /extension 提供的 zip 文件;重新运行安装命令并点击重新加载。完成前,务必在真实 WebRTC 通话中验证录制器更改(README 中介绍了 Chromium 测试环境)。

  • “我的通话录下来了吗?”但收件箱是空的: 检查端点,而不是代码。

    aws cloudwatch get-metric-statistics --region us-east-1 --namespace AWS/ApiGateway \
      --metric-name Count --dimensions Name=ApiId,Value=<your-api-id> --statistics Sum --period 300 \
      --start-time $(date -u -d '-3 hours' +%FT%TZ) --end-time $(date -u +%FT%TZ)
    

    通话期间没有请求:浏览器从未尝试录制(自动录制关闭、没有令牌、仍在使用基于标签页录制的旧版本,或页面钩子未捕获到通话)。4xx:令牌或端点有误。生成了预签名 URL,但 S3 中没有文件:PUT 失败。弹出窗口中的最近上传状态行也会显示浏览器端的同一情况。

  • 状态: 已在真实 Google Meet 通话中确认(2026-10-01,v0.3.0):无需点击即可启动(即使通话中只有自己),捕获麦克风音频,挂断时停止,完成上传,并成功转录。Zoom 网页版和 Teams 网页版使用相同的录制器,但尚未在实际通话中确认。对于 meet.new 通话,标题只有会议代码;日历会议会显示会议名称。参与者姓名尽力获取,但通常为空,因此请从转录内容中识别参会者。

流程 B:音频回复模式

用户会用手机阅读,通常无法快速浏览长篇回复。在此模式下,每条实质性回复都会以语音播报。

S=.claude/skills/meeting-brief/scripts

# 1. delete the clip from the previous turn; they have replied so they have heard it
$S/unshare.sh "s3://<bucket>/<previous-key>" <project-dir> <previous-local-file>

# 2. write the reply as a SPOKEN script, then
$S/say.sh reply.txt /tmp/claude/<project>/reply-<n>.mp3 1.5

# 3. private link
$S/share.sh /tmp/claude/<project>/reply-<n>.mp3 <project-dir>

然后发布 URL,附上最多两三行文字:说明音频涵盖的内容,以及他们必须采取的行动。不要附上音频转录稿。此模式的目的就是让他们不必阅读。

记下返回的 s3:// URI 和本地路径,以便下一轮删除它们。

默认语速为 1.5。 ElevenLabs 自带的 speed 设置最高为 1.2,因此 say.sh 会以正常速度渲染,再通过 ffmpeg atempo 调整速度;对于超出 0.5-2.0 范围的值,会串联多个滤镜。音高会保持不变。

撰写适合聆听的内容

大声朗读 Markdown 会让人难以忍受。调用 say.sh 前请先转换:

  • 将数字写成单词:“每月四百九十九”,不要写成“$499/mo”。
  • 不要包含文件路径、URL 或代码标识符。应将这些内容放在链接旁的文字消息中。
  • 不要使用项目符号、标题或粗体。改用“第一”“第二”“接下来”等表达。
  • 对于通常按字母念出的缩写,逐个字母读出:“M R R”“U X”“U I”。
  • 如果摘要依赖的内容存在已知转录错误,开头就要提醒。
  • 段落之间留空行。say.sh 会按这些边界分段,并使用 previous_text / next_text 拼接,让语调在衔接处保持连贯。

默认语音是平静的广播式朗读(onwK4e9ZLuTAKqWW03F9)。使用 MEETING_BRIEF_VOICE 覆盖。模型默认通过 MEETING_BRIEF_MODEL 设为 eleven_multilingual_v2。

脚本

脚本功能
scripts/transcribe.sh <outdir> <audio>...使用 Scribe v2 转录,区分说话人、添加关键词、并行处理,并跳过已有输出
scripts/format-transcript.mjs <raw.json> [--map s0=Name,...]带时间戳、按说话人分组的转录文本
scripts/say.sh <script.txt> <out.mp3> [speed] [voice]分块进行 TTS,拼接音频并调整语速
scripts/share.sh <file> [project-dir] [expires]上传到私有 S3,并生成预签名 URL(最长 7 天)
scripts/unshare.sh <s3-uri> [project-dir] [local-file]删除对象,并可选择删除本地文件
scripts/aws-env.sh按项目解析凭据,由上述脚本加载
scripts/lib.sh加载 ElevenLabs 密钥
scripts/extension-icons.mjs重新生成扩展程序的工具栏图标(闲置和录制状态)
ingest/ingest.sh {list,pull,done,retag}S3 会议收件箱(Flow C)
ingest/presign-lambda/deploy.sh重新部署端点,并重新打包在 <your-endpoint>/extension 提供的扩展程序 zip 文件

从环境中读取 ELEVENLABS_API_KEY。如果环境中尚未定义该变量,可以通过 ELEVENLABS_ENV_FILE 指定一个定义了该变量的本地 .env 文件。

环境说明

  • 使用 & 或 nohup 进行后台运行可能无法在工具调用结束后继续运行。 请改用 Bash 工具的 run_in_background,这是可靠地保持进程运行的方法。
  • 预签名 URL 按 HTTP 方法签名。 对由 GET 签名的 URL 执行 curl -I 会返回 403,这是正常现象,并不代表失败。请使用带范围的 GET 请求验证:curl -r 0-2000 "$URL"。
  • 需要 ffmpeg 和 ffprobe(请使用包管理器安装)。
  • 请将临时文件放在仓库之外(例如 /tmp/claude/<project>/)。

不适用场景

  • 简短的事实性回答。不要让用户为了听一句话而播放音频片段。
  • 用户需要复制粘贴的任何内容:路径、URL、命令和 ID 都必须以文本提供。
  • 代码审查或差异内容。音频不适合阅读代码。

评论

支持 Markdown