10 KiB
name: fireflies-relanguage description: Fix a wrong-language Fireflies transcript on a meeting you don't own (can't hit Reprocess yourself) by re-uploading its audio under the correct language via the Fireflies API, recovering real speaker names into the result with transcript-speaker-fill, then deleting the duplicate meeting. Use when the user has a link to a Fireflies recording they aren't the host/owner of, the transcript is in the wrong language, and they want a corrected transcript without waiting for the owner to act or leaving a duplicate meeting behind. Trigger phrases: "I'm not the owner of this meeting", "can't reprocess this transcript", "fix this Fireflies transcript without the owner", "re-transcribe a shared meeting".
Fireflies relanguage skill
Purpose
Fireflies' own "Update Language + Reprocess" fix only works for the meeting's
host/owner (see guide.fireflies.ai docs). If you were just sent a link to
someone else's recording and it came out in the wrong language, you have no
UI path to fix it and can't wait for the owner. This skill routes around
that: pull the meeting's audio via the API, re-upload it as a new meeting
under your own account with the correct language forced, recover the
original's real speaker names into the new, correctly-transcribed text using
the [transcript-speaker-fill] skill,
then delete the duplicate meeting the re-upload created.
Before you start: real constraints, not hypothetical ones
This may simply not be possible on your account. audio_url/video_url
on a Fireflies transcript require a Pro+ plan, and it is undocumented whether
they populate at all for a meeting merely shared with you rather than
owned by you. Michał's own wiki notes
record hitting exactly this wall before (no Pro seat → transcript download
tooling broke). Step 1 below (fetch) is also the diagnostic: if it prints
the "audio_url is null" warning, stop here — this workflow cannot proceed
without one of the workarounds it suggests (a Pro+ seat's API key, the actual
owner reprocessing it, or you manually downloading the audio via the web UI
and hosting it at some public HTTPS URL yourself).
Every re-upload consumes real transcription quota/minutes on the account whose API key you use, same as any other Fireflies upload — this isn't free just because it's automated. Deleting a transcript is irreversible. Don't run this on a meeting you actually might need to keep two copies of, and don't skip the confirmation gates below.
Also worth knowing up front: the Fireflies API has thin rate limits (Free:
50 requests/day, Pro: 500/day, Business/Enterprise: 60/min) and
deleteTranscript specifically is capped at 10/min. This workflow only
needs a handful of calls plus some polling, but don't loop the wait step
aggressively.
Requirements
FIREFLIES_API_KEYset in the environment. Get one from the Fireflies web app under Settings > API. The script exits with this exact instruction if it's missing — don't hardcode the key anywhere.- The
transcript-speaker-fillskill installed alongside this one (it is, in this repo) — this skill hands off the actual name-recovery merge to it rather than duplicating that logic.
Workflow
Resolve <skill-dir> to this skill's own directory throughout.
1. Fetch the original (broken-language) transcript
python3 "<skill-dir>/scripts/fireflies_client.py" fetch --ref "<link-or-id-the-user-gave-you>" --out original.md
Accepts a bare transcript id or a full share link like
https://app.fireflies.ai/view/Some-Title::abcDEF123. Writes original.md
(real speaker names, garbled text — the shape transcript-speaker-fill
expects for its "broken" input) and original.md.meta.json (id, title,
audio_url, etc., needed by later steps).
Check the printed output for the audio_url warning before continuing. If it's null, stop and follow the guidance it prints instead of proceeding to step 2 — do not attempt step 2 anyway "just to see."
2. Confirm the target language with the user
Don't guess the correct language from context alone unless it's unambiguous
(e.g. the user already told you). Ask if unclear. Use the language code
Fireflies expects — check
Learn about Fireflies supported languages
for the exact code if you're not sure it matches (e.g. en, pl, es).
3. Re-upload the audio under the correct language
python3 "<skill-dir>/scripts/fireflies_client.py" upload --meta original.md.meta.json --language <code>
This calls uploadAudio with custom_language set, tagging the new
meeting's title with [relang:<original-id>] so it can be found
unambiguously afterward (override with --title if you want a cleaner
name, but then pass that exact same string to step 4). Note the exact title
printed — you need it verbatim for the next step.
4. Wait for the re-upload to finish processing
python3 "<skill-dir>/scripts/fireflies_client.py" wait --title "<exact title from step 3>"
Polls every 30s (default) up to 15 minutes (default) for a transcript with
that exact title to appear with content. Long recordings can take longer —
if it times out, just re-run wait again rather than assuming failure.
Prints the new transcript's id once ready.
5. Fetch the new (correct-language) transcript
python3 "<skill-dir>/scripts/fireflies_client.py" fetch --ref "<id from step 4>" --out new.md
This one should come back with correct text but generic Speaker 1,
Speaker 2, ... labels (no calendar/roster context on a bare re-upload) —
exactly the gap transcript-speaker-fill closes.
6. Recover real speaker names
Hand off to the transcript-speaker-fill skill exactly per its own
SKILL.md, using original.md and new.md as the two inputs — dry run
first, present the resolution report, get the user's confirmation/manual
overrides, then --apply. Do not skip its confirmation gate just because
you're mid-pipeline; it's exactly as load-bearing here as when invoked
standalone.
Also pass --recording-url "https://app.fireflies.ai/view/<id from step 4>"
on every fill_speakers.py call in this handoff (both the dry-run and the
--apply run) — the bare-id form of the URL works without needing to
slug-encode the title, and gives the user a direct link to a recording they
definitely have full access to (they own the re-uploaded meeting) right
next to every label's example lines, for the spot-check
transcript-speaker-fill asks them to do before confirming. Use the new
transcript's id, not the original's — do this before step 8's cleanup,
while that meeting (and its recording) still exists.
7. Ask where to save the corrected transcript
Before touching the duplicate meeting, ask the user where the final
--apply'd output (from step 6) should end up — don't default to leaving
it in a scratch/temp location without asking. Common answers: a specific
path they name, this project's own tmp/ (if this skill is being run from
inside a Cascade Knowledge Base repo like this one — gitignored, agent-
managed), or raw/inbox/ if they want it ingested into a wiki afterward.
Move (don't copy) the file there once they've told you.
8. Delete the duplicate meeting — only after explicit confirmation
Once the user has confirmed the merged transcript (from step 6) looks right and it's been saved wherever they wanted (step 7), delete the meeting the re-upload created (not the original — you don't own that one anyway, and couldn't delete it if you tried):
python3 "<skill-dir>/scripts/fireflies_client.py" delete --id <id from step 4> --yes
The script refuses to run without --yes. Never pass --yes without the
user having explicitly confirmed they're ready — this is irreversible and
removes a real meeting from their Fireflies account. Show them the printed
{id, title, date, duration} of what was deleted as final confirmation.
Failure modes and what they mean
fetchon the original prints the audio_url warning — see "Before you start" above. This is the expected failure mode when the API key's account isn't Pro+, or when a merely-shared meeting doesn't expose audio via the API. Not a bug to work around silently.uploadmutation succeeds (success: true) butwaitnever finds it — the title match is exact-string, so a--titleoverride that doesn't exactly match what you pass towaitwill never resolve; double check you used the identical string in both commands.waittimes out — normal for long recordings. Re-run it; don't assume the upload failed.- Rate limit errors (
too_many_requests) — the error message includesretryAfter; wait that long before retrying, especially on a Free-tier key (50 requests/day total). deletefails withrequire_elevated_privilege— you're trying to delete a transcript you don't own (e.g. you accidentally passed the original id instead of the new one from step 4). Only the re-uploaded meeting is yours to delete.
Edge cases
- Multiple speakers with a name-recovery gap (new transcript has more
distinct
Speaker Nlabels than the original has real names) — this istranscript-speaker-fill's "roster gap" warning, not something this skill's own steps can fix; it means someone's voice wasn't distinctly captured with a real name in the original either. - Original meeting has
video_urlbut notaudio_url—uploadonly accepts--audio-url; there's no video re-upload path here. If you truly only have video access, extract audio from it yourself first and host that as a public URL, then pass it via--audio-url. - The user wants the corrected transcript ingested into this repo's
wiki, not just saved as a file — step 7 already asks where to save it;
if the answer is "ingest it," save it to
raw/inbox/there, then run the normal "Ingest" workflow from the rootCLAUDE.mdon it after step 8's cleanup (the duplicate meeting is Fireflies-side bookkeeping, unrelated to whether the wiki ingest has happened yet).