oh-my-cassette
by akanemartins
README.md
<p align="center">
<img src="assets/banner.jpg" width="80%" alt="Oh My Cassette banner" />
</p>
<h1 align="center">
Oh My <a href="https://trycassette.online/">Cassette</a>: Chat Your Raw Clips Into a Finished Cut
</h1>
<p align="center">
<a href="https://github.com/Cassette-Editor/oh-my-cassette/releases">
<img src="https://img.shields.io/github/v/release/Cassette-Editor/oh-my-cassette?style=flat-square&color=blue" alt="Version">
</a>
<a href="https://github.com/Cassette-Editor/oh-my-cassette/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/Cassette-Editor/oh-my-cassette?style=flat-square" alt="License">
</a>
<a href="https://github.com/Cassette-Editor/oh-my-cassette/stargazers">
<img src="https://img.shields.io/github/stars/Cassette-Editor/oh-my-cassette?style=flat-square&logo=github" alt="Stars">
</a>
<a href="https://github.com/Cassette-Editor/oh-my-cassette/fork">
<img src="https://img.shields.io/github/forks/Cassette-Editor/oh-my-cassette?style=flat-square&logo=github" alt="Forks">
</a>
<img src="https://img.shields.io/badge/Python-3.11--3.13-purple.svg" alt="Python">
<a href="https://github.com/Cassette-Editor/oh-my-cassette/actions/workflows/ci.yml">
<img src="https://img.shields.io/github/actions/workflow/status/Cassette-Editor/oh-my-cassette/ci.yml?branch=main&style=flat-square&label=CI" alt="CI">
</a>
<a href="https://trycassette.online">
<img src="https://img.shields.io/badge/Cassette-Compatible-1f6feb?style=flat-square&logo=data%3Aimage%2Fwebp%3Bbase64%2CUklGRhgHAABXRUJQVlA4WAoAAAAQAAAANwAANwAAQUxQSMkCAAABkIVt29lI75hr27Yx9tq2bdu2bdu2bdt23e4kfQ86TZN%2FeRgRE4DfcIX9Oyr%2BCuE7ZFJeX0a0oK0SE7SsKyNSmTU2KjQvKypKsTVWumhcVkSEIsuNVNG4KJ9WOabqqPK3yVm1yDnjCzX8OCWLWhknfabG7yZkUiPz5HcU8HWvVK5kGPuegj4blEqJV%2B9XFPhpZ09nmU0UWi7gLKteLHtRBTqx5CIKvotl%2B%2B%2F2tNfgd7%2FC6%2BHpgCwTv4r2YVQGJJhn2meRPo3PCoU5lhhE%2BT41F1wsssoswo%2FphaFiycVGrfQLC0Dl0ssNqugSMq0uAQ0LrbQlJLlkXVUSGgdttjnISr6T8TuCIGDQVom0FVa0PxSCRu2Ltwcp2pdOFLe2P1nKWX6LXnc7nRhR53mvuaezEpyU58d0AdwaRG1mX18oDOcQLH%2FqizEjUmpSZidHrXuarXmggmAOQ9IYb78HnK1BwVVm2%2BTUG%2BON31IryGgZCwBh8bzqBZ9EqhSNvkauB7Zwb2ko9Dh8PnFMfowmdVkDDjzq5eVS7lm25S1aSKuBHS%2Fdsk%2FP4QylDA%2BstxOfJO2xOWWZ892VpR3zlXvyIqO0Btj2bZnZmFMBYh9xS7YfJEcmM02rLVeFl7uTNPlXkFc8gBwOW8g1BaE4WViShiS5F4tf5ti%2FK%2FPpU9UdkvR4t7pZ45dn4GTV%2FvJwPebx7J3S67Sprjyr07oz7ewA78b3ebI8cO%2B8g7weSOUBNVO4YxS7HYq6%2BiBxNBvOMmYJ4svGALzvO%2BSUxkLDXN9HfRuX4vMMr9t7MusGhHFwxtLOAuL8tUDRwgPs01%2Fe8i6v31u%2FehTfG5c6XIKIAQvJo42XNbWuRhylDVkA7yfbhQBippUKY%2BVKrBbOCShbAx5VUgsCwHvvp1HSjDCumsnVEDvzKXJSOCmtyC4YfFpOyRhnnF8Mv2TaYviLBABWUDggKAQAAPAYAJ0BKjgAOAA%2BTSCLRCKiIRgN%2FgAoBMS0htgATIB%2FRvwg8Cf6r%2BM37Vdtj559kc4Z9Yvtn5Gfkzzg7Sf%2BC%2FKTgCePfx3%2FVfmBzAfTz%2B7epP%2BKf2X8wvYDuAPUA%2Flv9E%2F2P3O%2FDz%2FeeSD8v%2FuHsB%2Fxz%2Bef6r%2B7fu%2Fxm36xJmyyFkngkpmRPYsV6xmH5QF4lb%2Fl9hSgk5D3PqHNQLXrlv7NrItI%2FEHrxBF2jRuhKjEBVmBB10mJvHzkR2Q2arL3GqP10RyllNZGUghwhZxRilAA%2Fuw6mSpSUmz%2BC9%2BKh7D7qK39xAKDdKGxdWNME94DsfqLZMWOWeIeTypqgNWds0IPEbdim9%2FrYj%2BEd8AhWw%2F%2Bzi%2FwdIkNi7bJQyZ55GARC1%2FHJxJRDbUPxx7XEJNOqXwK2TTvcPfg%2FB1Sxtu3%2F%2BqXZV7Ea27hgAqAwjmpzYt%2FUnFY%2BC0oW45G3Loc8bVetEXzeXitUxCUpACSaawCSSfLqRe1eG3zUIXqEc82GnC78rFUxGMUSd%2FG9fuFsdPGi96Lm3KIZEKgeEYxznL%2BMFlhtO40ZN%2FW3ejoFZfedwy4KUpiGElmS9DdaNzh40f3qq2ox2aJonnJDtPET3GC8%2FxLitJKLpjNVH%2Fs2f5UmAx%2B5LKDbHdllFCDWoI3Pp%2FVHmOId6JL4jNCWVVHcq5vtCed3YAxjpLyN7Mu2NYOtVFR9IFyf7Vd5AztRBIGFD79z80kLXz%2F%2F%2BfO3t2lkek5ydWcB0weeaYMf%2Fwaie0%2Bighho%2Bx1LSEM4hwlpukY3yztN8wyYCF8fSe9AWia9TSnFp57nMo5YifIm9RF6TM%2Fvo6yBTI0Pi%2FGt%2F%2F6mnejWgvH1%2F%2F%2BhS5iYOwLt%2BHG5ouw5J01Fd%2F1WfcWXdBL9MEwe3fGBYZUYUOiM3FvKWH0ikirZAvG0xfpgf%2FgnXTZaTTeyzpnuvF289BWGVcYoRTe2gBbGUT00tzQ4XuCIo9OV7ysRBBK4PTfYTi%2FntO%2FGJkP7JHWEAf7RfyPpf2z%2F3gmxcwD3IXTbEB9aXF%2BVQYVzi8x%2FWj1eluYh3G6xEWj5aKxK09fn3AaJy6LKTQjgk8209Tv7brUzGKt26W4a5uQVRnc6cAzlXdvZB3nrAUJ4SsTWRbCM9m6TDQ7A0dctlIEQzv%2FUTvpPTnyuaOqiVP5PsHXhi9x0791xIp4e1U8sUVgkxVIgE2QYZjQXnY9Kuv0ciSsqTTzWZ6it0Z1Y9qOMi%2F%2BDwjsHCI%2FTwjcrXfrv2jVjya%2Fh3h%2FRzBb7Mszb6Pr54Dpg%2B6OQeVLDvWMOcd9P7x1uSSp%2FrzOS7zB9i5HJvNTeTjIi%2Be5Xf9eSzCoym6aKUC6i6Gkf7O96HwkdmR9TOx3ZuNOJY%2F%2BdF%2F%2F%2FnRxgu4Mj%2F29%2FT%2FJ34nP%2F6r9U3fQV%2BjAyqrfV23tQAAA&logoColor=white" alt="Cassette Compatible">
</a>
<a href="https://github.com/nousresearch/hermes-agent">
<img src="https://img.shields.io/badge/Hermes%20Agent-Compatible-7c3aed?style=flat-square&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZD0iTTUgNGgzdjZoOFY0aDN2MTZoLTN2LTdIOHY3SDV6IiBmaWxsPSJ3aGl0ZSIvPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjIiIGZpbGw9IiMxMTEiLz48L3N2Zz4%3D&logoColor=white" alt="Hermes Agent Compatible">
</a>
<a href="https://github.com/openai/codex">
<img src="https://img.shields.io/badge/Codex-Compatible-000000?style=flat-square&logo=openai&logoColor=white" alt="Codex Compatible">
</a>
<a href="https://claude.com/claude-code">
<img src="https://img.shields.io/badge/Claude%20Code-Compatible-d97757?style=flat-square&logo=anthropic&logoColor=white" alt="Claude Code Compatible">
</a>
<a href="https://opencode.ai">
<img src="https://img.shields.io/badge/OpenCode-Compatible-0b0b0b?style=flat-square&logo=opencode&logoColor=white" alt="OpenCode Compatible">
</a>
<a href="https://discord.gg/qd9NY4k8d7">
<img src="https://img.shields.io/discord/1514649803626250452?style=flat-square&logo=discord&logoColor=white&label=Discord&color=5865F2" alt="Discord">
</a>
<a href="https://glama.ai/mcp/servers/Cassette-Editor/oh-my-cassette">
<img src="https://glama.ai/mcp/servers/Cassette-Editor/oh-my-cassette/badges/score.svg" alt="oh-my-cassette MCP server">
</a>
</p>
<p align="center">
<a href="./README.zh-cn.md">简体中文</a> | <b>English</b>
</p>
<table align="center" width="82%">
<tr>
<td>
<video src="https://github.com/user-attachments/assets/efcfda75-f09b-4bde-8a69-e84410f28e10" controls width="100%"></video>
</td>
</tr>
</table>
<h3 align="center">
<em>
Point <a href="https://claude.com/claude-code">Claude Code</a>, <a href="https://github.com/openai/codex">Codex</a>, or <a href="https://github.com/nousresearch/hermes-agent">Hermes</a> at a folder of raw clips.<br />
Describe the video you want. Get back a finished, beat-synced cut.
</em>
</h3>
<p align="center">
<b>14 clips in. One prompt. ~13 minutes to a rendered file.</b><br />
<sub>No timeline. No editing software. No GPU.</sub>
</p>
## ⚡ Install in 30 seconds
```bash
# Claude Code
claude plugin marketplace add Cassette-Editor/oh-my-cassette
claude plugin install oh-my-cassette@cassette-editor
```
```bash
# Codex
codex plugin marketplace add https://github.com/Cassette-Editor/oh-my-cassette.git
codex plugin add oh-my-cassette@cassette-editor
```
Restart your agent, then say: *"Edit the clips in ./footage into a 30-second travel vlog with beat-synced cuts."*
Want to try the workflow before installing? Open the [public web demo](https://trycassette.online/agent-demo).
Needs Python 3.11–3.13, `ffmpeg`, and a [Cassette account](https://trycassette.online/signup/). Full setup — including [OpenCode](#opencode), [Hermes](#hermes), and any other MCP host — is in [Quick Start](#-quick-start).
# 🎥 Overview
**Oh My Cassette** is an open-source AI video editing plugin and local MCP server for [Claude Code](https://claude.com/claude-code), [Codex](https://github.com/openai/codex), [Hermes Agent](https://github.com/nousresearch/hermes-agent), and [OpenCode](https://opencode.ai). It turns natural-language chat into finished montage videos on [Cassette](https://trycassette.online) — beat-synced cuts, auto-matched music, subtitles, transitions, and picture-in-picture — with minimal token overhead.
The agent does the parts that make editing tedious: it watches every clip, picks the shots, plans the cut, syncs it to the beat, and renders — while you stay in chat. Because it runs through your agent, you can do all of it from your phone.
<table>
<tr>
<td align="center" width="33%">
<h3>💬 Chat-to-Edit</h3>
<p>Describe the video in plain language — the agent handles shot selection, pacing, and the timeline, so you never open an editor.</p>
</td>
<td align="center" width="33%">
<h3>🎵 Smart Music Matching</h3>
<p>Finds and syncs music to the mood and rhythm of your footage, so the cut lands on the beat without you marking a single one.</p>
</td>
<td align="center" width="33%">
<h3>👀 Nothing Renders Until You Say So</h3>
<p>Every turn returns a timeline digest and a contact sheet you can review in seconds — you approve the plan before a frame is rendered.</p>
</td>
</tr>
</table>
## 🖥️ How it works
Upload your clips, describe the video you want, and the agent edits it.
<table width="100%">
<tr><td>
<video src="https://github.com/user-attachments/assets/28792f85-a468-4f8b-a5c6-c7f550e724a3" controls width="100%"></video>
</td></tr>
</table>
| Time | What happens |
| --- | --- |
| 0:09 | The brief — one line, style left entirely to the agent, typed into Claude Code |
| 0:22 | 15 files upload to Cassette; every clip is analyzed for scene content |
| 0:35 | The agent edits on its own — shot selection, title card, lower-third, grading, beat-synced cuts |
| 0:58 | The timeline comes back as a readable digest, with a clickable contact-sheet link |
| 1:03 | One `cmd+click` opens the real contact sheet — one frame per clip, zero render |
| 1:12 | The contact sheet itself: what the cut looks like before a single frame is rendered |
| 1:44 | The export lands, and the runtime measures it — duration, black frames, audio levels |
| 1:52 | The finished cut |
**The cut it produced**
<table align="center" width="70%">
<tr><td>
<video src="https://github.com/user-attachments/assets/54df6c4d-ba5f-4b01-af83-62f214dc6249" controls width="100%"></video>
</td></tr>
</table>
<sub>The screen recording is compressed to keep this page light, so the terminal text looks softer here than it does on your machine; the cut below it is the full-quality render. Prompt to rendered file took 9 minutes 53 seconds of real time, sped up above. A person's face is pixelated in both the screen recording and the cut it produced, for privacy — that blur is not something the agent added.</sub>
<sub>**Token cost:** that session used 55K output tokens and 2.33M billed input tokens (2.07M of them cache reads) on Claude Opus 5 — roughly **$4 at API list price**, measured from the Claude Code transcript of this exact recording. One brief, one turn, start to exported file. The editing itself runs on Cassette, so the agent only pays for the brief and the timeline digests, not for the footage.</sub>
## 🎬 Case Videos
Every case below was edited end-to-end by an AI agent through Oh My Cassette, from the exact prompt shown — real inputs, real processing times, and the output is what the agent delivered.
<table width="100%">
<tr>
<td width="33%" valign="top">
<video src="https://github.com/user-attachments/assets/b85285a9-30ed-4f9b-b314-538bfd9dbdd6" controls width="100%"></video>
<h3>Travel Vlog</h3>
<p>
<sub>🎞️ Input: 13 video clips · 1 audio track</sub><br />
<sub>⏱️ Processing Time: 15 mins</sub>
</p>
<p><b>Prompt</b><br />
Edit a 30-second travel vlog using all materials with a clear viewing flow. Add the title subtitle "KOTA KINABALU" at the beginning and end. Include the vlog shooting time, overlay the character video onto similar scenic shots as a picture-in-picture effect, keep the rhythm light and memorable, and use hard cuts plus music beat sync for a fresh vacation feeling.</p>
<p><code>Travel</code> <code>Vlog</code> <code>Beat Sync</code> <code>PiP</code></p>
</td>
<td width="33%" valign="top">
<video src="https://github.com/user-attachments/assets/97fdfe3a-f420-4135-8c62-494bbb7ea436" controls width="100%"></video>
<h3>Cooking Tutorial</h3>
<p>
<sub>🎞️ Input: 12 video clips · 1 audio track</sub><br />
<sub>⏱️ Processing Time: 8 mins</sub>
</p>
<p><b>Prompt</b><br />
Use these materials to edit a cooking video for stir-fried pork with green peppers. Keep the steps smooth, preserve the cooking sounds, and add simple subtitles. The subtitles can be generated based on the visuals to help viewers understand each step. Keep the style clean and natural without covering the ingredients.</p>
<p><code>Food</code> <code>Tutorial</code> <code>Explainer</code></p>
</td>
<td width="33%" valign="top">
<video src="https://github.com/user-attachments/assets/8da38e40-7876-4743-a32d-5fd95265f37e" controls width="100%"></video>
<h3>Commercial</h3>
<p>
<sub>🎞️ Input: 15 video clips · 15 sound effects · 1 audio track</sub><br />
<sub>⏱️ Processing Time: 13 mins</sub>
</p>
<p><b>Prompt</b><br />
Use these materials to edit a 15-second product commercial. Start with opening the bottle cap, add bubbles, water splashes, ice cubes, and product details in the middle, and end with the full product and brand. Keep it refreshing, thirst-quenching, and ad-like.</p>
<p><code>Product</code> <code>Short</code> <code>Commercial</code></p>
</td>
</tr>
</table>
<p align="center">
<strong><a href="./docs/showcase.md">→ See all six cases</a> — daily vlog, cinematic short, and game highlights, each with its exact prompt.</strong><br />
<sub>★ More cases are on the way. Star the project to follow along.</sub>
</p>
# 🚀 Quick Start
## Before You Start 🎬
Oh My Cassette connects Codex, Claude, or Hermes to the <a href="https://trycassette.online/agent">Cassette Agent</a>. You need:
* Codex, Claude Code, or a working Hermes Agent installation.
* A Cassette account.
* For Hermes only, a configured gateway such as QQ or Telegram.
> [!TIP]
> **Apply for a Cassette account here:** [**Cassette Sign Up**](https://trycassette.online/signup/)
If you plan to use Hermes and it is not installed yet:
```bash
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
```
If the Hermes Agent gateway is not configured yet:
```bash
hermes gateway setup
```
Oh My Cassette currently supports QQ and Telegram gateways.
## Requirements
- macOS, Linux, or Windows for the local MCP plugin (Codex, Claude Code, or OpenCode). The Hermes Agent gateway path is macOS/Linux only.
- Codex, Claude Code, or OpenCode for the local MCP plugin, or Hermes Agent with its gateway configured.
- Python 3.11–3.13.
- `ffmpeg`, required for Hermes gateway normalization and optional API export thumbnails.
### Supported video uploads
Cassette currently accepts video source files that match all of the following limits:
| Limit | Accepted input |
| --- | --- |
| Container | MP4 only |
| Video | H.264/AVC, 8-bit `yuv420p`, SDR |
| Audio | AAC mono, AAC stereo, or no audio track |
| Frame rate | Constant 29.97 or 30 fps |
| Landscape resolution | Up to `1920×1080` |
| Portrait resolution | Up to `1080×1920` |
| File size | Up to 2 GiB (`2,147,483,648` bytes) per video |
| Duration | Up to 60 minutes per video |
MOV, HEVC/H.265, AV1, VP9, ProRes, HDR, 10-bit, variable-frame-rate video, 24/25/50/60 fps, 4K, oversized files, and videos longer than 60 minutes are rejected rather than transcoded in the cloud.
### Upload retention
Uploaded videos and plugin-managed previews, job state, and exports share one immutable **24-hour** deadline measured from the session's first ingest. After that deadline the plugin removes its local copies and the service removes its media; another session — even on the same host or the same account — cannot reach them. Keep your own copy of every source file, and move any export you want to retain outside the plugin-managed data directory before the deadline.
Install system tools:
```bash
# macOS
brew install uv ffmpeg
```
```bash
# Debian/Ubuntu Linux
sudo apt-get update
sudo apt-get install -y ffmpeg
curl -LsSf https://astral.sh/uv/install.sh | sh
```
```powershell
# Windows (PowerShell)
winget install Python.Python.3.13
winget install Gyan.FFmpeg
```
## Install
### Codex
```bash
codex plugin marketplace add https://github.com/Cassette-Editor/oh-my-cassette.git
codex plugin add oh-my-cassette@cassette-editor
```
Start a new Codex task after installation so plugin discovery runs again. The plugin contributes the host-neutral `cassette-video-edit` and `cassette-model` skills plus a local MCP process named `cassette`. Fresh editing sessions use GPT-5.6 Luna with Extra High thinking; invoke `$cassette-model` only when you want to inspect or change that session setting.
### Claude Code
```bash
claude plugin marketplace add Cassette-Editor/oh-my-cassette
claude plugin install oh-my-cassette@cassette-editor
```
Restart Claude Code after installation. You can verify the installation with:
```bash
claude plugin details oh-my-cassette@cassette-editor
```
Claude Code can keep the plugin up to date on its own once you enable auto-update for the marketplace — see [Update](#update).
Fresh editing sessions use GPT-5.6 Luna with Extra High thinking. Invoke `/cassette-model` when you want to inspect or change the current session's model and thinking level.
### OpenCode
OpenCode's plugin manager installs npm packages only, and its plugins cannot contribute MCP servers, so there is no marketplace entry to add. One command instead:
```bash
curl -fsSL https://raw.githubusercontent.com/Cassette-Editor/oh-my-cassette/release/scripts/install_opencode.py | python3 -
```
That downloads the current release, writes the `cassette` server into `~/.config/opencode/opencode.json` (merging with any servers and settings already there), installs the host-neutral skills into `~/.config/opencode/skills/`, and installs `/cassette-model` into `~/.config/opencode/commands/`. Restart OpenCode afterwards. Fresh editing sessions use GPT-5.6 Luna with Extra High thinking; the command changes the setting only when you invoke it.
**Re-run the same command to update.** Only `git` is not required — the release tarball is fetched with Python's standard library.
Cassette credentials are shared across Codex, Claude Code, OpenCode, and Hermes, so if you have already set up another host there is nothing more to do. Otherwise the installer prints the `setup_local_mcp.py` command to finish authentication. Jamendo uses the host-specific BYOK setup described below.
The plugin tree lands in `~/.oh-my-cassette` (override with `OMC_HOME`). `--dry-run` previews the changes. If you prefer a git checkout, clone it and run the installer from there — it registers that tree and leaves it alone, and `--sync` fast-forwards it to the release channel.
### Any other MCP host
The runtime is host-neutral, so any client that launches a local stdio MCP server can use it. Point the client at `scripts/run_local_mcp.py` (run with `python3`, or `python` on Windows) and set `CASSETTE_RUNTIME_ADAPTER=mcp`. The server ships full workflow guidance in its MCP `instructions`, and every tool returns a typed `phase`/`next_action` so a host without the packaged skill can still drive the flow. For the best experience, also install the `cassette-video-edit` and `cassette-model` skills (or equivalent system prompts). Generic clients can call `cassette_config` or ask in natural language to change the current session's model.
Letting an AI assistant do the install for you — Cline, or any agent with shell access? Point it at [llms-install.md](llms-install.md): a machine-readable setup guide covering the runtime pre-build, host registration, authentication, media roots, and verification.
### Hermes
Install through the Hermes plugin manager (recommended):
```bash
hermes plugins install Cassette-Editor/oh-my-cassette
```
The Hermes installer prompts for your Cassette account email and password and saves them to `~/.hermes/.env`. Then run the setup finisher — it configures the same stdio MCP server and canonical editing skill used by the other hosts, sets Hermes's tool timThis server cannot be deployed
Maintenance
ActivityActive
ResponsivenessResponsive