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

timecode

Skill1 starsChanged 3 months agoMITView on GitHub

SMPTE timecode arithmetic with drop-frame and non-drop-frame support — convert between timecode and seconds, add/subtract offsets, retime between frame rates, convert DF↔NDF, and infer format from strings or ffprobe/MediaInfo metadata. Use when edit decisions are expressed as HH:MM:SS:FF or HH:MM:SS;FF or when aligning clips at NTSC rates.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 1 is distinctive, and 5 are 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.

  • 5

    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 53
  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 54
  3. Very specific:

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

    line 77
  4. Distinctive:

    Before running any script, treat these two failures differently:

    line 82
  5. Very specific:

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

    line 85
  6. Very specific:

    After extract.py reports e.g.

    line 139

≈ “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.

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

Timecode

Frame-accurate SMPTE timecode math using the eoyilmaz/timecode library. Supports drop-frame (DF) and non-drop-frame (NDF) counting, DF↔NDF conversion, cross-fps retiming, and format detection from delimiters and metadata.

When to use

  • This skill — timecode ↔ seconds, offsets, fps conversion, DF/NDF conversion, format detection, read file timecode tags.
  • video-transformation — once you have seconds-based trim points from timecode math.
  • inspect — container duration and stream frame rates before assuming fps.

Drop-frame vs non-drop-frame

SignalMeaning
HH:MM:SS;FF (semicolon)Drop-frame display — standard for 29.97 / 59.94 NTSC
HH:MM:SS:FF (colon)Non-drop-frame display
NTSC nominal rate (29.97, 59.94, 30000/1001)Library defaults to drop-frame unless --non-drop-frame
MediaInfo Time code settingsDrop frame or Non drop frame

Drop-frame timecode skips frame numbers 00 and 01 at the start of each minute except every tenth minute, so the counter stays aligned with wall-clock time at 29.97 fps. At 01:00:00;00 DF, the NDF equivalent at the same wall-clock is roughly 00:59:56;12 when preserving frame index — use convert_df.py with --preserve realtime to match wall-clock instead.

Gotchas

  • Semicolon matters — do not normalize ; to : before parsing; it changes DF vs NDF meaning.
  • Two “seconds” values — scripts return seconds (linear from frame index), seconds_system (video system grid), and seconds_realtime (wall clock). For ffmpeg -ss on NTSC DF material, prefer seconds_realtime.
  • 29.97 is not 30 — use 29.97 or 30000/1001, not rounded 30, when DF is intended. When mapping file seconds → embedded TC, multiply by the exact rational fps from ffprobe (30000/1001), not the library's integer _int_framerate (30).
  • Embedded start TC — masters often start at embedded timecodes e.g. 00:58:40;00 with episode at 01:00:00;00. Run extract.py to read the tmcd start; use calculate.py or program-master to offset segment boundaries.
  • Missing file timecode — many MP4/H.264 files have no timecode tag; extract.py returns timecode: null — derive from fps + duration instead.
  • Cross-fps retiming — default convert.py preserves wall-clock duration (--preserve realtime). Use --preserve frames only when you need the same frame index at a new rate.

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/to_seconds.py --timecode 00:01:30;15 --fps 29.97

<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 timecode.
  3. Otherwise search standard install locations and confirm the script exists:
NAME=timecode
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/to_seconds.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/to_seconds.py" --timecode 00:01:30;15 --fps 29.97

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, 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 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. ffprobe is required for extract.py; other scripts only need uv.
  • Only escalate sandbox permissions if the error is explicitly a permission denial (e.g. Operation not permitted, Permission denied).

Recipes

Timecode to seconds (29.97 drop-frame)

uv run <skill_directory>/scripts/to_seconds.py --timecode 00:01:30;15 --fps 29.97

Seconds to drop-frame timecode

uv run <skill_directory>/scripts/from_seconds.py --seconds 90.5 --fps 29.97

Add a 5-second slate (wall-clock)

uv run <skill_directory>/scripts/calculate.py --timecode 01:00:00;00 --op add --offset-seconds 5 --fps 29.97

Convert 24fps edit point to 29.97 DF sequence

uv run <skill_directory>/scripts/convert.py --timecode 00:10:00:00 --from-fps 24 --to-fps 29.97

Convert drop-frame to non-drop-frame (same wall-clock)

uv run <skill_directory>/scripts/convert_df.py --timecode 01:00:00;00 --fps 29.97 --to non-drop-frame

Detect format from a timecode string

uv run <skill_directory>/scripts/detect_format.py --timecode 01:00:00;00 --fps 29.97

Analyze ffprobe or MediaInfo JSON

uv run <skill_directory>/scripts/analyze_metadata.py --input /path/to/ffprobe.json

Read embedded timecode from a file

uv run <skill_directory>/scripts/extract.py --input /path/to/clip.mov

Map file seconds to embedded SMPTE (broadcast master)

After extract.py reports e.g. start 00:58:40;00 at 30000/1001:

uv run <skill_directory>/scripts/calculate.py --timecode 00:58:40;00 --op add --offset-seconds 80.013 --fps 30000/1001

For full segment manifests with labels, prefer program-master label_segments.py (auto-detects tmcd).

Troubleshooting

SymptomCauseAction
Off by ~3.6s per hourDF treated as NDF (or vice versa)Check delimiter; run detect_format.py
Frame count off by 1–20-based vs 1-based framesUse frames (0-based) from script output
Invalid timecodeWrong field countUse four fields HH:MM:SS:FF or HH:MM:SS;FF
timecode null in extractNo tag in fileUse from_seconds with known fps
24→29.97 mismatchUsed frame index instead of wall-clockconvert.py defaults to --preserve realtime

Available scripts

ScriptPurpose
scripts/info.pySupported fps, formats, library reference
scripts/to_seconds.pyTimecode → seconds + frames
scripts/from_seconds.pySeconds → timecode
scripts/calculate.pyAdd/subtract offset (wall-clock)
scripts/convert.pyRetime timecode between fps values
scripts/convert_df.pyConvert DF ↔ NDF
scripts/detect_format.pyInfer DF/NDF from string + fps
scripts/analyze_metadata.pyInfer format from ffprobe/MediaInfo JSON
scripts/extract.pyRead timecode tags via ffprobe

See references/DF_NDF.md for drop-frame background.

Acceptance checks (agent must pass before delivery)

  1. Contract: exit 0, ok: true, and data.seconds_realtime / timecode fields present when converting for edits.
  2. Spot-check: DF vs NDF matches source (semicolon vs colon); seconds feed into trim and output duration ≈ (end − start).
  3. On failure: recalculate; do not trim on guessed seconds.

Do not use for

  • Actual video trimming (convert to seconds, then use video-transformation)
  • Legal frame-rate standards beyond SMPTE timecode display math

Related skills

  • video-transformation — apply trim points in seconds
  • inspect — probe frame rates and duration

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.