# Keeping one person (or one product) across every shot The film falls apart the moment the woman in shot 5 is not the woman in shot 2. Consistency is decided in the stills, before any video money is spent: Seedance image-to-video keeps what the start frame shows, so if every keyframe shows the same person, the clips will too. ## 1. Write the locks once In film.json, `locks.cast` and `locks.wardrobe` are single sentences pasted into every prompt through the `{{CAST}}` and `{{WARDROBE}}` tokens. Never paraphrase them between shots. - Cast: apparent age range, build, skin tone, hair colour, length and how it is worn. "A woman around 30 with sun-kissed olive skin, a slim athletic swimmer's build, long dark brown hair tied in a low loose bun." - Wardrobe: every garment with colour and cut. "A terracotta one-piece swimsuit with a scoop back and thin straps, under an open oversized cream linen shirt with rolled sleeves." - A strong, unusual wardrobe colour (terracotta, cobalt, mustard) does more for continuity than any face description: viewers track the colour. - Skip small accessories (rings, earrings, necklaces): they appear and vanish between shots. Add them only if they are the product. ## 2. Make the cast bible `build-requests.mjs --stage bible` asks for one landscape still with the same person three times: three-quarter front, profile, back, full length on a plain backdrop. Check it: same face, same proportions, clothes exactly as locked, natural hands and feet. This image is reference 1 for every keyframe with the person in it. - Synthetic cast (default): the prompt says the person is fictional and must not resemble a real or famous person. Never ask for a look-alike of anyone. - The user's own photo (`--person own-photo`): only the user's own face, or a person who gave written consent. Ask the user directly ("Is this you, or do you have this person's written consent to use their likeness in a generated film?"). If the answer is a clear yes, pass it word for word as `--consent-quote "..."`; build-shot-list.mjs saves it in film.json (`brief.consent_quote`, with the date) and build-requests.mjs will not make the bible without it. Never write the quote yourself or pick own-photo on your own; stop if the answer is not a clear yes. - Refuse photos of celebrities, public figures or minors, whatever the answer. - Privacy: send the photo inline (`--inline` / fal-run.mjs) rather than on a public link. When the film is done, delete the photo and the bible made from it from the working folders unless the user wants them kept, delete any public copy, and tell the user that fal keeps request inputs and outputs on its side for a period: they can delete them from their fal dashboard or ask fal to, and should check fal's current retention policy. ## 3. Reference images per keyframe `build-requests.mjs --stage keyframe` attaches, in this order: 1. The cast bible, when `person_in_shot` is true. 2. The location reference (usually the approved establishing still) when `use_location_ref` is true, so the architecture and landscape match. 3. The product photo when `product_in_shot` is true. It also adds the sentence "The person is the same as in reference image 1 …". GPT Image edit accepts up to 16 references; more than three dilutes each one. ## 4. Faces and Seedance (important) Seedance on fal runs a likeness check on the start frame. A clearly visible, realistic face is refused with `content_policy_violation: "likenesses of real people"`, even for a synthetic person. This happened in testing on a side-profile underwater frame. Frames passed when the face was turned away, seen from behind, in silhouette, under water from below, or small in frame (a drone shot). Design for it from the start, as good resort and fashion films do anyway: - Back and three-quarter-back views, the cheek line at most. - Silhouettes against the sun, a window or a bright sea. - Drone and wide shots where the person is under 15% of the frame height. - Close-ups of hands, hair, shoulders, feet, never the full face. - Set `face_visible: false` (the default). If the user insists on a visible face, warn them the clip may be refused, try one draft first, and keep a back-view fallback keyframe ready. If the user needs faces on screen, animate only those shots with another model and expect a different look (tested 2026-10-16 on one face-forward synthetic close-up): - Kling 3 turbo pro (`fal-ai/kling-video/v3/turbo/pro/image-to-video`, about $0.14/s; `prompt`, `image_url`, `duration` "3"–"15"): accepted it; the face stayed the same person for 3 s; it returned 1920 × 1080 with a sound track. - Veo 3.1 (`fal-ai/veo3.1/image-to-video`, $0.20/s silent, $0.40/s with audio; `duration` "4s"/"6s"/"8s"): accepted it, but the face drifted toward a different person within 4 s. Test one short draft before committing, and check the face frame by frame against the bible. This also helps consistency: a face is what drifts most between generations; hair, wardrobe colour and body shape drift least. ## 5. Tasteful framing Resort, swimwear and fashion films live or die on this; both failures below happened while making the sample. - Wardrobe covers by default: a shirt, wrap or robe over swimwear for walking and arrival shots; swimwear on its own only in the water, by the pool or in silhouette. - Say the garment stays in place: "the long linen shirt hangs to mid-thigh and covers her hips". "Shirt lifting in the breeze" gave a frame that showed the swimsuit bottom (jetty attempt 1, rejected). - Never centre the framing on hips or buttocks. A follow-from-behind underwater angle with a wide lens did exactly that (underwater attempt 2, rejected); the used version is seen from below, small, as a silhouette against the sun. - Swimwear shots are full-figure or side views (full length, silhouette, swimming across frame), not tight crops of the body. - Check every clip, not just the still, for wardrobe drift: a shirt that opens or slips, a strap that changes, fabric lifting mid-clip. Trim or re-roll. - Poster and thumbnail frames: pick the aerial, an arrival or the dusk shot, never a silhouette or swimwear frame. ## 6. What drifts, and the fix | Drift | Seen as | Fix | |---|---|---| | Hair style changes | Bun becomes loose hair mid-clip | Motion prompt: "her hair stays tied in the low bun the whole time"; avoid "smooths her hair" without that line | | Wardrobe changes | Shirt appears or vanishes, strap width changes | Name the wardrobe state per shot ("without the shirt"), keep the bible's garments, re-roll the still if a garment changed | | Extra people | A second person appears in a window or background mid-clip | Add "No other people anywhere" (build-requests adds it); avoid camera arcs that reveal new background; frame tighter | | Face turns toward camera | Silhouette becomes a lit front view | "stays in profile facing X the whole time, never turns towards the camera"; trim before it happens | | Odd hand gestures | Hands float or "pray" mid-shot when the action ends early | Give a complete action for the whole duration ("lowers her arms and stays still"); trim before the gesture | | Body proportions | Legs lengthen, hips change between shots | Keep similar lens and distance for similar sizes; re-roll the still, not the video | | Product changes | Label re-lettered, shape softened | Product photo as a reference in every product shot; product large in frame; slow camera; check every frame of the clip | ## 7. Two or more people Write one lock per person in `locks.cast` ("Person A: … Person B: …") and make one bible still showing both side by side. Keep them in the same relative positions in every shot (A always on the left). Couples read well from behind (by a fire, on a terrace), which also passes the face check. ## 8. Product as the "character" With `--product-photo`, the product is the continuity anchor: write `locks.product` like a product lock (shape, material, colours, label layout and the exact visible text), keep the product 30–50% of frame height in product shots, and never let the motion prompt spin it fast. If the label must be read on screen, the final shot of the product should be close to the keyframe (slow push-in), not an orbit.