Skip to main content
ClaudeWave
Skill82 estrellas del repoactualizado 2d ago

wjs-overlaying-video

Use when the user has one or more video clips and wants to add post-production on top — AI-generated cover as first frame, HTML/CSS captions synced to SRT, kinetic illustration overlays at hook moments, chapter chips, end-card CTA, or any other timed motion graphics. Most often used as the downstream of `/wjs-segmenting-video` — pick up where that skill stopped (raw cropped clip + per-clip SRT) and produce the upload-ready MP4. Backed by HyperFrames so everything compiles to ONE final encode — no cascade of re-encodes. Triggers — "加封面", "加字幕", "加动画", "加 CTA", "做后期", "post-production", "title card", "kinetic captions", "end card".

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/jianshuo/claude-skills /tmp/wjs-overlaying-video && cp -r /tmp/wjs-overlaying-video/wjs-overlaying-video ~/.claude/skills/wjs-overlaying-video
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# wjs-overlaying-video

Post-production for a video clip: cover, captions, illustrations, CTA,
custom motion graphics — all composed in ONE HyperFrames project and
rendered in a SINGLE final encode. No cascade of decodes/re-encodes
(each cascade pass degrades quality and burns time).

## When to use

- **Downstream of `/wjs-segmenting-video`** — the segmentation skill
  hands you cropped clips + per-clip SRTs; this skill turns them into
  upload-ready MP4s with cover/captions/illustrations/CTA.
- User has a finished video and wants to dress it up with motion
  graphics: opening hook, key-quote callout, closing slogan, chapter
  cards, AI-generated cover as first frame.
- User wants HTML/CSS-quality captions on a video (kinetic word-by-word
  highlighting, custom fonts, large outlined text, seekable per cue).
- User wants illustration overlays at specific hook moments — diagrams,
  big text emphasis, flow charts.

**Don't use** for:
- Splitting one long video into clips → use `/wjs-segmenting-video`.
- Creating the source SRT → use `/wjs-transcribing-audio` (then `/wjs-translating-subtitles` if you need a different language).
- Full HyperFrames productions where the source isn't a fixed video →
  use `hyperframes` directly.
- 微信视频号 / 抖音 upload (no public API for those) → this skill
  produces the MP4; upload is manual.

## What this skill IS — and IS NOT

| Is | Is not |
|---|---|
| Everything that goes ON TOP of a video clip: cover, caption, chapter, illustration, CTA | Cutting / cropping a video (that's `/wjs-segmenting-video` + `/wjs-reframing-video`) |
| One HyperFrames composition per clip = ONE final encode | A multi-step decode/encode cascade |
| `cover` is the literal first frame of the output (platforms auto-pick it as thumbnail) | A separate thumbnail file the user uploads alongside |
| Captions are HTML/CSS — `-webkit-text-stroke` for white-on-anything readability | libass burn-in (deprecated) |
| Illustrations: re-usable `stack` / `hammer` patterns + custom escape hatch | One bespoke HTML/CSS per illustration without re-use |
| AI covers regenerated at native target aspect (1024×1792 for vertical, 1536×1024 for horizontal) | Single 1024×1536 default that letterboxes or crops on the platform |

## The pipeline

```
clip.mp4 + clip.zh-CN.burn.srt   (from /wjs-segmenting-video hand-off)
   ↓
1. (Optional) Generate AI cover via gpt-image-2
   make_cover.py --segments S.json --out output/ --size 1024x1792
   cover_NN_slug.png

2. Scaffold a HyperFrames project per clip
   hf_clip_NN/1080/{index.html, clip.mp4, cover.png, captions.json}

3. Compose: cover scene + body video + caption track + chapter chip
            + 1-2 illustrations at hook moments + CTA scene

4. npm run check (lint + validate + visual inspect)
   npm run render → upload-ready MP4
```

A 2-minute vertical 1080×1920 composition renders in ~2-3 min on M-series Mac.

## Color: tone-map HLG/HDR source → SDR BEFORE compositing

**Only tone-map genuinely HLG/HDR sources.** If the body clip is ALREADY Rec.709
SDR — e.g. a graded multicam render, or polysync output where an S-Log3→709 LUT
was already applied — running the HLG tone-map recipe on it washes/darkens the
already-correct color. `build_hf_clips.py`'s `tonemap_to_sdr` now probes
`color_transfer` (`_is_hlg_hdr`): HLG/PQ → tone-map; otherwise a straight
re-encode with dense keyframes (no tone-map). Either way you still get the
`-g 30` dense-keyframe encode HyperFrames needs.

iPhone / modern-camera footage is often **HLG HDR (bt2020 / arib-std-b67)**.
If you feed that straight into HyperFrames it either renders washed-out
("发白") or, with a naive `--sdr`, too dark ("发黑"); and the HDR x265
path can hang the renderer. **Pre-convert the body clip to SDR (bt709)
30fps h264 with a locked zscale tone-map**, then composite the SDR clip.

The verified recipe (`tonemap_to_sdr()` in `build_hf_clips.py`). `npl=203`
matches macOS-native (qlmanage) reference brightness; `hable` keeps
contrast; this preserves the ORIGINAL look (natural skin / foliage / brick),
no wash, no darkening:
```python
# zscale-capable ffmpeg — Homebrew's lacks zscale/tonemap.
# imageio-ffmpeg ships one: .../imageio_ffmpeg/binaries/ffmpeg-macos-aarch64-v7.1
TONEMAP_VF = ("zscale=tin=arib-std-b67:min=bt2020nc:pin=bt2020:t=linear:npl=203,"
              "format=gbrpf32le,tonemap=tonemap=hable:desat=0,"
              "zscale=t=bt709:m=bt709:p=bt709:r=tv,format=yuv420p,fps=30")
# encode: libx264 -crf 18 -color_primaries/-trc/-colorspace bt709
#         -g 30 -keyint_min 30 -movflags +faststart   ← see gotcha below
```

**Dense-keyframe gotcha.** HyperFrames seeks the body video frame-by-frame.
A clip with sparse keyframes (long GOP) makes it freeze on stale frames —
the render log warns `Video "video" has sparse keyframes`. Always encode the
SDR clip with `-g 30 -keyint_min 30` (one keyframe per frame-second) so every
seek lands clean.

**Verify** the render log says `No HDR sources detected — rendering SDR`.
If it says HDR detected, your clip wasn't tone-mapped — fix that first.

## Version stamp (every output)

Stamp `「skill名字 + 版本号」` bottom-right, shown during the END/CTA scene,
so every render is traceable to the pipeline version that made it. Bump
`VERSION` in `build_hf_clips.py` on each pipeline change.
```css
#ver-stamp { position: absolute; right: 28px; bottom: 28px; z-index: 30;
  font-size: 20px; color: rgba(150,150,156,0.55); letter-spacing: 0.06em; }
```
```html
<div id="ver-stamp" class="clip" data-start="{cta_start}" data-duration="{cta_dur}"
     data-track-index="2">wjs-overlaying-video v1.3</div>
```

## Standard overlay types (the 6 building blocks)

Every clip's final composition is built from some combination of these.
The agent picks the right ones per clip — typically all 6 for a
podcast highlight, or just 1-2 for a single annotation overlay.

### 1. `cover` — full-frame AI image as first frame

The cover IS the first frame (no animation, no zoom) so platforms that
auto-pick the first
skill-quality-reviewerSubagent

Repo-wide drift detector for the wjs-* Claude Code skills in this marketplace. Sweeps every SKILL.md, scores it against the repo's own conventions (V-ing naming, trigger-phrase density, companion files, description shape), and returns a grouped punch list ordered by severity. Read-only — never edits files. Use before pushing a batch of skill changes, or whenever you wonder "are these skills still internally consistent?

wangjianshuo-perspectiveSkill

|

wjs-auditing-projectSkill

Use when the user asks to audit what's wrong with a project, "make it right", "看看项目出了什么问题", "为什么用户的需求还没上线", "为什么没提交App Store", "为什么没新build", or wants a holistic state-of-the-project check covering unmerged branches, stalled PRs, failed GitHub Actions, stale builds, plan drift (TODOS.md / ROADMAP), unreleased commits, and log errors. Runs read-only investigation, presents a grouped checklist, fixes only after explicit user confirmation. Aware of the Cathier iOS app workflow (Xcode + fastlane + auto-merge @claude PRs from in-app feedback).

wjs-burning-subtitlesSkill

Use when the user has a video + an SRT and wants the subtitles either burned into the pixels (libass, always-visible) or soft-muxed as a togglable track. Also handles the final composite step for the localization pipeline — burn subs, mix a dub track, and keep the original audio as a low-volume bed, all in ONE ffmpeg encode (no cascade). Verifies libass availability and auto-downloads a static evermeet ffmpeg build when Homebrew's stripped binary lacks it. Triggers — "烧字幕", "硬字幕", "burn subtitles", "burn-in subs", "embed subtitle", "soft mux SRT", "把字幕烧进视频", "做最终合成".

wjs-cleaning-spamSkill

Use when the user complains about spam on his X/Twitter posts — 同城面付 / 寻固炮 / 线下上门 / 免费破处 这类引流号在他推文下刷的 emoji 垃圾回复 — and wants them removed. Covers the last 7 days (X recent-search window). Triggers — "把这些spam删掉", "清理X垃圾回复", "推文下面好多引流号", "clean spam replies", "/wjs-cleaning-spam".

wjs-converting-text-to-videoSkill

Use when the user wants a 王建硕-style WeChat article (article.md) turned into a narrated short MP4 video — TTS voiceover via 火山引擎 Volcano TTS, HyperFrames CSS/GSAP animation per scene, subtle SFX, abstract watercolor background, full pipeline rendering to 1080×1920 portrait MP4 (30-90s). Triggers — "把这篇文章做成视频", "做一个解说视频", "讲解视频", "/wjs-converting-text-to-video".

wjs-converting-wp-to-hugoSkill

Use when migrating a WordPress site to a Hugo static site on GitHub Pages from a WXR export (.xml) plus the wp-content/uploads folder — preserving /archives/<id>/ URLs, localizing images, and deploying via GitHub Actions. Triggers — "把 WordPress 迁成 Hugo", "wordpress 转静态站", "migrate WordPress to Hugo", "WXR to Hugo", "publish WordPress to GitHub Pages", "/wjs-converting-wp-to-hugo".

wjs-dubbing-videoSkill

Use when the user has a video + a target-language SRT and wants the video to actually speak that language — generates a time-aligned TTS voice dub. Routes by voice ID — Volcano (豆包) TTS for Chinese, edge-tts neural for any language. Defaults to one voice (single-speaker); opt-in multi-speaker via visual diarization. Outputs `*_<lang>_dub.mp4` with the dub audio in place of the original. Final mixing (audio bed + burn-in) is handed off to `/wjs-burning-subtitles`. Triggers — "配音", "中文配音", "Chinese dub", "voice over this", "dub the video", "TTS this SRT", "different voice for each speaker".