product-video — コードで作る製品紹介動画 は何をしますか?
製品の画面を HTML で作り直し、動きを「時刻だけで決まる」ように書き、ヘッドレスのブラウザで 1 フレームずつ撮影して動画にする。曲と効果音もブラウザの中で合成する。使うのは Node.js・ffmpeg・Chromium だけ。
このスキルには、すぐ動く雛形(assets/template/)が入っている。撮影・音・検品の道具と、30 秒の見本動画がそろっているので、仕組みをゼロから作らず、雛形を複製して中身を差し替える。
大事な前提: 自分では見えないし、聴こえない
動画を再生して確かめることはできない。だからこの作業の品質は、静止画を書き出して自分の目で見る回数と、数値で測る検品で決まる。コードを書いただけで「できたはず」と進めると、文字切れ・重なり・一瞬の乱れが必ず残る。1 場面書くたびに並べて見て、直してから次へ進む。音は聴けないので、測った数値を示し、聴感の確認は人に頼む。
守ること(理由つき)
- 見た目は時刻だけで決める。 動きは
tl.*で「何秒に」と積むか、onFrame((t) => …)で t から直接求める。CSS の animation / transition、setTimeout、Math.random()、現在時刻は使わない。どの時刻へ飛んでも同じ絵になるからこそ、並列に撮影でき、一部だけ撮り直せる。 - 書いたら見る。 1 場面書くごとに
--sheetで並べ、画像を開いて見る。場面の切り替えは 0.1〜0.2 秒きざみで見る。見ずに次の場面へ進まない。 - 文字のある部品を、ゆっくり動かさない。 ブラウザは文字の位置を画素にそろえるため、数秒かけて少しずつ動かすと文字が細かく震える。入れ物や見出しは 1 秒ほどで動かしきり、止まった絵の中で中身を動かす。ゆっくり動かしてよいのは背景の光だけ。
- 登場は
tl.in、消すのはtl.out/tl.hide。tl.fromToは「開始時刻より前は元の値のまま」なので、登場に使うと、始まる前に一瞬見えてしまう。 - 製品の画面の CSS は、画面の根のクラスの下に書く。(
.ui-chat .rowのように。).row.titleのような短い名前を裸で使うと、雛形の部品や別の画面とぶつかって、気づきにくい崩れになる。 - 読める大きさにする。 動画はスマホでも見られる。見出しは 68px 以上、入れ物の中の本文は画面上で 18px 以上(フォントサイズ × 倍率)。小さい画面は、入れ物ごと大きく置くか、見せたい所へ寄る。
- 事実を曲げない。 資料で確かめられないことは入れない。できないことを「できる」と見せない。未確認の数値、他社との比較、推薦の言葉は入れない。他社のロゴは描かず、名前は文字で書く。最後のカードに、画面が作り直しであることを小さく入れる(
brand.fine)。 - 場面の境目と大きな動きは、小節の頭に置く。 ロゴがはまる瞬間、場面の切り替え、最後のカードは、曲の一撃(
hit: true)と同じ時刻にする。これだけで全体が締まって見える。 - 音量と音色は変えない。
kit/audio.jsの値は測って釣り合いを取ってある。聴けない状態で変えると崩れる。変えるのは曲の区間(plan.js)と、効果音の合図だけ。 - 測っていないことを「確認した」と書かない。 音は聴いていないと、報告に必ず書く。
進め方
各段階の終わりに確認がある。確認を飛ばして先へ進まない(後で直すほど高くつく)。
長い作業になる。途中で文脈が圧縮されて細部を忘れたら、このファイルと、その段階の references/ を読み直す。決めた構成(場面の表)は src/js/plan.js の先頭にコメントで残しておくと、中断しても続きから始められる。
0. 準備
node "${CLAUDE_SKILL_DIR}/scripts/new.mjs" video # 雛形を video/ に複製する(場所は依頼に合わせる)
cd video && npm install --ignore-scripts
node render.mjs --sheet 0:29:2 # 見本動画の一覧が out/sheet.png に出れば準備完了
${CLAUDE_SKILL_DIR} は、この SKILL.md があるフォルダ。文字のまま見えているときは、このファイルのあるフォルダの絶対パスに読み替える。
ブラウザが無いと言われたら npx playwright install chromium。それができない環境なら、入っている Chrome か Edge を使う(環境変数 CHROME_CHANNEL=chrome か CHROME_CHANNEL=msedge を付けて実行)。ffmpeg が無ければ入れてもらう。
最初に、見本の src/js/scenes.js と、書き出した out/sheet.png を見る。部品の使い方は、説明より見本のほうが早い。
1. 調べる
動画に出す事実は、すべて出どころを持つ。README・ドキュメント・デザインの決まり(色、文字、余白)・実際の画面の文言を読み、次を書き出す。
- 誰の、どんな困りごとを、どう解決する製品か(1 文で)
- 見せたい機能と、その根拠(どの資料のどこか)
- 画面に出る本物の文言(ボタン名、状態の表示、通知の文)。作り話の文言は、実物を知る人にすぐ見抜かれる
- 実物の画面の見た目。スクリーンショットや画面のモックがあれば開いて見て、配置・色・余白・文字の大きさを写し取る。無ければ UI のコード(コンポーネント、スタイル、デザイントークン)から読み取る
- 対応環境・制約・前提(言い過ぎないために)
依頼に書かれていなければ、次は自分で決めて先へ進み、報告に書く: 尺(60〜90 秒。短い依頼なら 30 秒)、言語(製品の画面と資料の言語)、明るい場面と暗い場面の使い分け。ブランドの色・ロゴ・フォントが資料から分からないときだけ、依頼者に尋ねる。
2. 構成を決める
場面割りを表にしてから作り始める。構成の型、見出しの書き方、時間の決め方は references/direction.md にある。必ず読む。
- 伝えることは 1 つ。場面ごとの見出しも 1 つ。機能の一覧にしない
- 冒頭は製品ではなく「困りごと」から始める
- 場面の境目は小節の頭に置く(120 BPM なら 2 秒きざみ)
src/js/plan.jsのT(場面の開始時刻)とmusic(曲の区間)を、この表のとおりに書く
決めた構成は依頼者に短く見せる。返事を待たずに作り始めてよい(方向が違えば早く分かる)。
3. ブランドと画面を用意する
src/js/brand.js: 名前、ひとこと、色、フォント、ロゴ。値は製品の実物から取るsrc/css/app.cssとscenes.jsの HTML: 製品の画面の作り直し。色・寸法・文言を実物に合わせる- 動かす前に、止めた状態で
--shotして実物と見比べる。ここで似ていなければ、動かしても似ない
画面はスクリーンショットを貼らずに HTML で作り直す。部品ごとに動かせ、拡大しても鮮明で、色を場面に合わせて切り替えられるため。
4. 場面を 1 つずつ作る
scenes.js に、場面ごとの関数を書く。部品と書き方は references/kit.md にある。書き始める前に読む。
1 場面ごとに、次を繰り返す。
node render.mjs --sheet 14:26:1 # その場面を 1 秒おきに並べる → out/sheet.png を開いて見る
node render.mjs --shot 16.6,22.5 # 気になる時刻を等倍で見る → out/shots/
node render.mjs --sheet 13.4:14.6:0.1 --cols 7 --w 420 # 場面の切り替えは 0.1〜0.2 秒きざみで見る
node render.mjs --lint # 文字切れ・重なり・小さすぎる文字を機械で拾う
見るときの観点: 文字が切れていないか、重なっていないか、読める大きさか、余白が片寄っていないか、何を見ればいいかが一目で分かるか、前の場面の部品が残っていないか。
目安として、1 場面につき 3 回は見る(書いた直後、直した後、前後の切り替え)。一覧で小さくて分からない所は、--shot で等倍にして確かめる。
5. 音を付ける
曲は plan.js の区間の並びから自動で編曲される。効果音は、場面を組むときに cue("種類", 時刻) で積んだものが鳴る。詳しくは references/audio.md。
node render.mjs --audio # out/audio-master.wav。音量とピークが表示される
6. 通しで下見して、検品する
node render.mjs # 等倍で全編(30 秒の動画で数分)。out/video.mp4
node tools/qa.mjs # 形式・音量・1 フレームの乱れ・コマ落ち・真っ黒・無音
node render.mjs --sheet 0:90:1.5 --cols 6 # 全編を通して見る(秒数は動画の長さに合わせる)
✗ をすべて直す。検品の読み方と、よくある不具合の直し方は references/qa.md。
ここからが仕上げ。 最初に通った版は、たいてい「崩れてはいないが、物足りない」。全編の一覧を見て、直したい所を 5 つ以上書き出してから直す。探すもの:
- 2 秒以上、何も起きない時間
- 大きく空いた余白、片側に寄った絵、入れ物の中の空き(スマホの下半分が白い、など)
- 何が何を起こしたのか分かりにくい瞬間(押した → 変わった、の対応が見えない)
- 実物と違う文言・色・配置
5 つ見つからないときは、見る間隔が粗い。1 秒おき、気になる場面は 0.25 秒おきで見直す。
7. 本番を書き出す
node render.mjs --scale 2 --keep-frames # 2 倍で撮影して縮小(等倍の 3〜4 倍の時間)。裏で走らせる
node tools/qa.mjs
node tools/extras.mjs web # 10 MB 未満の軽量版(チャットや GitHub に貼れる)
node tools/extras.mjs poster 15.9 # 見出し用の静止画(内容がいちばん伝わる時刻)
2 倍で撮るのは、輪郭をなめらかにし、文字の震えを半分にするため。途中で止まったら --resume --reuse-audio を付けて続きから撮る。一部だけ直したときは、その区間のフレーム(out/frames/ の該当番号)を消して --resume すれば、そこだけ撮り直せる。
8. 報告する
次を、短く、正直に書く(型は references/qa.md の最後)。
- できたもの(ファイルの場所、尺、解像度)と、構成の要約
- 確かめたこと(検品の結果)と、確かめられていないこと。音は聴いていないので、「数値では基準内。聴感の確認をお願いします」と必ず書く
- 自分で決めたこと(尺、言語、色の扱いなど)と、資料から確かめられず入れなかったこと
- 画面が作り直しであること。直したいときの頼み方
手直しを頼まれたとき
この雛形で作った動画を直すときは、上の手順を最初からやらない。
references/kit.mdと、直す所のコードを読む。見出しや画面の文言はscenes.js、最後のカードの文字はbrand.js、時間割と曲はplan.js、画面の見た目はapp.css- 直す
- 直した場面と、その前後の切り替えを
--shot/--sheetで見る。--lintもかける - 場面の長さや曲の区間を変えたときは、
node render.mjs --audioで警告が出ないことも確かめる - 動画ファイルまで頼まれていれば、手順 6〜7 で書き出す。頼まれていなければ、どこを見て確かめたかを報告し、書き出すかどうかを尋ねる
node render.mjs をオプションなしで実行すると、全編の書き出しが始まる(数分以上かかる)。確認だけのときは、必ず --shot --sheet --lint のどれかを付ける。使い方は node render.mjs --help。
できばえの基準
出す前に、自分で確かめる。
- 音を消しても、見出しだけで話が通じる
- 最初の 3 秒で「自分の話だ」と思える困りごとが出ている
- どの場面でも、見るべき所が 1 つに決まっている(同時に 2 か所を動かしていない)
- 製品を知る人が見て、画面と文言に違和感がない
--lintとtools/qa.mjsに✗がない- 場面の切り替えを 0.1〜0.2 秒きざみで全部見た
参考資料
| ファイル | 内容 | いつ読むか |
|---|---|---|
references/direction.md | 構成の型、時間割、見出しの書き方、画面の置き方、動かし方 | 構成を決める前(必ず) |
references/kit.md | 雛形のファイルの役割と、エンジン・部品の使い方 | 場面を書く前(必ず) |
references/audio.md | 曲の区間、効果音の合図の一覧、測り方 | 音を付けるとき |
references/qa.md | 検品の読み方、よくある不具合と直し方、報告の型 | 下見と本番のとき |
assets/template/src/js/scenes.js | 見本の動画。部品の使い方の実例 | 最初に |