Skip to main content
SANA-Streaming is a real-time video editing model. Feed it a video clip or a live webcam feed and describe a change in plain text. The model outputs an edited video stream alongside the source footage. The edit lands where you aim it; everything you don’t mention carries through from the source untouched. SANA-Streaming edits the video you bring rather than generating one from scratch. The prompt describes a change to apply, not a world to create, and the model’s job is to make that change and preserve everything else. The SANA-Streaming reference is split across four pages: this overview, the complete command and message schema, the prompt guide for writing surgical edit prompts, and an end-to-end tutorial. The base wire protocol is the same as every other Reactor model: open a session with the Reactor class (model name sana-streaming), send named commands, and receive messages. SANA-Streaming’s surface adds commands for setting the source video and applying edit prompts.

At a glance

SpecValue
Model namesana-streaming
Pricing
Resolution1280 × 704
The model name is the string you pass when you open a session, e.g. new Reactor({ modelName: "sana-streaming" }). See Pricing & Billing for how billing works.

Key features

Surgical edits

Change the one thing you name and nothing else.

Real-time responsiveness

Send a new edit mid-stream and watch it land about a second later, not after a re-render.

Live webcam input

Restyle yourself, your room, or your product demo as it streams.

Quick start

The fastest path to a working SANA-Streaming app is the create-reactor-app CLI, which scaffolds a runnable project for you. You can also clone the open-source reference frontend directly, or follow the tutorial for a guided walkthrough.
npx create-reactor-app my-sana-app --model=sana-streaming
A minimal connect-and-edit flow looks like:
import { Reactor } from "@reactor-team/js-sdk";

const video = document.querySelector("video")!;
const reactor = new Reactor({ modelName: "sana-streaming" });

// Render the edited stream as frames arrive.
reactor.on("trackReceived", (name, track, stream) => {
  video.srcObject = stream;
  void video.play();
});

reactor.on("statusChanged", async (status) => {
  if (status !== "ready") return;

  // Publish your camera as the live source. Pin the resolution first:
  // a mid-chunk resolution change crashes the session.
  const cam = await navigator.mediaDevices.getUserMedia({ video: true });
  const track = cam.getVideoTracks()[0];
  track.contentHint = "detail";
  await reactor.publishTrack("camera", track);

  // Describe the edit, then start.
  await reactor.sendCommand("set_prompt", {
    prompt:
      "Replace the subject's t-shirt with a vintage dark brown leather aviator jacket with a cream shearling collar.",
  });
  await reactor.sendCommand("set_mode", { mode: "live" });
  await reactor.sendCommand("start", {});
});

const jwt = await getToken(); // token minted on your server
await reactor.connect(jwt);
Publishing a track and uploading a file are base-SDK features that work the same on every model; see Tracks and File Uploads. To change the edit mid-stream, send set_prompt again: the new edit lands at the next chunk boundary, about a second later.

How it works

On connect the model is live but idle. Give it a source (your camera or an uploaded clip), apply an edit prompt, and call start; the edited stream begins on main_video. From there you direct it in real time: send a new prompt and the change lands at the next chunk boundary, so successive edits feel like adjustments to a live feed rather than separate render jobs. The architecture comes from the paper SANA-Streaming: Real-time Streaming Video Editing with Hybrid Diffusion Transformer (Zhao et al., 2026), research led by NVIDIA with collaborators at MIT, THU, NUS, and HKU. See the schema for every command and message, and the prompt guide for how to write edit prompts that land where you aim them.