Communitygithub.com

raisaksham377-bot/youtube-shorts-ai-editor

Build a split-frame vertical Short/Reel (1080x1920) from talking-head footage — real face cropped into the bottom half throughout, bespoke motion-graphic beats + word-by-word captions in the top half. Use when the user wants a "vertical short", "reel", "9:16 video", "split-frame" format, asks to keep their face on screen the whole time while graphics play above it, wants an in-context app/UI mockup moment (like clicking a button in a browser) without cutting away from their face, or hits caption-pill-covers-my-face / no-GPU-rendering / audio-duration-mismatch problems while building one. Covers the crop-offset technique for framing the face, the caption-pill safe zone, the top-half-only UI-mockup scene pattern, the full pipeline from raw footage to final SFX mix, and the environment gotchas (no NVIDIA GPU, AAC priming gap, comp-native transcode). Topic-agnostic — this is a layout/technique skill, not tied to any one video's content. Builds on /clean-cut, /make-tsx conventions, and /suggest-sfx; doesn't rep...

youtube-shorts-ai-editor 是什麼?

youtube-shorts-ai-editor is a Cursor agent skill that build a split-frame vertical Short/Reel (1080x1920) from talking-head footage — real face cropped into the bottom half throughout, bespoke motion-graphic beats + word-by-word captions in the top half. Use when the user wants a "vertical short", "reel", "9:16 video", "split-frame" format, asks to keep their face on screen the whole time while graphics play above it, wants an in-context app/UI mockup moment (like clicking a button in a browser) without cutting away from their face, or hits caption-pill-covers-my-face / no-GPU-rendering / audio-duration-mismatch problems while building one. Covers the crop-offset technique for framing the face, the caption-pill safe zone, the top-half-only UI-mockup scene pattern, the full pipeline from raw footage to final SFX mix, and the environment gotchas (no NVIDIA GPU, AAC priming gap, comp-native transcode). Topic-agnostic — this is a layout/technique skill, not tied to any one video's content. Builds on /clean-cut, /make-tsx conventions, and /suggest-sfx; doesn't rep...

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/raisaksham377-bot/youtube-shorts-ai-editor/tree/HEAD/.claude/skills/build-vertical-reel

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

build-vertical-reel — the split-frame vertical Short/Reel format

A format, not a topic: bottom half of a 1080x1920 canvas is the real talking-head footage, cropped and held in frame for the entire video; top half is a sequence of bespoke motion-graphic beats timed to the narration; word-by-word captions sit near the bottom of the frame, below the chin, for the whole runtime. The premise is the host's face never leaves the screen — which is what makes this different from /make-tsx's cutaway/overlay model (that format cuts AWAY from the talking head for concept beats; this one never does). Everything here generalizes to any subject — what follows is technique, learned building one real video, written so it applies the same way to the next one on a completely different topic.

The layout, top to bottom

AbsoluteFill (1080x1920)
 └─ background layer (full canvas — brand bg or a per-video treatment)
 └─ bottom-half video div: position:absolute, top:960, width:1080, height:960, overflow:hidden
     └─ OffthreadVideo, position:absolute, top:<CROP_OFFSET>px, left:0, width:1080, height:1920
 └─ top-half content: ONE bespoke scene or a generic statement card, height:960, swapped by beat
 └─ WordCaptionOverlay — always last (topmost), so captions survive every beat, including UI-mockup ones

The video element is oversized to the FULL 1920 canvas height and then shifted up by CROP_OFFSET so the crop window (the bottom-half div, 0-960 in its own local coordinates) lands on the right part of the frame. This is the whole trick — read on for how to find that number.

1. The crop-offset technique (framing the face)

You're taking a 1080x1920 source (or a source transcoded to that spec — see the environment section) and showing only a 1080x960 WINDOW of it in the bottom half. CROP_OFFSET is the top value (usually negative) applied to the full-height video element inside that clipped window.

The formula, once you have CROP_OFFSET:

canvas_y = 960 + (video_local_y - CROP_OFFSET)

video_local_y is a pixel row in the SOURCE footage (0 = top of frame); canvas_y is where that row ends up on the final 1920-tall canvas. Anything with canvas_y < 960 is invisible (cropped off above the window) or > 1920 (cropped off below).

How to find CROP_OFFSET for a new video (don't guess — measure):

  1. Pick a candidate offset (start from 0 or from the previous video's value as a rough prior).
  2. Render ONE still frame of the actual composition at that offset.
  3. Look at it. Is the hairline/head cut off at the top of the bottom half? Offset is too small (not negative enough) — push it more negative to shift the video content up and reveal more head. Is there too much dead space above the head? Offset is too negative — pull it back toward 0.
  4. Re-render, re-look, converge. Two or three iterations is normal. This is the same render-a-still-and-actually-look discipline as everything else in this repo — never ship a crop offset you haven't seen.
  5. Once converged, use the formula above to compute canvas_y for any landmark you need later (eyes, chin, collar) without re-measuring by eye every time — you already have the mapping.

Worked example from one build (numbers are specific to that shoot's framing — re-measure for any new footage, don't reuse them): CROP_OFFSET = -140 put the hairline right at the top of the bottom-half window (canvas_y ≈ 960), eyes/glasses landed around canvas_y ≈ 1380-1470, and the chin/collar line fell around canvas_y ≈ 1650-1850. A different framing (wider shot, different camera height, sitting vs standing) will produce completely different numbers — the FORMULA and the measure-render-look LOOP are what transfer, not the constant.

2. The caption-pill safe zone (never covers the face)

Word-by-word captions (WordCaptionOverlay in lib/kit.tsx) are positioned with a bottomPad prop: distance in px from the bottom of the full 1920 canvas to the bottom of the pill. Bigger bottomPad = higher up the screen; smaller = closer to the bottom edge.

The bug this format is prone to: picking a bottomPad that lands the pill directly on the eyes/glasses — it looks fine on a spot-check at one frame (a short word, small pill) and then fails on a long word (wider/taller pill) or a different beat where the framing shifted. It was caught exactly this way once already: reported by checking several different real rendered frames, not one.

Where the pill should sit: below the chin, at the collar/upper-chest line — clear of the face under ANY word length, since this is normally a static-camera shot and the neck line doesn't move frame to frame. Use the crop-offset formula from §1 to convert your measured chin/collar video_local_y into a target canvas_y, then work backward: bottomPad = 1920 - canvas_y_target (roughly — the pill has some height above its bottom edge, so bias bottomPad a little smaller than the raw subtraction and verify).

Verification checklist before calling a bottomPad value done (all of these, not a subset):

  • Render stills at several different words, not just one, including the SHORTEST word in the transcript (narrowest pill) and the LONGEST word (widest/sometimes tallest pill — check it doesn't wrap or grow into the danger zone).
  • Render stills at different beats/scenes, since some beats may change what's visible in the bottom half (a full-width UI mockup in the top half doesn't affect this, but any future variation in the crop or framing would).
  • Actually look at each still. Confirm the pill is below the jaw/chin line and hasn't drifted onto the neck's shadow or the eyes.

3. The top-half-only UI/app-mockup scene pattern

Sometimes a beat needs a concrete on-screen action — clicking a button, filling a form, scrolling a page — shown as a real (mocked) UI rather than described in text. The instinct is to build it as its own full-screen Remotion composition and drop it in via <Sequence>, the way /make-tsx's cutaway shots work elsewhere in this repo. Don't do that here — a full-screen cutaway hides the talking head for its whole duration, which breaks this format's entire premise. Two real symptoms of getting this wrong: the mockup covering the whole page instead of sharing it with the face, and the mockup never actually appearing in the final composite because a full-screen <Sequence> was wired in as a separate overlay instead of through the beat-scheduling system everything else uses (both happened in one real build; both wasted a full render-and-review cycle each).

Source the mockup from a REAL capture, not a hand-drawn clone (brand.md §6, creator feedback 2026-09-03). Both example reels in examples/shorts/ hand-coded a fake LinkedIn "Easy Apply" UI from scratch (a LinkedInTopScene built purely from CSS boxes/colors chosen by eye) — it worked, but it's a fabricated UI, and it's strictly worse than the real thing when a real thing exists (which it almost always does: the actual job posting, the actual app, the actual company page). Before hand-drawing ANY UI mockup, spend two minutes checking whether you can capture the real one instead: tools/capture_web.py against the real public URL → real PNGs in media/projects/<video>/real/ → use those bitmaps as the scene's content (via <Img src={staticFile(...)}>, cropped/scaled to the top-half region per point 3 below) instead of redrawing the page in JSX. Only fall back to a hand-drawn clone when no real equivalent exists (a hypothetical/future UI, a competitor's page you can't reach, a private/authenticated view) — and say so in a comment when you do.

The correct pattern — treat it exactly like every other bespoke scene:

  1. Build a scene component SomeUiMockupScene: React.FC<{ frame: number; holdFrames: number }>, confined to height: 960 (top half only), driven ENTIRELY by the frame/holdFrames props — not by calling useCurrentFrame() internally. It is not wrapped in its own <Sequence>; the outer beat-scheduler computes localFrame = frame - card.startFrame and passes it straight in, same as a statement card or an icon animation.
  2. Gotcha: reusable chrome components (a browser-window frame, a phone-status-bar component, etc.) often call useCurrentFrame() internally to drive their OWN entrance animation. That reads the GLOBAL timeline frame, which is wrong once the scene is driven by a local frame instead of a <Sequence> — the entrance either fires at the wrong time or (if the beat starts well past frame 0) never visibly fires at all. Either hand-roll a smaller version of the chrome sized for the top-half region (safest — full control over scale and timing), or, if reusing the shared component, pass its appearAt prop equal to the beat's GLOBAL start frame so its internal comparison lines up with when local frame 0 actually happens.
  3. Scale every coordinate to fit inside 1080 wide x 960 tall with margin — don't just crop a 1080x1920 mockup down to its top 960px, or you'll clip whatever chrome/base sits at the bottom (a laptop's base, a phone's home indicator, a browser's lower content). Re-derive box/button coordinates for the smaller canvas rather than reusing the full-screen version's numbers.
  4. Any cursor/click micro-interaction (reusable from lib/screencast.tsx's sampleCursor / CursorPointer / CursorKey): keyframe coordinates are VIEWPORT-FRACTION (0-1), not pixels — so they're canvas-size-agnostic. Just be consistent about multiplying by the REGION's own dimensions (e.g. cur.x * 1080, cur.y * 960) when placing the cursor, not the full 1920 canvas height.
  5. Wire it into the same beat-scheduling table every other scene uses (a Card-like list with startFrame/endFrame/scene, dispatched by a chain of if (activeCard.scene === 'x') return <XScene .../>). This means the SAME mockup component can appear at multiple points in the timeline for free — just add a second entry to the schedule referencing the same scene — instead of duplicating the component or wiring a second bespoke <Sequence>.

4. Full pipeline, raw footage → final delivered file

This format is layered ON TOP of the existing pipeline, not a replacement for it:

  1. /clean-cut on the raw talking-head footage → an approved master cut + edited-transcript.json (word-level timestamps in the master's timeline). Unchanged from the standard pipeline — do this first, exactly as documented there, including its own user-audit gate.
  2. Comp-native transcode — Remotion's OffthreadVideo needs a decode-friendly source. Whatever the master's native spec, transcode a copy to this format's target (1080x1920, 30fps, 8-bit H.264):
    ffmpeg -i master.mp4 -vf "scale=1080:1920" -r 30 -c:v libx264 -pix_fmt yuv420p -c:a copy master-comp-native.mp4
    
    Skipping this and pointing OffthreadVideo at a high-bitrate/odd-fps/10-bit master starves the decoder during render — duplicated frames, visible stutter, perceived desync (documented in /clean-cut too; it bites here just as hard since the video plays for the ENTIRE runtime, not just cutaway spans).
  3. Find CROP_OFFSET per §1 above, and build the split-frame shell (background + cropped bottom-half video div + caption overlay).
  4. Read the transcript, decide the beat list, and author one bespoke scene per beat that needs punch (icons/animation sized generously for the top-half region — this format reads better with big, confident graphics than small restrained ones) or a generic statement card for plain-text beats. Any beat needing a concrete UI moment follows §3.
  5. npm run gen after adding/renaming any scene file (the shot registry is generated, not hand-maintained — same rule as the rest of this repo).
  6. Render proof stills at each new beat's key frames (entrance, a mid-hold frame, and — for anything caption-adjacent — per §2's checklist) and actually look at them before moving on. npx tsc --noEmit first to catch type errors cheaply, before spending render time.
  7. Render the full composite.
  8. A/V duration gate — ffprobe -show_entries stream=duration on v:0 vs a:0. The VIDEO track duration must equal the intended composition length exactly. See the AAC note below for why the audio track alone is expected to differ slightly at this stage.
  9. SFX pass (/suggest-sfx conventions apply as-is): author/re-use a sfx-plan.json, get it audited, then mix: python tools/mix_sfx.py <path/to/sfx-plan.json>. Gotcha: the script's positional argument is the PLAN FILE path, not the project directory — passing a directory fails with a confusing PermissionError (it tries to open() the directory itself), not a helpful "wrong argument" message.
  10. Re-verify durations on the SFX-mixed output (video track should still match exactly; the mix step also tends to bring the audio track back in line). Pull a few final stills at the changed beats to confirm nothing regressed, then deliver.

Whenever a beat changes later, only re-render from step 6 onward for the affected span — but the A/V gate (step 8) and a fresh SFX mix (step 9) are cheap enough to just always re-run on the whole file rather than trying to patch a segment in place.

5. Environment gotchas (real, not hypothetical — hit them once each)

  • No NVIDIA GPU on some machines. h264_nvenc / hevc_nvenc and -hwaccel cuda fail with Cannot load nvEncodeAPI64.dll on a machine with no NVIDIA card. Fix: fall back to CPU encoders — libx264 for preview-grade renders, libx265 for final-grade — and drop the -hwaccel cuda flag entirely (an empty hardware-accel option list). This is a real, working fallback, not a degraded/broken mode — just slower. Keep it easy to revert (a single constant/flag) for anyone running the same tools on a GPU-equipped box later.
  • The AAC audio-priming gap is normal, not a bug. Every render tends to show the audio track measuring a small amount (roughly 40-55ms) LONGER than the video track when probed independently — this is a well-known, consistent AAC-encoder artifact (encoder priming samples), not drift and not something to chase or "fix" with padding/trimming. Gate correctness on the VIDEO track matching the intended duration (step 8 above); don't fail a render over a sub-60ms audio-track mismatch that reproduces identically every time. If the gap ever grows well beyond that range, or the audio is SHORTER than the video, THAT is a real problem worth investigating — the small, consistent, audio-longer case is not.
  • Comp-native transcode is not optional — see step 2 above. This is the single most common "why does my render stutter" cause when the source wasn't prepared for OffthreadVideo.
  • (Windows/Git-Bash) venv Python needs drive-letter paths. venv/Scripts/python.exe is a Windows-native binary — it rejects MSYS-style /c/... paths some Git-Bash tooling produces. Pass C:\...-style paths when invoking Python tools from Git Bash on Windows.

Principles (apply these)

  • The face is the constant; graphics are the variable. Every design decision (crop offset, caption position, mockup scene sizing) starts from "does the face stay visible and legible" and works outward from there.
  • Measure, don't guess, and verify by looking. Crop offsets, caption safe zones, and any new scene's timing all get found by rendering a real still and looking at it — never asserted from arithmetic alone, and never confirmed from a single frame when a range of words/beats could break it.
  • Big, confident graphics. This format's top half reads better with icons and text sized generously for a 1080x960 region than with restrained desktop-sized graphics — when in doubt, size up.
  • Reuse the beat-scheduling system for everything, including UI mockups — a second appearance of the same scene is a second table entry, not a second component or a second <Sequence>.
  • Topic-agnostic. Nothing in this skill should reference any one video's script or subject — when writing scenes for a specific video, keep the content decisions (what the beats say) separate from the technique decisions (how the format works) described here.

Done = the face is on screen and legible for the entire runtime, captions never touch it at any word length, any UI-mockup beats share the frame with the face instead of hiding it, the A/V duration gate passes, the SFX mix is applied and re-verified, and every new beat has been confirmed by looking at a real rendered still — not asserted.

Individual skills in this repo

This repo contains 8 individual skills — each has its own dedicated page.

raisaksham377-bot/youtube-shorts-ai-editor

Makes this repo's videos look like YOUR channel instead of the house default — interviews you for palette, fonts, wordmark, motion energy, delivery specs and SFX taste, then rewrites brand.md + remotion/src/brand.ts + remotion/src/fonts.ts together and renders a proof card so you SEE it. Use whenever the user wants to set up or change their brand, rebrand the repo, "make it my colors/fonts", change the accent color, set their wordmark, adjust the motion feel, or asks why their videos look like someone else's. Run it once before the first video. Not for per-video art direction (that is /make-tsx) and not for thumbnails, which are deliberately louder than the brand (that is /packaging).

raisaksham377-bot/youtube-shorts-ai-editor

Voice/audio cleanup step of the AI Video Editor pipeline — diagnose a video's background noise, pick the right denoise method, and produce a cleaned master (voice isolated, levels preserved, video stream copied). Use when the user wants to "clean the audio / voice", "remove background noise", "denoise", "isolate voice", fix outdoor/room/water/hum/hiss noise, run ElevenLabs Voice Isolator or local RNNoise, A/B denoise methods, or produce a cleaned master for a video-N in this repo. Covers diagnosing the noise (spectrogram + levels), choosing eleven vs rnnoise by noise type, the sample A/B, tools/clean_voice.py, preserving levels (RMS-match, not LUFS), and rewiring the pipeline to the clean master. Not the SFX/music mix (that is /suggest-sfx + the final-mix step) and not the cut (that is /clean-cut).

raisaksham377-bot/youtube-shorts-ai-editor

Step 1 of the AI Video Editor pipeline — turn raw talking-head footage into a clean master cut. Use when the user wants to "clean cut", "cut the raw footage", "remove filler / dead air / bad takes", "tighten the pacing", produce cuts.json, run the cut editor, or render a cleaned preview/master for a video-N project in this repo. Covers audio extraction, AssemblyAI transcription, authoring cuts.json (keeps/cuts/fluff categorized), the cut policy (content-aggressive, pause-natural ~0.5s), QA + review docs, the local cut-editor UI, tight/natural previews, the final 4K60 render, and producing edited-transcript.json as the handoff to /make-tsx. Not for building TSX overlays (that is /make-tsx) or the raw TSX authoring rules (that is vidtsx-2d-generator).

raisaksham377-bot/youtube-shorts-ai-editor

Turn static SCREENSHOTS into a simulated screen recording (TSX) — a fake screencast with an animated cursor that eases to targets and clicks, a browser URL bar that updates per page, hard-cut navigations, in-page filter crossfades, smooth scroll, and a ken-burns zoom onto the payoff. Use when a beat needs to show a walkthrough of a web app / dashboard / settings page and you'd rather build it from screenshots than get (or ask for) a real screen recording — "fake a screen recording", "turn these screenshots into a screencast", "simulate clicking through the dashboard", "animate this UI walkthrough", "cursor moving through the app". Built on remotion/src/lib/screencast.tsx. This is a technique WITHIN step 2 (make-tsx): defer timeline/render/bake orchestration to make-tsx and raw crash-free TSX rules to vidtsx-2d-generator. Not for a single static page clone (use WebBrowserFrame directly) and not when the point is genuine proof of real speed/output (use a real recording).

raisaksham377-bot/youtube-shorts-ai-editor

Step 2 of the AI Video Editor pipeline — build the visual beats (Remotion TSX shots) over a project's master cut and bake a composited preview. Use when the user wants to add/edit overlays or full-screen animation segments, "make a shot / beat", implement an edit plan or a v2 update, retime a beat to the narration, re-render shots, or re-bake the video-N preview in this repo. Covers reading the plan + edited-transcript + brand + reusable kit, authoring shots library-first, syncing reveals to word times, updating timeline.json (cutaway vs overlay), rendering, verifying by screenshot, and baking with tools/bake.py. Defers raw TSX authoring rules to vidtsx-2d-generator and the cut itself to clean-cut.

raisaksham377-bot/youtube-shorts-ai-editor

Generates click-optimized YouTube packaging — 3 thumbnail bets under one fixed title, engineered for YouTube's built-in A/B/C thumbnail test, plus a value-forward description, then renders the thumbnails as real images. Use this whenever you want to package a long-form video or turn a video idea into titles and thumbnails. Triggers include how would you package this, title ideas for, thumbnail concept, package this video, A/B variations, and make this clickable. Calibrates to your channel's own CTR data if you have it. Long-form only, never Shorts. Not for non-YouTube copywriting.

raisaksham377-bot/youtube-shorts-ai-editor

Step 4 of the AI Video Editor pipeline — the SFX pass. Analyze a video's beats + narration and propose tasteful sound effects synced to them, drawing from (and growing) a shared, reusable SFX library, then render an SFX-mixed audition preview. Use when the user wants to "add SFX / sound effects", "suggest sfx", "score the transitions", "sound-design this beat", generate/source sound effects, build or extend the sfx library/catalog, author or audit a sfx-plan, or mix SFX over a video-N preview in this repo. Covers reading timeline + edited-transcript + brand §10, the library-first flow, generating misses with the ElevenLabs Sound Effects API, the per-video sfx-plan.json, the hard user-audit gate, and mixing with tools/mix_sfx.py (light voice ducking). Not the music bed (that is the final-mix step) and not the visual beats (that is /make-tsx).

raisaksham377-bot/youtube-shorts-ai-editor

Generate production-ready 2D TSX video files for VidTSX (Remotion-based) from a shot, scene, or video description. Use whenever the user wants to create or generate a VidTSX video, a 2D TSX shot or scene, an animated clip, title card, or rendered motion graphic — including when they describe a visual animation they want built, or say "make a shot", "build this scene", "generate the TSX", or "turn this into a video". Covers the mandatory file structure and composition config, dimension presets (horizontal/vertical/square), six style presets (minimalist, memphis, neo-brutalism, glassmorphism, neon, corporate), and the hard rules that keep renders from crashing, covering frame-based animation only (no useState/useEffect/setTimeout), strictly monotonic interpolate ranges, Easing.bezier not wrapper syntax, and the chroma-js and @remotion/paths import gotchas. Not for 3D/three.js compositions, general React work, or editing video files.

相關技能