mcpbeat Sign in

Cassette Video Edit Agent Skill

Edit, trim, cut, caption, subtitle, reframe, combine, add background music to, or export video, audio, and image files through Cassette. Use this skill whenever the user asks to change, preview, or render a media file in the project — even if they never say "Cassette" or name a tool — for example "trim the intro off demo.mp4", "add subtitles to this clip", "make me a 30-second cut with music", "why is there dead air at the start". Drives the local Oh My Cassette stdio MCP tools in Codex or Claude as one multi-turn conversation with the Cassette agent, with per-turn timeline previews, guided questions, and rendering only on explicit export.

4k tokens
context cost
the whole folder, loaded on every use
3
files
instructions only
0
copies elsewhere
how many repositories repackaged it
139
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/Cassette-Editor/oh-my-cassette --skill cassette-video-edit

The instruction itself

11 sections, as written by the author

Oh My Cassette local workflow

Cassette edits the media; you carry the messages. The cassette MCP server is a local stdio child

process that opens no port and talks directly to the separate Cassette backend. Do not start or

depend on the repository's FastAPI web-demo server for this workflow — that is a different adapter.

Two details live outside this file to keep it short. Read them when they apply:

  • references/auth.md — any auth_* error, or the user is not signed in on this machine.
  • references/previews.md — showing a timeline, contact sheet, or storyboard, and the plan-review

pause.

Courier doctrine

You are a courier between the user and the Cassette agent, not an editor or a brief writer.

  • Pass the user's editing words to cassette_run_job as message VERBATIM. Never rewrite,

optimize, summarize, translate, or expand them. The agent is the creative brain and it reads the

session's uploaded media itself, so a "helpfully" rewritten instruction only throws away detail

the user chose and the agent could have used.

  • Relay the agent's questions and plans back verbatim too. You add exactly three things: the

timeline delta, the version numbers, and any validated artifact path.

  • Do not call cassette_make_prompt. It is a legacy brief builder, kept only so the tool-name set

stays stable.

  • Never ask upfront about model, thinking level, optimization, or BGM. The defaults match the web

editor, and front-loading configuration questions is precisely the friction this workflow exists

to remove.

Safety and identity

  • Only files inside the active host project roots or explicitly configured media roots are

ingestible. On source_path_not_allowed, ask the user to move the file into the project or to

rerun the private setup command with --allowed-root. Do not go hunting for a path that works.

  • Keep the returned session_id and job_id. Sessions are isolated by default; hand one to

another host only when the user deliberately asks for a Codex or Claude handoff.

  • Use only paths and resource links returned in artifacts. Never invent an export path or ask the

MCP runtime to expose another local file.

The editing loop

One session is one continuous conversation on one persistent agent thread. The agent remembers

every previous turn, so a follow-up like "make that title bigger" needs no context restating.

  • Call cassette_ingest_media once per source asset. Omit session_id on the first call so the

runtime generates one, then reuse the returned value everywhere.

  • Call cassette_list_assets and confirm the intended files are present.
  • For each editing request, call cassette_run_job with the user's verbatim message and the same

session_id.

  • Relay what comes back (see routing below), then wait for the user's next instruction.
  • Pass export=true only on a turn where the user expresses finish or export intent.

If the user explicitly asks for background music, cassette_match_exact_bgm takes a concrete

title/artist, jamendo_music_matcher a configured mood/genre, and cassette_match_bgm is the Free

To Use fallback. Then continue the conversation as normal.

One turn, end to end

User:  trim the dead air off the front of demo.mp4 and add a title card

You:   cassette_run_job(session_id="s_41k",
                        message="trim the dead air off the front of demo.mp4 and add a title card")
       → phase="succeeded"
         timeline_delta="v6→v9: trimmed 3.2s from head; added title card 0.0–2.5s"
         quality.timeline_ctl=<digest>, artifacts=[contact sheet]

       "v6→v9: trimmed 3.2s off the head and added a 2.5s title card. Nothing is rendered
        yet — want to see the contact sheet, or should I export?"

User:  export it

You:   cassette_run_job(session_id="s_41k", message="export it", export=true)
       → phase="review_required"
       cassette_review_completion(job_id="j_88", decision="export",
                                  reason="user asked to export; trim and title card both landed")
       → phase="exported", artifacts=[…/exports/j_88/demo_cut.mp4]

Note what did not happen: no status polling, no rewriting of the user's words, and no rendering

until the user asked for it.

Routing on typed state

Treat the structured phase and next_action fields as authoritative. Do not decide routing,

progress, or completion from keywords in prose.

cassette_run_job is the wait. It returns when the turn is settled, streaming MCP progress

notifications while the agent works, and answers with a terminal phase. One call per user turn.

| phase | what it means | what you do |

|---|---|---|

| succeeded | edit committed, nothing rendered | relay data.job.timeline_delta + the digest, continue the conversation |

| needs_user | the agent asked a question | relay it, then cassette_answer_question(job_id, response) |

| review_required | export turn awaiting judgement | evaluate the result, then cassette_review_completion(job_id, decision, reason) — only decision=export renders |

| exported | the render finished | present the validated artifacts and their resource links |

| failed / cancelled / timed_out | terminal error | report the structured error and its runtime-derived next action |

| running / exporting | the call detached (wait=false) or was interrupted | see recovery below |

Where the per-turn data lives

The envelope itself is thin — ok, phase, next_action, session_id, job_id, artifacts,

data. Everything describing the turn hangs off data.job:

| what you want | where it is |

|---|---|

| what changed this turn | data.job.timeline_delta |

| the agent's plan checkpoints | data.job.plan_progress |

| the text digest of the timeline | data.job.quality.timeline_ctl |

| the contact sheet, when one exists | data.job.quality.contact_sheet_uri |

| measurements of the rendered file | data.job.quality.export_qc (on exported only) |

| resource links and export paths | artifacts[] — top level, not under data |

Reading timeline_delta or quality off the top of the envelope yields nothing at all, which

looks exactly like a turn that produced no preview. The digest is there on every settled turn; the

contact sheet is best-effort and is simply absent when a sheet could not be built from the current

frames, so check before offering to show one.

cassette_timeline answers in its own shape — data.ctl plus data.version, data.clip_count,

and data.duration_sec — not under data.job. Same digest, different path from the run envelope.

cassette_review_completion takes reason as a required argument alongside job_id and

decision (plus an optional summary) — omitting it fails the call with validation_error

before anything renders. Write the judgement you actually made, in one line: it is the record of

why this edit was considered finished, and it is the only place that judgement is captured.

On exported, the runtime has already measured the finished file into quality.export_qc

(duration, fps, resolution, audio span, black_segments, and audio_levels with

mean_dbfs/peak_dbfs). Read those numbers instead of probing the export yourself, and raise them

with the user only when a field contradicts what they asked for.

A thread_busy error means a run is already live on this session's thread, often started from an

open editor tab. Wait and retry rather than starting a second job.

On hosts that support MCP elicitation, the runtime may collect a needs_user answer itself and

return the already-resumed result. Trust the returned phase and do not answer twice.

Recovery, not polling

cassette_job_status re-attaches to a job whose call did not return — the host restarted, the call

was cancelled, or the turn was deliberately started with wait=false. Call it once, act on the

phase it reports, and stop. A settled turn never needs it.

job_id is the durable handle for that recovery: jobs persist private thread and interrupt

metadata on disk, so a paused turn resumes after a Codex or Claude restart.

A long edit does not need managing. Hosts that background long tool calls (Claude Code moves any

call past two minutes into a background task) keep the session usable while the turn runs and

deliver the result when it lands.

Timeline grounding

  • Every user-visible statement about project state comes from cassette_timeline or the envelope's

timeline_delta, never from memory. Name the version: "v42→v43: trimmed the intro to 4.0s."

  • Prefer relaying timeline_delta and plan_progress over re-describing the whole timeline.
  • The runtime hands out no editor deep link, and you must not construct or offer one. That URL is a

bearer capability: the backend binds no owner to a session, so any signed-in account that sees it

can open the project and run edits on the thread. Previews go through the digest, the contact

sheet, and the export instead.

  • Route essentially everything through cassette_run_job. cassette_edit is an opt-in fast lane

for small named changes (trim, retime, text, delete, undo) that stays **disabled unless the

operator sets CASSETTE_DIRECT_EDIT=1** — no shipping host config sets it, so assume it is off

and reach for it only once a cassette_edit call has actually succeeded in this session or the

user says they enabled it. When you do use it, read cassette_timeline first and pass

expected_version from that read; a stale_timeline error means re-read and retry.

Model, thinking level, and updates

  • cassette_config(session_id) shows the current choice and the available options; adding

model=… / thinking_level=… changes them. It accepts a product id (openai/gpt-5.6-luna) or a

label ("GPT-5.6 Luna").

  • The selectable models are GPT-5.6 Luna and GPT-5.4 Mini. Thinking levels are off, minimal,

low, medium, high, and xhigh. The defaults — GPT-5.6 Luna, low thinking — match the web

editor. The preference persists for the session and applies from the next turn, the same

semantics as switching model between turns in the web editor. Change it only when the user asks,

and confirm in one line.

  • The MCP instructions carry an UPDATE AVAILABLE: line when a newer Oh My Cassette release

exists. Mention it once per session with both version numbers and offer the command it names. Run

that command only after the user explicitly agrees, and never re-offer in the same session — it

replaces the plugin on disk, so tell the user the new version applies after the host reloads

(/reload-plugins in Claude Code, a new task in Codex). Never fabricate a version or an update

command; if the line is absent, the install is current and the subject does not come up.

Cancellation and handoff

  • Call cassette_cancel_job only when the user asks to stop the edit.
  • For a deliberate host handoff, provide the exact session_id and active job_id; the receiving

host should begin with cassette_job_status rather than re-ingesting or starting a duplicate job.

  • Exported files remain under the shared Oh My Cassette data directory. Prefer the returned resource

link or file URI over relocating the artifact.

Other skills for the same job

different authors, same section of the catalogue
Canvas Design
by anthropics
vendor ×13

Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.

1388k tokens
Algorithmic Art
by anthropics
vendor ×10

Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.

15k tokens scripts
Image Enhancer
by frostant
×6

Improves the quality of images, especially screenshots, by enhancing resolution, sharpness, and clarity. Perfect for preparing images for presentations, documentation, or social media posts.

635 tokens
Video Downloader
by CommandCodeAI
×4

Downloads videos from YouTube and other platforms for offline viewing, editing, or archival. Handles various formats and quality options.

671 tokens
Histolab
by christophacham
×3

Lightweight WSI tile extraction and preprocessing. Use for basic slide processing tissue detection, tile extraction, stain normalization for H&E images. Best for simple pipelines, dataset preparation, quick tile-based analysis. For advanced spatial proteomics, multiplexed imaging, or deep learning pipelines use pathml.

18k tokens
Omero Integration
by christophacham
×3

Microscopy data management platform. Access images via Python, retrieve datasets, analyze pixels, manage ROIs/annotations, batch processing, for high-content screening and microscopy workflows.

32k tokens
Pydicom
by christophacham
×3

Python library for working with DICOM (Digital Imaging and Communications in Medicine) files. Use this skill when reading, writing, or modifying medical imaging data in DICOM format, extracting pixel data from medical images (CT, MRI, X-ray, ultrasound), anonymizing DICOM files, working with DICOM metadata and tags, converting DICOM images to other formats, handling compressed DICOM data, or processing medical imaging datasets. Applies to tasks involving medical image analysis, PACS systems, radiology workflows, and healthcare imaging applications.

13k tokens scripts
Transformers
by christophacham
×3

This skill should be used when working with pre-trained transformer models for natural language processing, computer vision, audio, or multimodal tasks. Use for text generation, classification, question answering, translation, summarization, image classification, object detection, speech recognition, and fine-tuning models on custom datasets.

13k tokens

How to use it

Copy the folder

Take cassette-editor/cassette-video-edit from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.