--- name: product-reveal-video description: Turn one product photo into a 6 to 8 second cinematic hero reveal. The product fades up out of darkness, a soft light sweep travels across it and the camera pushes in slowly, while the product stays exactly as it is in the photo. Dark luxe, glowing glass, bright clean or colour pop moods, in 16:9 or 9:16, with a frame-by-frame fidelity check against the photo before delivery. metadata: type: video version: 1.0.0 category: Video & animation tagline: Use this Skill to turn a product photo into a cinematic 8-second hero reveal with the product kept exactly as it is. made-for: Brands, E-commerce sellers, Creators, Agencies generates-with: 1 hero keyframe + 1 MP4 reveal, 16:9 or 9:16, 720p, 8 s requires: Node.js 18 or newer, ffmpeg 5 or newer (for the finish and the check), and your own FAL_KEY to send the requests outside-costs: About $0.30 for the hero keyframe (GPT Image 2 edit, high) and about $3.80 for an 8-second 720p clip (Seedance 2.5). An optional 480p motion draft is about $0.45. Billed by fal to your own key. Always ask before each paid step. updated: 2026-10-16 title: Product reveal video availability: live summary: Turn a product photo into an 8-second cinematic reveal, with light sweeping across the product while it stays exactly as photographed. command: /product-reveal-video my headphones, dark luxe, 16:9 output: MP4 ยท 8 s reveal, 16:9 or 9:16, 720p + hero keyframe required-input: Product photo + mood creator: meleon --- # Product reveal video Use this skill when someone has a photo of a real product and wants the kind of short hero shot that opens a launch film or tops a product page: the product appears out of the dark, light finds its shape, the camera eases in, and nothing about the product changes. The work is split so the product stays true: an image model builds one hero keyframe with the product unchanged, a video model only adds camera and light movement to that frame, and the fade, grain and encode are done locally. ## What you need - **One product photo.** Sharp, whole product in frame, the important side facing the camera, at least 1000 px. A phone photo on a table or bed is fine. If it is blurred, cropped or the label is angled away, ask for a better one before spending anything. - **A short product description** for the prompts, e.g. "matte black over-ear headphones" or "amber glass dropper bottle with a cream label". - **The exact printed text** on the product (for `--label-text`), or confirmation that it is unbranded (`--unbranded`). - **Mood**: `dark-luxe`, `glass-glow` (glass and liquids), `bright-clean` or `colour-pop` (with a colour). No default: ask, or suggest one from `references/reveal-craft.md`. - **Aspect**: 16:9 (default) or 9:16. **Product size**: `standard` (default), `tall` (bottles, shoes standing up) or `tiny` (rings, earbuds). **Length**: 8 s by default. Do not invent the product. If the photo is missing, ask for it. ## What you make 1. A hero keyframe (JPEG, 1536 x 864 for 16:9 or 864 x 1536 for 9:16) with the product unchanged in the mood's set. 2. An MP4 reveal: 720p, 8 s, 24 fps, H.264, muted by default, under 8 MB, with a fade up from black and a soft fade out. The clip starts on black, so its first frame is never a usable poster. 3. A poster still taken after the fade (at 3 s), for any page or player that shows a still before playback. 4. The fidelity board and contact sheet you checked it with. ## How to run it Tell the person the model and the cost before every paid step, and wait for a yes. Every request goes to fal with the user's own FAL_KEY: POST the printed `input` to `https://queue.fal.run/` with the header `Authorization: Key `, poll the returned `status_url`, then fetch `response_url`. The Skill never stores keys. 1. **Intake (free).** Look at the photo with your image tool. Write a one-line product lock (shape, material, colour, parts, any text exactly as printed). Read `references/reveal-craft.md` and pick the mood, product size and camera move (`push-in` unless there is a reason not to; `locked` for small printed text; never `orbit` on a complex product). `assets/reveal-presets.json` lists what has been tested; the scripts print a note when you pick something less proven. 2. **Hero keyframe (about $0.30).** `node scripts/build-keyframe-input.mjs --photo product.jpg --product "matte black over-ear headphones" --mood dark-luxe --aspect 16:9 --unbranded --out keyframe.json` (or `--label-text "EXACT TEXT"` instead of `--unbranded`; add `--size tall` or `--size tiny` when it fits). A local photo is embedded in the request, so nothing is uploaded publicly. POST the `input` to `openai/gpt-image-2/edit` (size from the aspect, quality high, one image). Without a key, paste the prompt and photo into any GPT-Image-class image editor. Add `--draft` for a $0.03 composition check first. 3. **Check the keyframe.** Put it beside the photo: same silhouette, parts, buttons, colour, and the label spelled exactly. If it differs, re-run with a more exact `--product` line (max 3 attempts, one change each). The alternative is `fal-ai/nano-banana-pro/edit`, about $0.15, with the same `prompt` and `image_urls` but `aspect_ratio` ("16:9" or "9:16") and `resolution: "2K"` instead of `image_size` and `quality`. 4. **Optional motion draft (about $0.45).** `node scripts/build-video-input.mjs --keyframe keyframe.jpg --product "..." --mood dark-luxe --move push-in --unbranded --draft --out draft.json`, then POST `input` to `bytedance/seedance-2.0/mini/image-to-video` (`resolution` "480p", `duration` "6"). Drafts blur small text, so judge the motion and shape, not the label. 5. **Final clip (about $3.80).** `node scripts/build-video-input.mjs --keyframe keyframe.jpg --product "..." --mood dark-luxe --move push-in --unbranded --out video.json` prints the request for `bytedance/seedance-2.5/image-to-video` with `resolution` "720p", `duration` "8", `aspect_ratio` "auto" and `generate_audio` false: the settings that made `assets/preview.mp4`. Use `--duration` (4 to 30), `--resolution 1080p` (about $1.16 per second) or `--audio` only when asked. With `--label-text`, the camera defaults to `locked` and the script prints a label-drift warning; printed text drifts most when the camera moves. POST the `input`; the video is at `video.url`. 6. **Fidelity check (free).** `node scripts/check-frames.mjs --video raw.mp4 --product product.jpg --board board.jpg --sheet sheet.jpg --first-at 0 --expect-duration 8 --expect-resolution 720p`, then open both images. On a finished clip leave out `--first-at`: the first board frame is then taken at 1.4 s, after the fade. The contact sheet spreads up to 24 frames over the whole clip, however long. Check everything in `references/output-spec.md`: same product in the first, middle and last frames, the label spelled exactly, no invented lights or parts, smooth motion. 7. **Fail path: at most 3 video attempts.** Change one thing per attempt and say what: first `--move locked`, then `--duration 6`, then a different mood. View each result's board beside the photo. If it still fails, return the best clip and say exactly what differs. The alternative video model is `fal-ai/kling-video/v3/turbo/pro/image-to-video`, about $0.14 per second, with `prompt`, `image_url` and `duration` ("3" to "15") and no `resolution`, `aspect_ratio` or `generate_audio`. 8. **Finish (free).** `node scripts/finish.mjs --input raw.mp4 --output reveal__16x9_720p.mp4 --poster reveal__poster.jpg` adds the 1.2 s fade up from black, a 0.5 s fade out and fine grain, mutes it, encodes H.264 with `+faststart`, and saves a poster still at 3 s (`--poster-at` to change it). These defaults made `assets/preview.mp4`. Without the script, take the poster with `ffmpeg -ss 3 -i reveal.mp4 -frames:v 1 poster.jpg`. Add `--keep-audio` if audio was generated and wanted. Run the check once more on the finished file. 9. **Deliver** the MP4, the poster, the keyframe, and the prompts you used. Tell whoever embeds it to use the poster, not the first frame (which is black). For the other aspect, repeat from step 2 with `--aspect 9:16`; never crop the 16:9 clip. ## Files - `references/reveal-craft.md`: the three beats of a reveal, which mood and camera move suit which product, product types that go wrong (labels, black on black, glass, screens, sets), prompt patterns that worked and failed in testing, and a fixes table. - `references/output-spec.md`: sizes, formats and the pass/fail checklist. - `assets/reveal-presets.json`: the moods (set, light move, feel), camera moves, framing by product size, keyframe sizes, and what has been tested. - `assets/prompt-template.md`: the keyframe and video prompts, filled by the scripts. - `assets/generation-input.json`: models, default settings, alternatives and approximate costs. - `assets/example-input.jpg` and `assets/preview.mp4`: the phone photo of the headphones and the finished dark-luxe reveal made from it. - `scripts/build-keyframe-input.mjs`: prints the keyframe request. It calls no API. - `scripts/build-video-input.mjs`: prints the Seedance request (final or draft). It calls no API. - `scripts/check-frames.mjs`: prints the clip's length, size and audio, and writes the fidelity board and contact sheet (ffmpeg). - `scripts/finish.mjs`: fade, grain, web encode and the poster still (ffmpeg).