| name | x-video-transcribe |
| description | Transcribe a video from an X.com (Twitter) URL and return a clean, readable transcript. Use this whenever the user asks to "transcribe", "get the words from", or "give me the transcript of" an X.com video link. Offloads the heavy work to a GitHub Actions runner in the current repo because Claude Code's sandbox blocks x.com — Actions runners reach X.com fine. YouTube is not supported (cloud IPs are blocked by YouTube). |
x-video-transcribe
Pipeline lives in this repo at canonical paths (don't move them — the
workflow trigger and skill both reference these paths):
EXPERIMENTS/x-video-transcribe/transcribe.py — yt-dlp + ffmpeg + faster-whisper (CPU, int8). Writes transcript.txt (timestamped) and transcript-clean.txt (one paragraph).
.github/workflows/x-video-transcribe.yml — runs the pipeline on ubuntu-latest, posts a GitHub issue titled Transcript: <url> with the clean transcript in the body and the timestamped version in a collapsed <details> block.
EXPERIMENTS/x-video-transcribe/url.txt — pushing this file triggers the workflow. The first non-comment line is the URL.
Pre-flight: discover the current repo
The procedure below polls GitHub for the result issue. Before starting,
determine the repo identifier so the polling targets the right place:
git remote get-url origin
Parse the output (e.g. https://github.com/owner/repo.git or
git@github.com:owner/repo.git) into <OWNER> and <REPO>. Use these
values wherever the procedure below says <OWNER> and <REPO> — do not
hardcode any specific repo.
Procedure
When the user supplies a URL:
-
Capture a baseline. Record the highest current issue number via
mcp__github__list_issues with owner=<OWNER>, repo=<REPO>,
state=OPEN, orderBy=CREATED_AT, direction=DESC, perPage=1.
If there are no issues yet, treat the baseline as 0.
-
Write the URL to EXPERIMENTS/x-video-transcribe/url.txt (replace
any existing URL line; keep the # comments). Commit and push to the
current branch:
git add EXPERIMENTS/x-video-transcribe/url.txt
git commit -m "transcribe: <short description of the video>"
git push -u origin HEAD
-
Wait ~4 minutes for the workflow. Use Monitor with
sleep 240 && echo checkpoint=run-done (timeout 360000ms). Don't
poll faster — Actions runs typically take 3–4 minutes (apt install +
pip install + faster-whisper base model download + transcription +
issue post).
-
Read the new issue. Call mcp__github__list_issues again with
the same <OWNER>/<REPO>; find the issue with number > baseline
whose title starts Transcript: . Read its body (already in the
list response, or via mcp__github__issue_read).
-
Present the clean transcript as markdown, broken into paragraphs.
The issue body has the clean version followed by a <details> block
with timestamps — surface only the clean version unless the user asks
for timestamps.
The clean version is one run-on paragraph. Insert paragraph breaks
at natural boundaries to make it readable:
- Speaker topic shifts ("So...", "And then...", "Now let's...").
- Long pauses (visible as larger time gaps in the
<details> block
— use those as hints).
- End of an extended thought or anecdote before the speaker pivots
to the next.
Hard rules:
- Do not change, add, delete, paraphrase, summarize, or "correct"
any words. The text between paragraph breaks must be byte-identical
to a contiguous slice of
transcript-clean.txt.
- Do not introduce headings, bullets, bold, or other structure
beyond paragraph breaks. Plain paragraphs only.
- Don't merge words across breaks or drop trailing/leading spaces.
A paragraph break is just
\n\n between two existing space-
separated word boundaries.
Failure modes and what to do
- YouTube URLs don't work. GitHub-hosted runner IPs are blocked by
YouTube for both audio download (yt-dlp bot wall) and the caption
API (
youtube-transcript-api raises RequestBlocked). Tell the
user this skill doesn't support YouTube and ask for an X.com mirror
or a direct mp4 instead. Don't try to work around it.
Run pipeline fails with yt-dlp 403 on a private or geo-blocked
source. Tell the user; consider a mirror.
- Pipeline succeeds but
Post transcript as GitHub issue fails.
Read the failed-run page via WebFetch. Most likely cause is the
repo's "Workflow permissions" set to read-only — direct the user to
Settings → Actions → General → Workflow permissions and enable
"Read and write permissions". The transcript is still in the run's job
summary and as an uploaded artifact.
- Pipeline fails for any reason — read the diagnostic issue. The
workflow opens a
Transcribe FAILED: <url> issue with the last 120
lines of run.log when the pipeline fails. Use
mcp__github__list_issues to find it and surface the error to the
user.
- Workflow doesn't trigger. Verify the changed path is exactly
EXPERIMENTS/x-video-transcribe/url.txt. The workflow's on.push.paths
is narrow.
- Multiple URLs in one session. Repeat the procedure per URL — the
workflow handles one URL per run.
Notes
- Default model is
base (~150 MB download on the runner; balanced
quality/speed for short clips). For longer/higher-stakes clips, the
user can pick small or medium via Actions UI → "Run workflow";
the push-triggered path always uses base.
transcript-clean.txt joins all segments with single spaces. The
paragraph-break rules are spelled out in step 5 of the procedure
above — follow them strictly. No word changes, ever.
- The pipeline runs locally too
(
python EXPERIMENTS/x-video-transcribe/transcribe.py <url>) when the
environment can reach the source — but Claude Code's web sandbox
blocks x.com, so prefer the Actions path there.