30x-web-to-video 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.mjs CHANGED
@@ -26,8 +26,10 @@ const HELP = `
26
26
 
27
27
  Usage:
28
28
  npx 30x-web-to-video <brand-url> [--out <dir>] [--agent] [--no-harvest]
29
+ npx 30x-web-to-video --global # install skill for ALL projects (~/.claude/skills)
29
30
 
30
31
  Options:
32
+ --global Install the skill user-wide (~/.claude/skills) instead of per-project
31
33
  --out <dir> Output project directory (default: ./<brand>-launch-video)
32
34
  --agent After harvest, launch Claude Code on the build prompt
33
35
  (requires the \`claude\` CLI; agent time/tokens are yours)
@@ -47,9 +49,9 @@ Optional: ELEVENLABS_API_KEY in the project .env for premium narration
47
49
  (falls back to Kokoro local TTS — zero keys needed).
48
50
  `;
49
51
 
50
- if (!url || flags.has("--help") || flags.has("-h")) {
52
+ if (flags.has("--help") || flags.has("-h") || (!url && !flags.has("--global"))) {
51
53
  console.log(HELP.trim());
52
- process.exit(url ? 0 : 1);
54
+ process.exit(url || flags.has("--global") ? 0 : 1);
53
55
  }
54
56
 
55
57
  const slug = (() => {
@@ -66,11 +68,18 @@ const outDir = resolve(outIdx > -1 && args[outIdx + 1] ? args[outIdx + 1] : `./$
66
68
 
67
69
  // ── 1) install the skill into the project-local .claude/skills ──────────
68
70
  const skillSrc = join(__dirname, "skill");
69
- const skillDst = join(process.cwd(), ".claude", "skills", "30x-web-to-video");
71
+ const skillDst = flags.has("--global")
72
+ ? join(process.env.HOME || process.cwd(), ".claude", "skills", "30x-web-to-video")
73
+ : join(process.cwd(), ".claude", "skills", "30x-web-to-video");
70
74
  mkdirSync(dirname(skillDst), { recursive: true });
71
75
  cpSync(skillSrc, skillDst, { recursive: true });
72
76
  console.log(`✔ skill installed → ${skillDst}`);
73
77
 
78
+ if (flags.has("--global") && !url) {
79
+ console.log("✔ skill installed user-wide. Open Claude Code anywhere and say: 给 <brand-url> 做个 launch video");
80
+ process.exit(0);
81
+ }
82
+
74
83
  // ── 2) deterministic harvest + scaffold ─────────────────────────────────
75
84
  if (!flags.has("--no-harvest")) {
76
85
  const tsxCli = require.resolve("tsx/cli");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "30x-web-to-video",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "One URL in, an agency-grade brand launch video out. Harvests the site, scaffolds a Remotion project, and hands Claude Code a battle-tested taste codex (10-brand validated) to design the five acts.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -105,6 +105,7 @@ Worked example(happy-model, 2026-07-04 — **这是推导方法的示范,不
105
105
  - 颜色、字体、光的性格全部来自该品牌的 brand-report(designTruth),不继承任何往期项目。
106
106
  - failover 一行是关键教训:卖点的领域要按**这个产品的真实语义**判断,别被词面带偏("failover"听着像地理,实际是 provider 层)。
107
107
  - 相邻 beat 必须换世界(status page 世界 → 请求流世界 → 地理世界),两个 beat 共用一套视觉公式(如连续两张"地图+弧线")已被用户点名毙掉。
108
+ - **换构图不换世界观(Laper 事故 2026-07-05)**:换世界指的是构图系统与 artifact 换,不是色系与字系换。一部片只有一套底色谱系、一套字体声部、一套光的语言;某一幕突然跳成芥末金或深绿海报 = 世界观断裂,用户判词"不统一、不高级、没有品牌味"。多样性活在构图与 artifact 层,统一性锁死在 theme 层——beat 再怎么换,观众要能从任何一帧认出这是同一部片。
108
109
 
109
110
  **跨视频测试:** 拿本 skill 产的两个不同品牌的视频各抽一帧并排——如果互换品牌 logo 后毫无违和,自适应失败。
110
111
 
@@ -35,6 +35,7 @@ These patterns instantly signal "AI-generated." Never use:
35
35
  - **Heartbeat motion — any rhythmic scale/brightness oscillation** (downbeat scale pulse on the whole frame, `1 + Math.sin(frame/N) * k` breathing on glows/blobs/backgrounds, BGM-synced throb). User verdict 2026-07-04: "心跳的那种动效 以后别用". The throb reads as anxious, not alive. Slow positional drift (`translateX/Y` sine float) is still fine — atmosphere moves, it never *pumps*. Beat-sync stays for CUT TIMING only (transitions/act boundaries on downbeats), never as a continuous visual pulse
36
36
  - **Decorative horizontal bars / rules / divider lines** — animated accent bars under headlines, metric progress-bar tracks, `borderBottom` hairlines between rows, vertical divider strokes between logo/stat groups. User verdict 2026-07-04: "我不喜欢那些横杠杠". Group with spacing and weight hierarchy instead; a real number (9/10) says more than a filled track
37
37
  - **Symbol/dingbat decoration rows** — star-rating glyphs, sparkles, diamonds, any repeated icon strip used as ornament. User verdict 2026-07-04: "symbols之类的 (不要)". Ratings become numeric text; grouping becomes whitespace
38
+ - **Brand-native exception for the two bans above**: these ban *decorative defaults*, not brand truth. If the brand's own site verifiably uses hairlines or symbol marks as its design language (screenshot evidence, not vibes), reproducing that language is Law-4 real-asset fidelity, not a violation — cite the evidence in the act header comment. A star baked inside a product screenshot is always fine; a star you *drew* needs the brand to have drawn it first
38
39
  - **Text overlaid on a full-bleed motion asset** — when a real motion graphic (product film, app showcase video) plays full-screen, it IS the statement; no headline on top. User verdict 2026-07-04: "动效图上面就不要字了 因为那个是全屏". Either full-bleed textless, or contained in a panel with type outside — never both at once
39
40
  - Two adjacent beats sharing the same visual formula (e.g. "map + arcs" twice in a row) — each beat gets its own world; see composition diversity in composition.md
40
41
 
@@ -240,6 +240,8 @@ sed 's|//.*||' src/MainVideo.tsx | grep -qE 'staticFile\("brand/homepage|findAss
240
240
 
241
241
  ### Visual Classification — demo / cover (MANDATORY — BLOCKING)
242
242
 
243
+ **Spoken-watermark check (BLOCKING, Laper incident 2026-07-05).** Free-library tracks routinely carry spoken tags ("royalty free music", channel names) baked into the audio. Before accepting any downloaded BGM: extract three 8-10s windows (head / peak / tail) with ffmpeg and inspect for speech — e.g. `ffmpeg -ss <t> -t 8 -i bgm.mp3 -af silencedetect=n=-30dB -f null -` plus an actual listen-equivalent (whisper-tiny transcription of the windows works: any transcribed words = reject the track). A track that fails goes back to the pool; never ship a watermark to the user's ears.
244
+
243
245
  **Dedup is necessary but not sufficient.** Even with unique images, pairing the wrong *kind* of image with the wrong *kind* of copy destroys trust. A Raycast og-image with "Your shortcut to everything" baked into the pixels must not have another scraped headline overlaid on it — that is the content-mismatch bug the user called out as *"素材非常的不 make sense"*.
244
246
 
245
247
  **Before composing any scene, classify every harvested visual into exactly one bucket:**