> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bfl.ml/llms.txt
> Use this file to discover all available pages before exploring further.

# Text-to-Video

> Learn how to prompt FLUX 3 for text-to-video generation with stronger action, camera language, pacing, lighting, and scene continuity.

export const PromptAnatomy = ({segments, examples, roles, caption}) => {
  const list = examples && examples.length ? examples : [{
    segments: segments || []
  }];
  const [active, setActive] = useState(0);
  const [copied, setCopied] = useState(-1);
  const [edges, setEdges] = useState({
    left: false,
    right: list.length > 1
  });
  const trackRef = useRef(null);
  const wiredRef = useRef(false);
  const ROLE_DEFS = roles || [{
    key: "camera",
    label: "Camera"
  }, {
    key: "subject",
    label: "Subject"
  }, {
    key: "motion",
    label: "Motion"
  }, {
    key: "environment",
    label: "Environment"
  }, {
    key: "style",
    label: "Style"
  }];
  const COLORS = {
    camera: "59, 130, 246",
    subject: "217, 119, 6",
    motion: "219, 39, 119",
    environment: "5, 150, 105",
    style: "139, 92, 246"
  };
  const hue = role => COLORS[role] || "72, 106, 88";
  const copy = (segs, i) => {
    const text = segs.map(s => s.t).join("");
    try {
      navigator.clipboard.writeText(text);
      setCopied(i);
      setTimeout(() => setCopied(c => c === i ? -1 : c), 2000);
    } catch (e) {}
  };
  const startVideo = event => {
    const v = event.currentTarget;
    v.muted = true;
    const p = v.play?.();
    if (p && typeof p.catch === "function") p.catch(() => {});
  };
  const updateEdges = el => {
    if (!el) return;
    const max = el.scrollWidth - el.clientWidth;
    const next = {
      left: el.scrollLeft > 4,
      right: el.scrollLeft < max - 4
    };
    setEdges(prev => prev.left === next.left && prev.right === next.right ? prev : next);
  };
  const scrollToIndex = i => {
    const el = trackRef.current;
    if (!el) return;
    const clamped = Math.max(0, Math.min(i, list.length - 1));
    el.scrollTo({
      left: clamped * el.clientWidth,
      behavior: "smooth"
    });
  };
  const attachTrack = el => {
    trackRef.current = el;
    if (!el || wiredRef.current) return;
    wiredRef.current = true;
    if (typeof requestAnimationFrame !== "undefined") {
      requestAnimationFrame(() => updateEdges(el));
    } else {
      updateEdges(el);
    }
    if (typeof IntersectionObserver !== "undefined") {
      const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
          const v = entry.target.querySelector("video");
          if (entry.isIntersecting) {
            const idx = Number(entry.target.getAttribute("data-index"));
            if (!Number.isNaN(idx)) setActive(idx);
            if (v) {
              v.muted = true;
              const p = v.play?.();
              if (p && typeof p.catch === "function") p.catch(() => {});
            }
          } else if (v) {
            v.pause?.();
          }
        });
      }, {
        root: el,
        threshold: 0.6
      });
      Array.from(el.children).forEach(child => observer.observe(child));
    }
  };
  const hasTabs = list.length > 1;
  return <div className="not-prose prompt-anatomy">
      {hasTabs ? <div className="prompt-anatomy__tabs" role="tablist">
          {list.map((ex, i) => <button key={i} type="button" role="tab" aria-selected={i === active ? "true" : "false"} className={`prompt-anatomy__tab${i === active ? " is-active" : ""}`} onClick={() => scrollToIndex(i)}>
              {ex.label || `Example ${i + 1}`}
            </button>)}
        </div> : null}

      <div className="prompt-anatomy__slider">
        {hasTabs ? <button type="button" className="prompt-anatomy__arrow prompt-anatomy__arrow--prev" onClick={() => scrollToIndex(active - 1)} disabled={!edges.left} aria-label="Previous example">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <polyline points="15 18 9 12 15 6" />
            </svg>
          </button> : null}

        <div className="prompt-anatomy__track" ref={attachTrack} onScroll={e => updateEdges(e.currentTarget)}>
          {list.map((ex, i) => {
    const segs = ex.segments || [];
    const present = ROLE_DEFS.filter(r => segs.some(s => s.role === r.key));
    return <article key={i} className="prompt-anatomy__slide" data-index={i}>
                {ex.video ? <div className="prompt-anatomy__media">
                    <video src={ex.video} poster={ex.poster} autoPlay loop muted playsInline preload="metadata" onLoadedData={startVideo} onCanPlay={startVideo} aria-label={ex.alt || ""} />
                  </div> : null}

                <p className="prompt-anatomy__prompt">
                  {segs.map((s, j) => s.role ? <span key={j} className="prompt-anatomy__seg" style={{
      textDecorationColor: `rgb(${hue(s.role)})`
    }}>
                        {s.t}
                      </span> : <span key={j}>{s.t}</span>)}
                </p>

                <div className="prompt-anatomy__footer">
                  <ul className="prompt-anatomy__legend">
                    {present.map(r => <li key={r.key} className="prompt-anatomy__legend-item">
                        <span className="prompt-anatomy__dot" style={{
      background: `rgb(${hue(r.key)})`
    }} aria-hidden="true" />
                        {r.label}
                      </li>)}
                  </ul>
                  <button type="button" className="prompt-anatomy__copy" onClick={() => copy(segs, i)} data-copied={copied === i ? "true" : "false"}>
                    {copied === i ? "Copied!" : "Copy prompt"}
                  </button>
                </div>
              </article>;
  })}
        </div>

        {hasTabs ? <button type="button" className="prompt-anatomy__arrow prompt-anatomy__arrow--next" onClick={() => scrollToIndex(active + 1)} disabled={!edges.right} aria-label="Next example">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <polyline points="9 18 15 12 9 6" />
            </svg>
          </button> : null}
      </div>

      {caption ? <p className="prompt-anatomy__caption">{caption}</p> : null}
    </div>;
};

export const MutedVideo = ({src, poster, alt = "", aspectRatio = "16 / 9", borderRadius = "0.75rem"}) => {
  const videoRef = useRef(null);
  const [muted, setMuted] = useState(true);
  const start = event => {
    const v = event.currentTarget;
    v.muted = muted;
    const p = v.play?.();
    if (p && typeof p.catch === "function") p.catch(() => {});
  };
  const toggleMute = () => {
    const v = videoRef.current;
    const next = !muted;
    setMuted(next);
    if (v) v.muted = next;
  };
  const iconBtn = {
    position: "absolute",
    top: "0.9rem",
    right: "0.9rem",
    zIndex: 3,
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    width: "2.4rem",
    height: "2.4rem",
    padding: 0,
    borderRadius: "999px",
    border: "none",
    background: "rgba(12, 14, 18, 0.62)",
    backdropFilter: "blur(6px)",
    color: "#fff",
    cursor: "pointer",
    transition: "background 160ms ease"
  };
  return <div className="not-prose" style={{
    position: "relative",
    width: "100%",
    aspectRatio,
    borderRadius,
    overflow: "hidden",
    background: "#0c0e12"
  }}>
      <video ref={videoRef} src={src} poster={poster} autoPlay loop muted={muted} playsInline preload="metadata" onCanPlay={start} onLoadedData={start} aria-label={alt} style={{
    position: "absolute",
    inset: 0,
    width: "100%",
    height: "100%",
    objectFit: "cover",
    display: "block"
  }} />
      <button type="button" onClick={toggleMute} aria-label={muted ? "Unmute" : "Mute"} style={iconBtn}>
        {muted ? <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
            <line x1="23" y1="9" x2="17" y2="15" />
            <line x1="17" y1="9" x2="23" y2="15" />
          </svg> : <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
            <path d="M15.54 8.46a5 5 0 0 1 0 7.07" />
            <path d="M19.07 4.93a10 10 0 0 1 0 14.14" />
          </svg>}
      </button>
    </div>;
};

export const PromptDisplay = ({prompt}) => {
  const [copied, setCopied] = useState(false);
  const copy = () => {
    navigator.clipboard.writeText(prompt);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };
  return <div className="not-prose" style={{
    marginTop: "1rem"
  }}>
      <div style={{
    backgroundColor: "#1a1a1a",
    borderRadius: "1rem",
    padding: "1.25rem 1.5rem",
    display: "flex",
    flexDirection: "column",
    gap: "1rem"
  }}>
        <p style={{
    color: "#e5e5e5",
    fontSize: "1rem",
    lineHeight: 1.6,
    margin: 0,
    fontFamily: "inherit"
  }}>
          {prompt}
        </p>
        <div style={{
    display: "flex",
    justifyContent: "flex-end"
  }}>
          <button onClick={copy} style={{
    backgroundColor: copied ? "#3d8a5b" : "var(--aspen-evergreen, #486A58)",
    color: "#fff",
    border: "none",
    borderRadius: "0.375rem",
    padding: "0.25rem 0.6rem",
    fontSize: "0.7rem",
    fontWeight: 600,
    cursor: "pointer",
    transition: "background-color 0.2s"
  }}>
            {copied ? "Copied!" : "Copy prompt"}
          </button>
        </div>
      </div>
    </div>;
};

<Columns cols={2}>
  <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/9b5ab883bfd9c68fec643908cd283357954b8187.mp4" alt="FLUX 3 text-to-video output" />

  <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/b5e1de89047f707c5717ee5d712e19fddbe5884d.mp4" alt="FLUX 3 text-to-video output" />
</Columns>

FLUX 3 understands a wide range of prompts and turns even simple ideas into
creative videos. You can prompt with a short phrase, long natural language,
timestep prompting, and much more. For longer shots we recommend a format — the
[prompt schema](#prompt-schema) below — but it's only one of many ways to
generate FLUX 3 videos.

## Before you prompt

FLUX 3 understands multiple prompting formats. Explore each one below:

<Tabs>
  <Tab title="Short">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/e4d7af7096056c7b37a1f44cbc8c14e9e56cf6a8.mp4" alt="A red fox leaping through fresh snow" />
    </div>

    ```text wrap theme={null}
    A red fox leaping through fresh snow, telephoto.
    ```
  </Tab>

  <Tab title="Long natural language">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/32209d3aa9091f6445b3d152eb236b28f73819d6.mp4" alt="A cozy ramen shop on a rainy Tokyo night" />
    </div>

    ```text wrap theme={null}
    A cozy ramen shop on a rainy Tokyo night: steam rising from the broth, neon reflections in the window puddles, the cook working calmly. The camera drifts slowly past the counter. Rain patter and quiet kitchen sounds.
    ```
  </Tab>

  <Tab title="Timestep">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/79c23904555a1fef231d3ba3ea3a6e0323a3c036.mp4" alt="Desert highway hard-cut sequence" />
    </div>

    ```text wrap theme={null}
    SHOT ONE: wide aerial of a desert highway at dawn, a single red car speeding through. HARD CUT. SHOT TWO: interior close-up, the driver's hands drumming the wheel. HARD CUT. SHOT THREE: from the roadside, the car shrinks into the heat haze. One music bed across all three shots.
    ```
  </Tab>

  <Tab title="Other formats">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/2671eb55d6e9bc9ee714f7af1f6108daf87b6031.mp4" alt="Weather presenter speaking to camera" />
    </div>

    ```text wrap theme={null}
    A weather presenter on camera in front of a stylized storm map, speaking to the lens: "Storm season is here — and this time, we're ready." Confident delivery, clean studio lighting. No on-screen text, no subtitles.
    ```
  </Tab>
</Tabs>

For the best results, think of your prompt as **directing a scene**, not describing a collection of objects. Clearly define what is happening, how subjects move, how the camera behaves, and the overall atmosphere. Well-structured prompts with explicit motion, intentional shot language, and a clear narrative consistently produce stronger outputs.

## Short vs long prompt

FLUX 3 takes short prompts and interprets them into a full story. Giving the model more freedom can lead to surprising, fresh results; longer prompts lead to more precise ones. Experiment and find what works for your use case.

<Columns cols={2}>
  <div>
    <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/069a1594defbdba4bc1a4cbc9c89164d50833f58.mp4" alt="Short prompt result" />

    <p style={{ textAlign: "center", marginTop: "0.5rem", opacity: 0.7 }}>Short prompt</p>

    ```text wrap theme={null}
    A red fox leaping through fresh snow, telephoto.
    ```
  </div>

  <div>
    <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/175098a7cdc0c1b520fe67f3362319969542e3b4.mp4" alt="Long prompt result" />

    <p style={{ textAlign: "center", marginTop: "0.5rem", opacity: 0.7 }}>Long prompt</p>

    ```text wrap theme={null}
    A cozy ramen shop on a rainy Tokyo night: steam rising from the broth, neon reflections in the window puddles, the cook working calmly. The camera drifts slowly past the counter. Rain patter and quiet kitchen sounds.
    ```
  </div>
</Columns>

|              | Short prompt                                            | Long prompt                                           |
| ------------ | ------------------------------------------------------- | ----------------------------------------------------- |
| **Control**  | The model fills in framing, motion, and mood            | You direct scene, camera, pacing, and audio           |
| **Best for** | Fast exploration, single clear subject, happy accidents | Specific shots, multi-element scenes, consistent look |
| **Risk**     | Key details may be left to chance                       | Over-stuffing can make motion less coherent           |

<Tip>
  Start short to explore an idea, then lengthen the prompt to lock in the details that matter. Add camera, motion, and atmosphere only where they improve control. Length alone is not the goal.
</Tip>

## Prompt schema

FLUX 3 prompts follow a simple **schema** — a handful of elements you fill in, then assemble (see [Prompt formats](#prompt-formats)). Name each one with concrete nouns and verbs the camera can actually see; vague adjectives leave the result to chance.

* **Core summary** — one line stating the whole sequence: who, where, and the arc, so every later choice has context.
* **Scene** — per shot: setting, light quality, and depth of field.
* **Subject description** — a fixed description held identically across shots, so identity stays consistent.
* **Dynamic narrative** — per shot, timecoded: the camera move and the subject's action. Camera language lives here.
* **Audio** — per shot, the soundscape; FLUX 3 renders it synchronized to the frames.
* **Style & color** — the global look that ties the shots together: realism level, palette anchors, and grain.

For the full vocabulary of shot sizes, angles, movements, and focus, see [Camera Terms, Prompts & Examples](/guides/prompting_video_camera_terms).

Assembled, the six elements make one schema — a 10-second desert crossing:

```yaml wrap theme={null}
Core summary: A first-person and third-person mixed cinematic sequence follows a lone man traversing a scorching desert, from a wide dune crossing through a sandstorm, discovering an oasis, and collapsing in exhaustion before crawling toward the water.

Scene:
  Shot 1: A vast desert landscape with rolling golden sand dunes stretching to the horizon. Harsh, bright midday sun casting sharp shadows and a heat-shimmer haze. Deep depth of field.
  Shot 2: The same desert, now engulfed in a violent sandstorm with swirling orange-brown dust obscuring visibility. Muted, diffused lighting, grainy particles filling the air. Shallow depth of field.
  Shot 3: A small oasis, a cluster of palm trees and a shallow turquoise pool surrounded by sand. Warm, golden-hour sunlight, soft and inviting. Deep depth of field.
  Shot 4: A close, low-angle view of the sand near the oasis's edge, water gently rippling nearby. Warm, low light with soft reflections on the water. Shallow depth of field.

Subject description: A rugged traveler in a tattered, sand-colored linen tunic, a loose scarf wrapped around head and neck, leather sandals, and a worn canvas satchel. Sunburned, weathered skin; lips cracked from dehydration.

Dynamic narrative:
  Shot 1 [0.0s-2.5s]: A wide, tracking shot follows the man trudging up a massive dune, his silhouette stark against the bright sky. Footsteps sink deep into the sand, kicking up small clouds with each labored step.
  Shot 2 [2.5s-5.0s]: Hard cut to first-person as the sandstorm hits. He shields his eyes with his forearm, stumbling forward blindly as gusts of sand whip across the frame, nearly knocking him off balance.
  Shot 3 [5.0s-7.5s]: The storm clears abruptly, revealing the oasis. A wide shot shows him breaking into a weak run toward the palm trees, his pace increasing with desperate energy.
  Shot 4 [7.5s-10.0s]: He collapses at the water's edge, then drags himself forward on hands and knees. The camera pushes in close as his trembling hand touches the water, sending ripples outward.

Audio:
  Shot 1: Low, dry desert wind, faint crunching footsteps on sand, sparse ambient silence emphasizing isolation.
  Shot 2: Roaring, chaotic wind howl mixed with gritty sand-whipping sounds and the man's muffled, strained breathing.
  Shot 3: Wind fades into a gentle breeze rustling palm fronds, faint birdsong, and the man's heavy, relieved panting.
  Shot 4: Soft splashing water, the man's shaky exhale, a warm ambient hum fading into a peaceful silence.

Style and color: Realistic, high-fidelity cinematic sequence. Warm, sun-bleached palette of ochre, amber, and sandy beige, shifting to cool teal-blue during the oasis reveal. High dynamic range holds both blown-out sun highlights and deep shadow detail; fine grain adds gritty, tactile realism to the sand and dust.
```

<Note>
  This schema is just one format, not a requirement. You can prompt FLUX 3 with a
  short phrase, long natural language, or timesteps just as well — reach for the
  schema when a multi-shot look and story has to hold together.
</Note>

## Prompt formats

Three ways to structure a prompt, from simplest to most exhaustive. Pick by how much control the shot needs.

### Natural-language one-liner

The best default. A single flowing sentence with a loose, consistent shape, so you can revise one part without touching the rest:

```text theme={null}
[camera] shot of [subject] [action] in [environment]. [supporting visual and motion details]
```

<PromptAnatomy
  examples={[
{
  label: "Tracking, nature",
  video: "https://cdn.sanity.io/files/2gpum2i6/production/02aa909bbbb3404552813acb8101c7512c6deecc.mp4",
  alt: "Low tracking shot of a fox at dawn",
  segments: [
    { t: "A low tracking shot", role: "camera" },
    { t: " of " },
    { t: "a fox sprinting", role: "subject" },
    { t: " through " },
    { t: "wet pine undergrowth at dawn", role: "environment" },
    { t: ". " },
    { t: "Mist drifts between the trees", role: "motion" },
    { t: " as the camera keeps pace beside it. " },
    { t: "Cool blue morning light, fast but controlled motion, cinematic naturalism", role: "style" },
    { t: "." },
  ],
},
{
  label: "POV, documentary",
  video: "https://cdn.sanity.io/files/2gpum2i6/production/0c1d027c4d65671cb778caefedd7291eabdc9b73.mp4",
  alt: "POV shot of a boxer in a dim gym",
  segments: [
    { t: "POV shot", role: "camera" },
    { t: " of " },
    { t: "a boxer weaving", role: "subject" },
    { t: " through " },
    { t: "a dim training gym", role: "environment" },
    { t: ". " },
    { t: "Gloved hands rise into frame as the camera advances toward a heavy bag", role: "motion" },
    { t: ". " },
    { t: "Fluorescent lights buzz overhead, sharp footwork, quick bursts of impact, gritty documentary realism", role: "style" },
    { t: "." },
  ],
},
]}
/>

### Structured / labeled fields

When you need tighter control, break the prompt into labeled fields so every lever is explicit and easy to tweak in isolation:

```text theme={null}
Camera shot: wide shot, low angle
Subject + action: a lone rider crosses a shallow desert river
Depth of field: shallow (sharp on subject, blurred background)
Lighting + palette: warm backlight with soft rim — amber, cream, walnut
Motion: water splashes around the horse's legs, orange dust hangs in the light
Style: epic western realism
```

<MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/bf3fe92d8289a4359dbe30f9814209863e95e162.mp4" alt="Wide low-angle shot of a lone rider crossing a shallow desert river at sunset" />

### Timestep prompting

For action that has to land *on time*, describe the shot as a short timeline. Keep each beat achievable — two or three for a 5-second clip. Mark a **hard cut** where the angle changes.

```text theme={null}
0.0–1.5s — locked wide of a still harbor at dawn, boats motionless on glassy water
1.5–3.0s — a slow push-in begins as gulls lift off the water
3.0–5.0s — the sun breaks the horizon, warm light spreads and the camera settles
```

<MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/600d910b8920e07531ff6950985413cc85acce65.mp4" alt="A harbor at dawn — gulls lift off the water as the sun breaks the horizon" />

<Tip>
  Reach for the **one-liner** for quick ideas and B-roll, **labeled fields** when
  you're tuning specific levers, and **timestep** when the action has to hit marks
  in time. For a look and story that must hold across several shots, use the
  [**prompt schema**](#prompt-schema).
</Tip>

## Iterate on your ideas

Iteration is an essential part of the process — your first prompt is rarely your final one, it's the starting point. Review each result and refine: add context, remove ambiguity, change the emphasis, or explore a new direction. Small adjustments can have a significant impact. Step through one example:

<Tabs>
  <Tab title="First try">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/21d7472dae836ea2a309f56be2c6d9a9f98df054.mp4" alt="First iteration — a video of an eagle" />
    </div>

    ```text wrap theme={null}
    a video of a eagle
    ```
  </Tab>

  <Tab title="Add context">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/d65a0576ec5ca0ce35c1aaf5851f0c23ba21bbe3.mp4" alt="Second iteration — a closeup video of an eagle" />
    </div>

    ```text wrap theme={null}
    a closeup video of a eagle
    ```
  </Tab>

  <Tab title="Change the scene">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/336526136612ad3f25d7c51f9bcb2048d4008e1a.mp4" alt="Third iteration — eagle on a tree in a forest" />
    </div>

    ```text wrap theme={null}
    a closeup video of a eagle, the eagle sits on a tree in a forrest
    ```
  </Tab>

  <Tab title="Refine it">
    <div className="not-prose" style={{ marginBottom: "1rem" }}>
      <MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/3a00d04c812d0bd78ef454b2bbca48ab7d9b78c9.mp4" alt="Final iteration — cinematic eagle in a misty forest" />
    </div>

    ```text wrap theme={null}
    a cinematic closeup of an eagle perched on a pine branch in a misty forest, feathers ruffling in the wind, slow push-in, golden-hour light
    ```
  </Tab>
</Tabs>

## If you want audio

FLUX 3 renders synchronized audio with video, so describe scenes that naturally imply sound — the action should make the soundscape obvious. Unmute the clip below to hear it:

<MutedVideo src="https://cdn.sanity.io/files/2gpum2i6/production/235e6179a792b229814ad84ce8889e68c506cb62.mp4" alt="A boxer training alone in a dim gym" />

<PromptDisplay prompt="A boxer trains alone in a dim gym. Rapid footwork on the canvas, gloves striking a worn punching bag, fluorescent lights buzzing overhead, handheld close follow shot, gritty documentary style." />

Scenes with footsteps, impacts, rain, engines, or crowd motion give the audio generation clearer material than abstract visual scenes.

For dialogue, voiceover, sound layers, timing, and voice direction, see [Audio and speech](/guides/prompting_video_audio).

## Related pages

<CardGroup cols={2}>
  <Card title="Video Generation Overview" icon="film" href="/guides/prompting_video_overview">
    Start here for the broader FLUX 3 video prompting framework across all workflows.
  </Card>

  <Card title="Camera Terms, Prompts & Examples" icon="camera" href="/guides/prompting_video_camera_terms">
    Reuse framing, angle, movement, composition, and focus phrasing in your FLUX 3 prompts.
  </Card>

  <Card title="FLUX 3 Video" icon="film" href="/flux_3/flux3_video">
    See the FLUX 3 video page for modes, parameters, and use cases.
  </Card>

  <Card title="Audio and speech" icon="waveform-lines" href="/guides/prompting_video_audio">
    Direct speech, ambience, effects, music, and the shape of a voice.
  </Card>

  <Card title="Prompting Basics" icon="pen" href="/guides/prompting_unified_basics">
    Core prompt-writing principles that still apply before you direct motion.
  </Card>
</CardGroup>
