agentleFS
timelapsetechtimelapsetech/mediaskills/.agents/skills/subtitles/SKILL.md

subtitles

Skill1 starsChanged 3 months agoMITView on GitHub

Convert, shift, extract, and burn subtitle files (SRT/WebVTT). Use when you already have caption text or embedded subtitle tracks and need format conversion, sync adjustment, extraction from containers, or hardcoded captions on video.

6 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

6 rules. 0 are common, 2 are distinctive, and 4 are very specific to this project.

  • 0

    Common

    Most of the 4 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If your tools showed a filesystem path when loading this SKILL.md, strip SKILL.md and use that folder.

    line 43
  2. Very specific:

    If you already ran another mediaskills script (for example .../audio/scripts/extract.py), this skill is a sibling of that folder: same …

    line 44
  3. Very specific:

    Prefer absolute paths for --input / --output when cwd is uncertain.

    line 67
  4. Distinctive:

    Before running any script, treat these two failures differently:

    line 72
  5. Very specific:

    Only escalate sandbox permissions if the error is explicitly a permission denial (e.g.

    line 75
  6. Distinctive:

    Use negative values if captions are late relative to dialogue.

    line 91

“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Subtitles

Subtitle file operations and burn-in. Use this skill when you need to work with caption files or embedded tracks — not automatic speech recognition (use speech-captions for that).

When to use

  • This skill — SRT ↔ VTT conversion, sync offset, extract 0:s:0 subtitle stream, burn SRT into video.
  • speech-captions — generate captions from spoken audio when no subtitle track exists.
  • video-transformation — mux soft subtitles into a container, transcode, or re-wrap streams without burning.
  • inspect — list streams and confirm a subtitle track exists before extract.py.

Gotchas

  • Extract maps first subtitle stream only — extract.py uses -map 0:s:0. Multi-language containers may need manual ffmpeg maps for other indices.
  • Burn re-encodes video — burn.py overlays PNG captions and outputs H.264 (libx264, CRF 20). Audio is stream-copied when present. Expect generation time to scale with cue count.
  • Burn expects SRT — WebVTT must be converted with convert.py first. VTT timing and styling tags are not preserved on burn.
  • Shift clamps to zero — negative offsets clamp cue starts at 0.0; very negative shifts can collapse short cues to a 0.1 s minimum duration.
  • No libass dependency — burn uses Pillow text rendering with a simple bottom-centered box. Complex ASS styling (fonts, positioning, karaoke) is not supported.
  • SRT vs VTT on shift — output format follows input extension (.srt or .vtt). Convert first if you need a different target format.

Running scripts

This skill's scripts live in scripts/ alongside this file. Before running any script, resolve its absolute path from this skill's own directory — do not assume the shell cwd is the skill folder, the repo root, or the workspace. Stay in the workspace (so media paths resolve) and pass the absolute script path to uv run:

uv run <skill_directory>/scripts/convert.py --input captions.srt --format vtt

<skill_directory> is a placeholder. Never pass those angle brackets to the shell — the command will fail. Replace it with a real absolute directory before invoking uv run.

How to get that directory (do this yourself; do not ask the user first; do not skip the skill):

  1. If your tools showed a filesystem path when loading this SKILL.md, strip SKILL.md and use that folder.
  2. If you already ran another mediaskills script (for example .../audio/scripts/extract.py), this skill is a sibling of that folder: same parent, directory name subtitles.
  3. Otherwise search standard install locations and confirm the script exists:
NAME=subtitles
for d in \
  "$HOME/.agents/skills/$NAME" \
  "$HOME/.cursor/skills/$NAME" \
  "$HOME/.codex/skills/$NAME" \
  "$HOME/.claude/skills/$NAME" \
  "$PWD/.agents/skills/$NAME" \
  "$PWD/.cursor/skills/$NAME" \
  "$PWD/skills/$NAME"
do
  if [ -f "$d/SKILL.md" ] && [ -e "$d/scripts/convert.py" ]; then
    SKILL_DIR=$(cd "$d" && pwd)
    break
  fi
done
[ -n "$SKILL_DIR" ] || { echo "mediaskills: $NAME not found" >&2; exit 1; }
uv run "$SKILL_DIR/scripts/convert.py" --input captions.srt --format vtt

Prefer absolute paths for --input / --output when cwd is uncertain.

Missing binaries vs permissions

Before running any script, treat these two failures differently:

  • If a required binary (uv, ffmpeg, ffprobe) reports No such file or directory or command not found: this is a missing or unreachable binary, not a permissions issue. Escalating sandbox permissions will not fix it. Run command -v uv, command -v ffmpeg, and command -v ffprobe to see whether they resolve at all. If not, install or re-link them (install-media-tools doctor/install) rather than retrying with wider permissions.
  • Only escalate sandbox permissions if the error is explicitly a permission denial (e.g. Operation not permitted, Permission denied).

Recipes

Convert SRT to WebVTT for HTML5 players

uv run <skill_directory>/scripts/convert.py --input captions.srt --format vtt --output captions.vtt

Fix captions that start 1.5 seconds early

uv run <skill_directory>/scripts/shift.py --input captions.srt --offset-seconds 1.5

Use negative values if captions are late relative to dialogue.

Extract embedded subtitles from MKV/MP4

uv run <skill_directory>/scripts/extract.py --input movie.mkv --output extracted.srt

Fails clearly when no subtitle stream exists — fall back to speech-captions transcribe.

Hardcode captions for social delivery

uv run <skill_directory>/scripts/burn.py --input clip.mp4 --subtitle captions.srt --output clip_subbed.mp4

Each cue becomes a timed full-frame PNG overlay; plan for longer encodes on caption-heavy videos.

Typical workflow after ASR

  1. speech-captions transcribe → SRT
  2. subtitles shift — fix sync
  3. subtitles convert — VTT for web, keep SRT for editors
  4. subtitles burn — optional deliverable without player subtitle support

Troubleshooting

Error / symptomLikely causeAction
No embedded subtitle track foundContainer has no s: streamUse speech-captions transcribe or mux subs first
No subtitle cues foundEmpty or malformed fileValidate SRT/VTT structure; re-export from editor
ffmpeg failed on burnOverlay filter error, corrupt videoProbe with inspect; test shorter clip
Wrong language track extractedNot stream 0:s:0Extract manually with ffmpeg -map 0:s:N
Blurry burned textSmall output resolutionUse higher-res source; burn scales font to frame height

Available scripts

ScriptPurpose
scripts/convert.pySRT ↔ WebVTT
scripts/shift.pyOffset all cue timings
scripts/extract.pyPull embedded subtitle track to SRT
scripts/burn.pyHardcode SRT captions into video

Acceptance checks (agent must pass before delivery)

  1. Contract: exit 0, ok: true, every output_paths entry exists and is non-empty.
  2. Spot-check: after shift.py, first/last cue times moved by the requested offset; after burn.py, re-inspect and visually sample burned frames.
  3. On failure: fix timing/path and retry; do not deliver burn-in without opening at least one frame.

Do not use for

  • Automatic speech recognition (use speech-captions)
  • FCC/SCC compliance validation (use captions-compliance)
  • On-screen text / graphics QC (use vision-analysis)

Related skills

  • speech-captions — automatic transcription to SRT/VTT
  • video-transformation — trim, transcode, mux without burning
  • inspect — stream and duration metadata
  • install-media-tools — install ffmpeg/ffprobe

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.