meeting-transcription
Skill13 starsChanged 16 days agoMITView on GitHub
Operates a context-aware meeting-transcription pipeline: recording, whisper.cpp plus pyannote diarization on a worker host, voice-matched speaker names, transcript handed to /debrief. Trigger: "transcribe a meeting", "transcription folder", "add a speaker", "train a voice", "speaker diarization", "reprocess recording", "how does my transcription system work".
1 other project uses a version of this.
Adopted by
Most recently taken up by
- fiveonecode/agent-skillstheir own version, first seen Sep 6, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- fiveonecode/agent-skills★ 20same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository44 other files it gives its agents.
- AGENTS.mdAGENTS.md
- skills/board-pilot/references/agents.mdAGENTS.md
- .github/copilot-instructions.mdCopilot instructions
- a2aSkill
- archiveSkill
- board-pilotSkill
- bridge-auditSkill
- bridge-contributeSkill
- bridge-curatorSkill
- bridge-explorerSkill
- bridge-greetingSkill
- bridge-leak-checkSkill
- bridge-learnSkill
- bridge-onboardSkill
- bridge-overlaySkill
- bridge-promoteSkill
- bridge-statusSkill
- bridge-syncSkill
- briefingSkill
- calendarSkill
- capability-brokerSkill
- channelSkill
- cmuxSkill
- cockpitSkill
- dashboardSkill
- debriefSkill
- doc-systemSkill
- github-projects-managerSkill
- html-canvasSkill
- html-slidesSkill
- knowledge-repo-initSkill
- mail-draftSkill
- mandantsSkill
- object-storeSkill
- onboard-simSkill
- remoteSkill
- scheduleSkill
- secretsSkill
- spec-kickoffSkill
- task-close-postmortemSkill
- tmuxSkill
- tracker-syncSkill
- workloadSkill
- workspaceSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 194
Add workflow/contexts/<name>.yaml (copy from _template.yaml — fill schema_version, scope, id, and an integrations.transcription block).
- Distinctive: line 246
Voice libraries are per-context: Never match one context's meeting against another context's voices — that's the whole point of the split.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Meeting Transcription Pipeline
A pipeline that turns meeting recordings into clean, structured Markdown
transcripts with named speakers. It is context-aware: each context
(e.g. main, customer-x) has its own voice library, language default, and
output routing, so the same system serves internal standups and customer calls
in different languages without reconfiguration.
This skill is both the knowledge base (how the system works) and the
operations manual (how to change it). The canonical scripts live in
scripts/ here and are deployed to the worker host's ~/transcribe-pipeline/.
It is the reference implementation of the bring-your-own-worker contract in
docs/transcription-worker.md — /debrief
talks to it only through scripts/debrief_sync.sh (pull / push).
Configuration — the yaml wiring
Three config surfaces, same pattern as every other capability:
1. bridge-config.yaml — the integration block (is the capability on, which
script, which contexts — registration + routing):
integrations:
transcription:
enabled: true
sync_script: "skills/meeting-transcription/scripts/debrief_sync.sh"
default_context: main # context for audio handed off without an explicit one
contexts:
main: # → workflow/contexts/main.yaml
imports: work/imports # where this context's transcripts land on pullBRIDGE_IMPORTS / TRANSCRIBE_CONTEXTS env-override the imports dir + context
list. /debrief degrades gracefully to its manual path when the block is absent
(see the contract doc).
2. infra/transcriptions/topology.yaml — placement (WHERE the pipeline runs):
mode: remote # local | remote — THE topology switch (env TRANSCRIBE_MODE overrides)
worker: # consulted only when mode == remote
host: worker-host # SSH/Tailscale alias — see infra/remotes/
launchd_label: com.openbridge.transcribe-worker
# local: # consulted only when mode == local; all keys optional
# inbox_dir: ~/transcribe-inbox # defaults = the worker's own conventions
# transcripts_dir: ~/Transcripts
# library_dir: ~/transcribe-pipeline/speaker-library
# contexts_dir: ~/transcribe-pipeline/contextsResolution: TRANSCRIBE_MODE / TRANSCRIBE_WORKER env > topology.yaml >
inferred (a worker host resolves ⇒ remote, else local). remote runs every op
over ssh+rsync; local runs plain filesystem cp/mv with no SSH (the compute
stack is still required). An unknown mode fails loud. Schema + guide:
infra/transcriptions/README.md.
3. workflow/contexts/<ctx>.yaml — per-context settings. A context
"participates in transcription" iff it carries an integrations.transcription:
block (schema: IntegrationTranscription in workflow/contexts/_schema.yaml):
integrations:
transcription:
language: auto # de | en | auto (multi-window vote)
library: main # → speaker-library/<library>/*.npy on the worker
output: main # → ~/Transcripts/<output>/ on the worker
notify: false # completion ping (e.g. iMessage on macOS)
# mic_speaker: Alice # display name for the dual-track mic channel (default "Me")The skill does not maintain its own context directory — two files joined-by-slug drift silently. Discovery rule (codified — run this whenever you need to know what contexts exist):
for f in workflow/contexts/*.yaml:
data = yaml.safe_load(f)
if data.get("integrations", {}).get("transcription"):
ctx = data["id"] # slug, e.g. "main"
settings = data["integrations"]["transcription"]
# → this context is live; use settingsThe worker doesn't parse the bridge yaml directly (its cfg() helper is
awk-based and can't read nested keys). The deploy step closes that gap:
scripts/extract_runtime_contexts.py reads the bridge yamls, flattens each
integrations.transcription block into a flat runtime yaml per context
(language, library, output, notify, mic_speaker), and rsyncs the result to
~/transcribe-pipeline/contexts/. The worker keeps its simple parser; the
bridge keeps a single source of truth.
The 30-second model
capture machine (optional) worker host Claude
────────────────────────── ─────────── ──────
2-track recorder or any ──► ffmpeg split (mic-L / meeting-R)
mixed recording whisper.cpp large-v3 (Metal GPU) ASR
~/Recordings/meetings/<ctx>/ + pyannote diarize on MPS (+embeddings)
│ │
launchd transcribe-bundler.sh speaker_naming.py ◄── speaker-library/<ctx>/*.npy
rsync per context │
▼ merge_transcripts.py → transcript-raw.md
worker:~/transcribe-inbox/<ctx>/ │ (the NAKED transcript = worker output)
launchd transcribe-worker.sh deliver ~/Transcripts/<ctx>/<ts>.md
│
▼ NO summary on the worker
in-session /debrief → context-aware summary + tasks
second way in, no capture machine:
audio in imports/ or a recordings source ──► /debrief ──► debrief_sync.sh push
──► worker:~/transcribe-inbox/<ctx>/Two ways in. The capture machine with its bundler is optional. The second
way needs neither a second machine nor a recorder app: drop any audio file where
/debrief scans, and it hands the file to the worker with debrief_sync.sh push
(see the sync-script commands below). It is the lowest barrier into the pipeline,
so start there.
Key idea — identity comes from voice, not text. Speakers are matched by pyannote voice-embedding (cosine ≥ 0.60) against a per-context library, so "Alice" is always labelled Alice even when Whisper mishears her name.
Second key idea — transcription is mechanical, interpretation is contextual.
The worker produces ONLY the naked transcript (ASR + diarization + voice-match —
no bridge context needed). The summary/tasks are made by the in-session
/debrief, which has the bridge loaded (name conventions, ecosystem, board,
open issues, contexts, prior meetings). A headless worker-side summarizer was
removed for being context-blind: it distorted names and significance.
When to read which reference
This SKILL.md is the map. For anything beyond the quick operations below, open the matching reference — they hold the detail so this file stays scannable.
| You need to… | Read |
| Understand data flow, file layout, every script's role | references/architecture.md |
| Add a context, add/re-train a speaker, reprocess, extend the pipeline | references/operations.md |
| Know what you need first (worker / capture / bridge prerequisites) | references/deployment.md § Prerequisites |
| Provision a worker host from scratch (venv, HF token, launchd) | references/deployment.md |
| Fix diarization bleed, OOM, language misdetect, delivery failures | references/troubleshooting.md |
Core concepts
- Context = the inbox subfolder a recording lands in. Defined by the
integrations.transcriptionblock ofworkflow/contexts/<name>.yaml(see Configuration above). To add a context: add the yaml, re-deploy. - Voice library =
speaker-library/<context>/<name>.npy— 256-dim pyannote embeddings, one file per known speaker (can stack multiple samples). Bootstrapped once per speaker, then reused forever. - Bilingual = Whisper auto-detects language (or the context forces it); the
transcript frontmatter records it; the summary prompt
(
prompts/meeting-summary-{de,en}.md) is chosen by/debriefto match. - Summary = NOT here. The worker does no summarizing — it delivers the
naked transcript only. Summary + task-extraction happen in the in-session
/debrief.summarize.pysurvives only as a manual headless fallback;prompts/meeting-summary-{de,en}.mdis the/debriefsummary template. The mechanicalscripts/anchor_transcript.py(per-utterance anchors +.index.tsv, makes a transcript addressable) is owned here but invoked by/debrief's gold path; the interpretive↪evidence-linking stays in-session. - Engine = hybrid (GPU). ASR runs on whisper.cpp large-v3 (Metal) via
asr_whispercpp.py; diarization + the 256-d embeddings run on pyannote/MPS viadiarize_assign.py— the same embedding space the library was built in, so libraries keep matching. A CPU-only fallback stays one env var away:TRANSCRIBE_ENGINE=whisperx. Rationale + measurements:references/architecture.md§ Engine.
Quick operations
Most requests map to a playbook in references/operations.md. The headlines:
Transcribe a meeting — drop the recording into the context's inbox; the
worker auto-runs. Manual: <worker>:~/transcribe-inbox/<ctx>/<ts>/meeting.mp3
touch .READY. No 2-track? A mono/stereo-mix file still works (diarization separates by voice; settracks: singlein the manifest — the sync script'spushdoes this automatically). Always confirm the right context first.
Add a context (bridge-side YAML + remote dirs + recording dir):
- Add
workflow/contexts/<name>.yaml(copy from_template.yaml— fillschema_version,scope,id, and anintegrations.transcriptionblock). Validate:check-jsonschema --schemafile workflow/contexts/_schema.yaml workflow/contexts/<name>.yaml. - Bootstrap the remote dirs + recording folder:
bash skills/meeting-transcription/scripts/add_context.sh <name>. - Deploy: extract + rsync (see
references/deployment.md§ Redeploy). - Point your recorder at
~/Recordings/meetings/<name>/(capture machine).
Add / re-train a speaker — after a meeting is diarized, show the user who each cluster is, then persist the voiceprint:
python bin/speaker_idcard.py --json <inbox>/<ctx>/<ts>/teams_out/teams.json
python bin/apply_speaker_names.py --json <that.json> --out teams-named.json \
--map "SPEAKER_00=Alice,SPEAKER_01=Bob" \
--library speaker-library/<ctx> --save-embeddingsStacking more samples over time sharpens recognition.
Reprocess — delete the bundle's .PROCESSED flag and touch .READY, or
re-run the steps manually. Cached teams.json means re-naming is cheap (no
re-transcription). See operations.md § Reprocess.
Re-summarize only (manual fallback, e.g. after improving a prompt):
python bin/summarize.py --raw <bundle>/transcript-raw.md --out <bundle>/transcript.md --prompt-dir prompts
Bridge to /debrief — scripts/debrief_sync.sh implements the worker
contract (docs/transcription-worker.md):
debrief_sync.sh pull— fetch finished transcripts into the bridge imports dir (prefixed<ctx>-…) where/debriefPhase 1 finds them.debrief_sync.sh push <audio> [ctx]— hand an audio file to the pipeline; the transcript arrives async and is collected on the nextpull./debriefrunspullat the start of Find andpushfor any audio without a transcript. Run it from the machine that can SSH into the worker.
Back up / sync voiceprints — debrief_sync.sh voiceprints pull syncs the
per-context speaker-library/*.npy from the worker into the bridge under
identity/voiceprints/<ctx>/; voiceprints push restores them onto a fresh
worker. These are biometric embeddings (GDPR Art. 9), so
identity/voiceprints/ is user data — it never promotes upstream. Git
tracking is opt-in per context via your .gitignore; an instance handling
customer meetings should route customer voiceprints to that customer's own
repo rather than track them here. An optional weekly launchd job keeps the
backup fresh (scripts/voiceprint_backup.sh +
com.openbridge.voiceprint-backup.plist).
For anything structural (new pipeline stage, model swap, threshold tuning),
read references/operations.md § Extend and references/troubleshooting.md —
and explain the change to the user before deploying, since the worker runs
unattended via launchd.
Hard rules
- Voice libraries are per-context. Never match one context's meeting against another context's voices — that's the whole point of the split. Only the recording user legitimately appears in multiple libraries.
- HF token lives in the worker's keychain (service
hf-token-pyannote) or~/.config/open-bridge/hf-token(chmod 600). Keychain writes over SSH fail (audit session) — use the file fallback when provisioning remotely. - The worker runs unattended — validate script changes (
bash -n, a manual bundle run) before relying on the launchd trigger. - Customer transcripts route to the customer's repo at the
/debriefstage; this pipeline only produces the Markdown. - Voiceprints are biometric data — never commit them to a shared repo, never promote them upstream.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

