promo-video について
promo-videoは、割引や期間限定オファーを告知する6〜15秒のセール動画を作るスキルです。データ駆動のRemotionテンプレートで単一のオファーを表現し、価格の正確さ、フレーム駆動のアニメーション、レンダリング検証を重視します。
主な機能
- 01割引とプロモコードの動画作成
- 02旧価格の取り消し線と新価格の連動表示
- 03実際の期限による緊急性の提示
- 04オファーデータからの動画一括生成
- 05フレーム確認とMP4出力の検証
活用シーン
- 01ブラックフライデーやフラッシュセール広告の制作
- 02商品の通常価格と割引価格の表示
- 03コードと期限を含むエンドカードの作成
- 04商品価格表からの販促動画生成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ iart-ai/ ecommerce-video-skills --skill promo-videoインストール後、Claude Code で/promo-videoを入力して読み込まれたか確認します。
同梱ファイルREADME.mdreferences/promo-components.md
詳細
セール告知動画
視聴者に今すぐ行動を促す、6~15秒のインパクトあるセール動画を作成します。ひとつだけのオファーを告知し、割引額を目立たせ、取り消し線付きで価格を「元の価格→現在の価格」へと下げ、プロモコードと期限を読みやすく表示し、CTAで締めくくります。これはオファーの告知であり、機能紹介広告でも、お客様の声でもありません。勢いと正確な数字、緊急性が重要です。
使用する場面
- 割引や割引率の告知(「40% OFF」、「$20 off」)。
- 取り消し線付きで価格を「元の価格→現在の価格」へと下げる演出。
- ブラックフライデー/フラッシュセール/クリアランス/発売週/季節限定の告知動画。
- 期限やカウントダウンを含むプロモコードの告知。
- 多数の商品やオファーにひとつのプロモ用テンプレートを適用(価格表 → N 本の動画)。
パフォーマンス広告のバリエーションには ad-creative-video を、お客様の声には testimonial-video を使用してください。オファーに集中しましょう。
展開
セール動画は短く、順序立てて構成します。各ビートの役割はひとつだけです。ふたつの役割を重ねないでください。
| ビート | 役割 | 長さ(10秒中) |
|---|---|---|
| フック | ブランド+イベント(「BLACK FRIDAY」)を瞬時に表示 | 0~1.5秒 |
| 割引の告知 | 大きな数字(「40% OFF」)を表示 | 1.5~4秒 |
| 元の価格→現在の価格 | 元の価格に取り消し線を引き、新しい価格をカウントダウン | 4~7秒 |
| 商品 | オファー対象の商品をひとつ、主役として映す | (価格表示の下、4~8秒) |
| コード+緊急性 | プロモコード+期限を静止表示 | 7~9秒 |
| CTA | 「SHOP NOW」+URLをきれいに表示して締める | 9~10秒 |
6秒に短縮する場合は(商品ビートをカット)、15秒に延ばす場合は(各ビートに余裕を持たせて)調整します。フックは決して長くしないでください。
絶対に守るべき2つのルール
- 数字がメッセージです。正確な値を保ちましょう。 価格と割引率は、二重に手入力せず、必ず計算してください。
wasと割引額からnowと% offを導き、食い違いが起きないようにします。間違った価格を表示する動画は、動画がないよりも悪い結果になります。通貨はセント単位に丸め、Intl.NumberFormatで書式設定し、数字のカウント中に揺れないようtabular-numsを使用してください。 - ひとつのオファー、各フレームの焦点はひとつ。 割引も、コードも、CTAも、それぞれひとつだけです。競合するオファーは緊急性を損ないます。特典が2つある場合は、動画を2本作成してください。
特徴的な演出:取り消し線付きの「元の価格→現在の価格」
3つの動きを同時に連動させ、同期を保つ必要があります。取り消し線が元の価格を横切るように伸び、新しい価格が最終値までカウントダウンし、最後に小さなオーバーシュートで着地を強調します。3つすべてを useCurrentFrame() から制御してください。CSSトランジションやJSタイマーは使わないでください。これにより、サーバーでのレンダリング時にもずれません。
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";
const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
export const PriceDrop = ({ was = 79.0, now = 47.4, startAt = 30 }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const f = frame - startAt;
// 1. strike-through line draws L→R over ~0.4s
const strike = interpolate(f, [0, 12], [0, 100], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
// 2. new price counts from `was` down to `now`, eased
const t = spring({ frame: f - 8, fps, config: { damping: 18, mass: 0.6 } });
const shown = was + (now - was) * t;
// 3. landing pop on the final value
const pop = interpolate(t, [0.9, 1], [1.12, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
return (
<div style={{ fontVariantNumeric: "tabular-nums", textAlign: "center" }}>
<span style={{ position: "relative", opacity: 0.55, fontSize: 48 }}>
{usd.format(was)}
<span style={{ position: "absolute", left: 0, top: "50%", height: 4, background: "#ff3b3b",
width: `${strike}%`, transformOrigin: "left" }} />
</span>
<div style={{ fontSize: 96, fontWeight: 800, transform: `scale(${pop})` }}>
{usd.format(shown)}
</div>
</div>
);
};
順序が重要です。まず元の価格に取り消し線を引き、その後に新しい価格を下げます。同時に取り消し線を引いてカウントダウンすると、ちらつきのように見えます。プロパティに連動する割引バッジ、コードの表示、カウントダウン、CTAを含む全体構成は、references/promo-components.md を参照してください。
割引の告知とプロモコード
画面上では、割引率を最も目立つ要素にします。ブランドよりも、商品よりも大きく表示してください。値は計算し、手入力しないでください。
const pct = Math.round((1 - now / was) * 100); // 79 → 47.4 ⇒ 40
const off = was - now; // for "$X off" framing
価格帯に応じて表示方法を選びます。高価格帯の商品では割合(「40% OFF」は「$32 off」より効果的)、低価格帯の商品では定額(「$5 off」は「8% off」より効果的)が適しています。コードはタップできそうなチップ(等幅フォント、破線の枠線、明るい背景)として表示し、静止させてください。動くコードは読みにくく、スクリーンショットにも収められません。緊急性を伝えるコードはコンバージョン率が高まります。FLASH40、TODAY20、LASTCHANCE などを使用してください。
誠実な緊急性
緊急性がコンバージョン率を高めるのは、それが本物である場合だけです。「日曜午後11:59に終了」のように具体的な期限を示すか、リアルタイムに見えるカウントダウンを表示してください。偽のタイマーは使わないでください。視聴者が時間限定オファーを読むには約2秒必要です。期限のビートは静止表示し、短時間だけ見せる演出は避けてください。カウントダウンは価格と競わせず、コードの近くの独立した行に配置します。
// frame → mm:ss remaining, derived from a deadline prop (deterministic per frame)
const remaining = Math.max(0, deadlineSec - frame / fps);
const mm = String(Math.floor(remaining / 60)).padStart(2, "0");
const ss = String(Math.floor(remaining % 60)).padStart(2, "0");
モーションの方針:エネルギッシュに、ただし混乱させない
セール動画の勢いは、キレがあり、一貫した動きから生まれます。素早いスプリングアニメーションでの登場(damping ~12、オーバーシュート)、アクセントに合わせたハードカット、割引を示すひとつのアクセントカラー(鮮やかな赤や緑)を全体で統一して使います。すべてのビートで同じイージングカーブを使用し、動きの速さから自信が伝わるようにしてください。緊急性を弱めるドリフトやパララックスは避けましょう。音楽を付ける場合は、最も力強い音のビートに合わせて割引の告知を着地させてください。
テンプレート × データ — 多数の商品を1つのテンプレートで
コード駆動のプロモーションがもたらすメリット:価格・オファーのテーブルから商品ごとの動画をレンダリングできます。価格はデザイナーが再入力したものではなくデータから取得するため、正確さが保証されます。オファーは入力プロップにし、何もハードコードしないでください。
// one composition, different offer → different video
export const Promo = ({ offer }) => { /* reads offer.was/now/code/deadline/img — no constants */ };
# render the promo for every offer row in /offers
for f in offers/*.json; do
npx remotion render Promo "out/$(basename "$f" .json).mp4" --props="$f"
done
レンダリング前に各行を検証し(now < was、コードが存在する、画像が存在する)、不正な行を見逃して誤った価格を公開するのではなく、明確に失敗するようにします。色・フォント・CTA は1つのテーマオブジェクトにまとめ、200件のプロモーションでもブランドを統一し、数字だけを変更できるようにします。オファーのスキーマ、検証、バッチスクリプトについては references/promo-components.md を参照してください。
出力チェックリスト
nowと% offはwasから計算し、二度入力しません。丸め処理を行い、Intl.NumberFormatでフォーマットし、tabular-numsを使います。- 取り消し線を先に描画し、新しい価格を後から表示します。どちらも
useCurrentFrame()のみから求める純粋関数にします。 - 1本の動画につき、オファー1つ、コード1つ、CTA 1つにします。割引を最も目立つ要素にします。
- 緊急性は実際の期限・カウントダウンで示し、2秒以上表示します。偽の点滅タイマーは使いません。
- すべてのビートで同じイーズインカーブと節約額のアクセントカラーを使います。
- オファーを入力プロップにし、バッチレンダリング前に各データ行を検証します(now < was)。
納品と検証(レンダリングした静止画 → MP4)
同梱ヘルパー(
scripts/):scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.pngで静止画を並べ、scripts/probe-mp4.sh out.mp4 [WxH] [fps]でエンコードを検証します。scripts/README.mdを参照してください。
これはヘビーティアです。納品物はライブページではなくMP4です。プロモーションには正確な金額が表示されるため、検証の大半は 数字が正しいか、商品画像が実際に表示されているか の確認です。
出力要件:
- Remotion プロジェクトにコンポジションを登録します(
<Composition>+ zodschema+defaultProps)。割引の表示、取り消し線、カウントダウン、CTA はすべてuseCurrentFrame()のみから求める純粋関数にします(CSS トランジション、タイマー、Date.now()は使いません)。 - 商品画像は
staticFile()で読み込み、delayRender/continueRenderで制御します。フレームがレンダリングされる前にヒーローショット(とブランドフォント)が確実に読み込まれるようにします。now/% offはwasから計算し、二度入力しません。 - 納品物 = レンダリング済みの
out/*.mp4とプロジェクト(オファー行ごとに再レンダリングします)。
検証ループ — 静止画をレンダリング → 確認 → エンコード。 まず低コストの PNG で確認し、数字と画像が正しいことを確かめてから動画を一度だけ作成します。
# Frame-exact stills WITH THE OFFER PROPS YOU'LL SHIP, not defaultProps
npx remotion still Promo out/f-discount.png --frame=60 --props=offer.json # "40% OFF" big number landed
npx remotion still Promo out/f-price.png --frame=120 --props=offer.json # was struck through, now settled
npx remotion still Promo out/f-cta.png --frame=270 --props=offer.json # code + deadline + CTA end-card
# end frame = durationInFrames - 1 (npx remotion compositions reads it)
各 PNG で、忠実性(was/now/% off が正確であること、was→now の取り消し線が古い価格に引かれていること、プロモーションコードの綴りが正しいこと、商品画像が正しいこと)とアーティファクト(画像が空白/未読み込み、数字がちらつく/誤っている、価格がはみ出す/キャンバス外に出る、取り消し線の位置が違う、CTA/コードがタイトルセーフエリア外にある、アスペクト比が違う/レターボックスが入る)を確認します。
# Only after stills are clean:
npx remotion render Promo out/promo.mp4 --props=offer.json
npx remotion render Promo out/promo.gif --props=offer.json --codec=gif # README first-screen proof
バッチ処理(1つのテンプレート、多数の商品): 価格テーブルから N 本の動画をレンダリングする場合、カタログをバッチレンダリングする前に、代表的なオファー1件のプロップを静止画で検証します。誤った価格や空白画像は、一度見つければ N 回公開してしまう事態を防げます。
完了前に確認すること:
- 割引/価格/CTA の静止画がエラーなくレンダリングされ、商品画像が実際に読み込まれている(空白でない)。
was/now/% offが正確である(wasから計算)。古い価格に取り消し線が引かれ、新しい価格が確定表示され、コード/期限が正しい。- すべての動きがフレーム駆動である。CSS トランジション/タイマー/
Date.now()/Math.random()を使っていない。 - 納品するオファーのプロップが正しくレンダリングされる。
defaultPropsだけで確認しない。 - MP4 全体をエンコードして再生できる。README 用の GIF レンダリングは任意です。
参考ファイル
references/promo-components.md— オファーのプロップで駆動する、実行可能な Remotion プロモーションコンポジションの完全な例。割引バッジ、was→now の取り消し線+カウントダウン、プロモーションコードのチップ、ライブカウントダウン、CTA エンドカードに加え、オファーのスキーマ、行ごとの検証、テーマオブジェクト、N 商品向けのテンプレート×データのバッチレンダリングスクリプトを含みます。