A podcast-clipping studio that runs on one home PC: Whisper on a 3090, face- and text-aware framing, auto-designed covers, and one-tap publishing to four platforms.
20 entriesStack Python 3.12 · faster-whisper · OpenCV · ffmpeg · FastAPI · SQLite · Anthropic API · YouTube Data API · Buffer · Cloudflare R2clipper-siteView on timeline
Clipper takes long podcast and interview episodes and turns them into captioned vertical clips. Claude picks the moments, the owner reviews every one of them in a local web app, and approved clips post to a YouTube channel on a fixed daily schedule, with copies to TikTok, Instagram, and Facebook.
It was built in eight days by a manager session dispatching builder, reviewer, and tester agents, almost always through pull requests with a review round. The story is mostly one of tuning against real footage: every change to framing and clip edges answered a specific clip that looked wrong. Then a pivot on day eight narrowed the sources to footage creators hand over directly.
The companion marketing site, clipper-site, is three static pages (home, privacy, terms) written so the Google OAuth consent screen had something to point at. It is folded into this section.
The owner joined a second clipping board and asked for its campaign list to be read by a browser session rather than scraped. The survey found the public list carries only a card per campaign: brand, title, rate, and a lock. The rules, budget, resources, and minimum views live in the signed-in app, which the browser extension cannot reach until the owner allows the site. The read-by-hand guide now sends the session there and makes the block visible. Overnight, under a blanket go, three small merges followed, including a test that failed only when the owner's drive dipped under the free-space floor.
Five suitable campaigns out of thirty-six on the first board was not enough, so the owner asked for more boards. A survey found only two others with public listings. One forbids scraping in its terms, so the app will never fetch it; the owner's own browser session will read it instead. The other has no such rule and is read through a paid third-party actor, so the app never touches that site either. Both shipped the same evening, after review caught one board's bad day wiping the other's list. Also today: a daily cap on rules reads, and campaigns mostly in another language are skipped.
At one minute to midnight the owner handed over a fifty-item improvement list, a rollback point, and leave to shut the machine down when nothing more could be done. By seven in the morning twenty-four pull requests had merged, each built by a fresh subagent against the full test suite and, where it mattered, one review round. Two of the biggest features ship switched off until the owner turns them on.
The board that forbids scraping now gets read the agreed way: a button on the Campaigns page starts a Claude session in the owner's own browser, which reads the listings at a person's pace, answers in a fixed shape, and writes the file the finder merges. No tick and no schedule; only the owner's press. The session gets six read-only browser tools and nothing else. Review fixed five things before merge, and the manager held one more tool back: the one that can click and type in a signed-in browser. Also today, the tab named after the first board became Campaigns.
A campaign's board card says little; its real rules often live on another site, a shared document, or a PDF. The owner asked for the finder to read all of it, and named three hard disqualifiers: a page dedicated to the brand, the brand's name required in the account name, or required logos and branding. The reader fetches public pages only, keeps them for a week, and a stronger model does the reading, because the goal is the screen capture that goes to Google.
Three merges across one evening and the small hours. Starting the app now restarts it if one is already running. Campaigns that have ended on the marketplace are flagged in Health with a switch-off button. And the owner's channel screenshots showed cover text trimmed at the top and bottom, so covers now keep their words inside the part of the picture YouTube actually shows.
The six o'clock shutdown never took, and half an hour later the owner asked whether clips under review that belong to no campaign should be cleared. Yes. A clear command shipped, review found four other doors a YouTube-era clip could still leave by, and the rework closed them all with one rule: a source outside any campaign is held, the same way paused and removed sources are.
Google's API quota reviewer asked for a step-by-step screen recording of the whole workflow within seven business days. The submission from three days earlier described a tool that no longer existed: it still admitted downloading from YouTube and setting a cover on every upload. The owner's answer was to remove the download path from the code entirely, not switch it off, so the reply can say so plainly.
The rate-limit fix worked: every cover sent to a Short was accepted. Then every one of them vanished within minutes, while the same JPEG uploaded by hand in YouTube Studio stayed. The API cannot set a Short's thumbnail, by Google's own word. One day after the backfill shipped, Shorts no longer go near it: the app hands the cover over and links into Studio. Long-form videos keep the automatic path.
Clipper now clips only footage that creators hand over directly. Downloading creator videos from YouTube is off by default, and a campaign source hosted on YouTube is never fetched.
Only two covers had ever reached YouTube. The publisher sent thumbnails in a burst, got rate-limited, and spent its single retry inside the same burst. Everything else stopped while it was fixed, and the owner's two questions turned a fix into a backfill and an on-demand command. Merged the next morning after one review round.
Clips of three to fifteen minutes, rendered in 16:9, reviewed in their own Inbox tab, scheduled into a 3 PM slot, and published to YouTube as regular videos. Five slices merged in one day, each with one review round. Off by default so the owner can trial it on one channel.
The app started in teal on purple to match the channel it served. It now uses the orange Ember accent and new logo from clipper-site, and the site dropped its channel-specific references on the same day.
About fifteen pull requests on the cover alone: picking a frame automatically, letting Claude judge the candidates, drawing the title in five styles, an Edit cover tool, and setting the YouTube thumbnail only after YouTube finishes processing.
A read-only Settings tab became an editable one, then was removed altogether in favour of an Options pane that slides in from the right on every page, a System cog, and Ctrl+K search.
TikTok, Instagram Reels, and Facebook Reels are reached through Buffer's free plan rather than each platform's own API, with every video served from Cloudflare R2. The posting cadence rose to four slots a day.
Moving the Google Cloud app to production status needed a homepage, a privacy policy, and terms. So clipper-site was born: three static pages on GitHub Pages. After that, the YouTube token stopped expiring every week.
The 115-line review page gave way to a real local web app: an Inbox with low-res preview renders and quality badges, a publish calendar, a campaign panel, a Health page, and Stats. Built in five slices in one day.
Download, transcribe, let Claude pick the moments, render 9:16 with captions, review in a 115-line web page, upload. The first real run produced 63 candidates from 9 episodes, and 13 were approved.
After reviewing the first batch, the renderer became shot-aware: it detects cuts, picks one framing mode per shot, keeps on-screen text in frame, and trims silence against the actual audio instead of the transcript.
After reviewing the first batch, the renderer became shot-aware: it detects cuts, picks one framing mode per shot, keeps on-screen text in frame, and trims silence against the actual audio instead of the transcript.
Download, transcribe, let Claude pick the moments, render 9:16 with captions, review in a 115-line web page, upload. The first real run produced 63 candidates from 9 episodes, and 13 were approved.
The 115-line review page gave way to a real local web app: an Inbox with low-res preview renders and quality badges, a publish calendar, a campaign panel, a Health page, and Stats. Built in five slices in one day.
Nothing posts from the calendar. It only tells you what the next tick will do, and lets you move it.
The Inbox: candidates on the left, the preview render in the middle, the clip's cover, badges, and summary on the right. Creator handles and the source episode title are blanked.
Moving the Google Cloud app to production status needed a homepage, a privacy policy, and terms. So clipper-site was born: three static pages on GitHub Pages. After that, the YouTube token stopped expiring every week.
TikTok, Instagram Reels, and Facebook Reels are reached through Buffer's free plan rather than each platform's own API, with every video served from Cloudflare R2. The posting cadence rose to four slots a day.
A read-only Settings tab became an editable one, then was removed altogether in favour of an Options pane that slides in from the right on every page, a System cog, and Ctrl+K search.
About fifteen pull requests on the cover alone: picking a frame automatically, letting Claude judge the candidates, drawing the title in five styles, an Edit cover tool, and setting the YouTube thumbnail only after YouTube finishes processing.
The app started in teal on purple to match the channel it served. It now uses the orange Ember accent and new logo from clipper-site, and the site dropped its channel-specific references on the same day.
Clips of three to fifteen minutes, rendered in 16:9, reviewed in their own Inbox tab, scheduled into a 3 PM slot, and published to YouTube as regular videos. Five slices merged in one day, each with one review round. Off by default so the owner can trial it on one channel.
The Inbox's Long form tab with a test clip: three moments after a title card, each with its source range. The clip and creator are the builder's test data.
Only two covers had ever reached YouTube. The publisher sent thumbnails in a burst, got rate-limited, and spent its single retry inside the same burst. Everything else stopped while it was fixed, and the owner's two questions turned a fix into a backfill and an on-demand command. Merged the next morning after one review round.
Clipper now clips only footage that creators hand over directly. Downloading creator videos from YouTube is off by default, and a campaign source hosted on YouTube is never fetched.
The rate-limit fix worked: every cover sent to a Short was accepted. Then every one of them vanished within minutes, while the same JPEG uploaded by hand in YouTube Studio stayed. The API cannot set a Short's thumbnail, by Google's own word. One day after the backfill shipped, Shorts no longer go near it: the app hands the cover over and links into Studio. Long-form videos keep the automatic path.
Google's API quota reviewer asked for a step-by-step screen recording of the whole workflow within seven business days. The submission from three days earlier described a tool that no longer existed: it still admitted downloading from YouTube and setting a cover on every upload. The owner's answer was to remove the download path from the code entirely, not switch it off, so the reply can say so plainly.
The six o'clock shutdown never took, and half an hour later the owner asked whether clips under review that belong to no campaign should be cleared. Yes. A clear command shipped, review found four other doors a YouTube-era clip could still leave by, and the rework closed them all with one rule: a source outside any campaign is held, the same way paused and removed sources are.
Three merges across one evening and the small hours. Starting the app now restarts it if one is already running. Campaigns that have ended on the marketplace are flagged in Health with a switch-off button. And the owner's channel screenshots showed cover text trimmed at the top and bottom, so covers now keep their words inside the part of the picture YouTube actually shows.
A campaign's board card says little; its real rules often live on another site, a shared document, or a PDF. The owner asked for the finder to read all of it, and named three hard disqualifiers: a page dedicated to the brand, the brand's name required in the account name, or required logos and branding. The reader fetches public pages only, keeps them for a week, and a stronger model does the reading, because the goal is the screen capture that goes to Google.
The board that forbids scraping now gets read the agreed way: a button on the Campaigns page starts a Claude session in the owner's own browser, which reads the listings at a person's pace, answers in a fixed shape, and writes the file the finder merges. No tick and no schedule; only the owner's press. The session gets six read-only browser tools and nothing else. Review fixed five things before merge, and the manager held one more tool back: the one that can click and type in a signed-in browser. Also today, the tab named after the first board became Campaigns.
At one minute to midnight the owner handed over a fifty-item improvement list, a rollback point, and leave to shut the machine down when nothing more could be done. By seven in the morning twenty-four pull requests had merged, each built by a fresh subagent against the full test suite and, where it mattered, one review round. Two of the biggest features ship switched off until the owner turns them on.
Five suitable campaigns out of thirty-six on the first board was not enough, so the owner asked for more boards. A survey found only two others with public listings. One forbids scraping in its terms, so the app will never fetch it; the owner's own browser session will read it instead. The other has no such rule and is read through a paid third-party actor, so the app never touches that site either. Both shipped the same evening, after review caught one board's bad day wiping the other's list. Also today: a daily cap on rules reads, and campaigns mostly in another language are skipped.
The owner joined a second clipping board and asked for its campaign list to be read by a browser session rather than scraped. The survey found the public list carries only a card per campaign: brand, title, rate, and a lock. The rules, budget, resources, and minimum views live in the signed-in app, which the browser extension cannot reach until the owner allows the site. The read-by-hand guide now sends the session there and makes the block visible. Overnight, under a blanket go, three small merges followed, including a test that failed only when the owner's drive dipped under the free-space floor.