Export transcripts and AI summaries from plaud.ai recordings.
Use when user mentions Plaud, plaud.ai, meeting recordings export,
or wants to download/sync transcripts from their Plaud device.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Export transcripts and AI summaries from plaud.ai recordings.
Use when user mentions Plaud, plaud.ai, meeting recordings export,
or wants to download/sync transcripts from their Plaud device.
allowed-tools
["Bash","Write","Read","AskUserQuestion"]
Plaud Connector: Export transcripts from plaud.ai
Download transcripts, speaker-labeled segments, and AI summaries from a Plaud account. Works with the unofficial plaud.ai web API.
First: get credentials
Before doing anything, ask the user for their Plaud credentials. They need one of:
Bearer token (most common, required for Google SSO users)
Email + password (for users with a regular Plaud account)
If they don't know how to get a token, walk them through it:
Open DevTools (Cmd+Option+I on Mac, F12 on Windows) -> Network tab
Click any recording to trigger an API request
Find a request to api.plaud.ai, click it, copy the full Authorization header value
EU accounts use a different API host (https://api-euc1.plaud.ai). Ask the user if they're on an EU account, or check if their token came from api-euc1.plaud.ai in the network tab.
Once you have credentials, set them as environment variables before running any scripts:
export PLAUD_TOKEN="bearer eyJ..."# OR
PLAUD_EMAIL=
PLAUD_PASSWORD=
PLAUD_API_BASE=
export
"user@example.com"
export
"password"
# EU accounts only:
export
"https://api-euc1.plaud.ai"
Two modes of operation
Mode A: CLI (if plaud-connector is installed)
Check first:
which plaud 2>/dev/null && echo"CLI available" || echo"CLI not installed"
If installed, these commands do everything:
plaud sync -o output # full sync: generate missing transcripts + download all
plaud list # list all recordings
plaud generate --dry-run # preview what needs transcription
plaud generate --wait# trigger transcription and wait
plaud download -o output # download transcripts as JSON + Markdown
OUTPUT = "output"
recordings = list_recordings()
tags = {t["id"]: t["name"] for t in get_tags()}
file_ids = [r["id"] for r in recordings]
exported, skipped = 0, 0for i inrange(0, len(file_ids), 20):
for rec in get_details(file_ids[i:i+20]):
tag_ids = rec.get("filetag_id_list") or []
folder = next((tags[t] for t in tag_ids if t in tags), "Unsorted")
dt = datetime.fromtimestamp(rec["start_time"] / 1000, tz=timezone.utc)
safe = re.sub(r'[<>:"/\\|?*]', '-', rec["filename"])
stem = f"{dt:%Y-%m-%d}_{safe}"
out = Path(OUTPUT) / folder
out.mkdir(parents=True, exist_ok=True)
if (out / f"{stem}.json").exists():
skipped += 1continue
transcript = rec.get("trans_result") or []
summary = parse_ai_content(rec.get("ai_content"))
dur_ms = rec.get("duration", 0)
(out / f"{stem}.json").write_text(json.dumps({
"id": rec["id"], "filename": rec["filename"],
"start_time": rec["start_time"], "duration_ms": dur_ms,
"transcript": [{"speaker": s.get("speaker", "?"), "content": s.get("content", ""),
"start_time": s.get("start_time", 0), "end_time": s.get("end_time", 0)}
for s in transcript],
"summary": summary,
}, indent=2, ensure_ascii=False))
lines = [f"# {rec['filename']}", "", f"**Date:** {dt:%Y-%m-%d %H:%M UTC}",
f"**Duration:** {fmt_duration(dur_ms)}", "", "## Transcript", ""]
for s in transcript:
ts = fmt_duration(s.get("start_time", 0))
lines += [f"**{s.get('speaker', '?')}** [{ts}]: {s.get('content', '')}", ""]
lines += ["## Summary", "", summary, ""]
(out / f"{stem}.md").write_text("\n".join(lines))
print(f" + {rec['filename']}")
exported += 1print(f"\nDone! {exported} exported, {skipped} skipped (already exist)")
Generate missing transcripts and wait
recordings = list_recordings()
missing = [r for r in recordings ifnot r.get("is_trans") and r.get("duration", 0) // 1000 >= 10]
ifnot missing:
print("All recordings already have transcripts!")
else:
print(f"{len(missing)} recordings without transcripts:\n")
for r in missing:
dur = r.get("duration", 0) // 1000print(f" {dur:>5}s {r.get('filename', '?')}")
start_transcription(r["id"])
print(f"\nTriggered {len(missing)} transcriptions. Polling...")
pending = {r["id"]: r.get("filename", "?") for r in missing}
while pending:
time.sleep(15)
for fid inlist(pending):
if poll_transcription(fid).get("status") == 1:
print(f" Done: {pending.pop(fid)}")
if pending:
print(f" Waiting on {len(pending)}...")
print("\nAll transcriptions complete!")
EU accounts use https://api-euc1.plaud.ai instead of https://api.plaud.ai
Tokens expire. If you get 401 errors, the user needs to grab a fresh token from their browser.
Triggering transcription is two steps: PATCH sets config, then POST to /ai/transsumm with is_reload=1 starts the job. PATCH alone does nothing.
ai_content field can be plain markdown, or JSON containing {"markdown": "..."}, {"content": {"markdown": "..."}}, or {"summary": "..."}. The parse_ai_content helper handles all variants.
Some transcript segments may lack speaker or content keys. Always use .get() with defaults.
Don't send more than 20 IDs at once to /file/list.
All GET requests need a random r= query parameter for cache busting.