What an LLM does in a video pipeline
If you are building an nsfw video script llm api workflow, the first thing to settle is the division of labour. A language model writes. A separate video model, or an editor, or a shoot, makes the footage. This service offers only the first part: one open-weight text model, tuned to answer without content refusals for lawful adult use, behind an OpenAI-compatible endpoint. It will not render a frame, synthesize a voice or create an image, and it does not offer embeddings or fine-tuning.
That still covers a lot of the work around a project made for adult audiences, such as fiction, roleplay and companion-style storytelling. The model can draft a treatment, split it into scenes, write dialogue and narration, produce a shot-by-shot list, and phrase prompts for whichever video tool you use downstream. The page on NSFW pipelines describes how this text stage connects to the rest of a stack.
One rule is fixed and applies to every request: no sexual content involving minors. Build your system prompt so every character is an adult, and treat that as a requirement of the project, not an afterthought.
A pipeline in four stages
A script workflow works best when each call does one job and hands structured output to the next. A practical layout looks like this:
- Story bible. One document with characters (all adults), setting, tone and recurring details. You write it once and send it with every call.
- Outline. One call turns a premise into 8 to 15 beat summaries.
- Scene scripts. One call per beat produces dialogue, action lines and narration, using the bible and the previous scene for continuity.
- Shot list and prompts. A final call per scene returns JSON: shots, durations, camera notes and a prompt string for your video tool.
Splitting it this way keeps outputs short, which makes each result easier to review and cheaper to regenerate if you dislike it. It also means a failed call costs one scene, not the whole script.
A system prompt that sets the rules
The system prompt is where tone, format and limits live. A model without refusal behaviour still follows instructions, so the quality of your prompt decides the quality of the script. Be specific about genre, point of view and what to leave out. Here is a starting point for fiction aimed at adult viewers, written to stay on the professional side of the page:
SYSTEM = '''You are a screenwriter for adult-audience fiction videos.
All characters are adults aged 25 or older, and you state each age in the character sheet.
Write in present tense, third person, with short visual action lines.
Keep dialogue natural and under 25 words per line.
Build tension and character through setting, glances and subtext.
Never include minors in any role or reference.
Follow the story bible exactly; do not change names, ages or relationships.
When asked for JSON, return only the JSON object.'''
Adjust it per project. A noir mystery and a romance comedy need different instructions, and a one-line style example inside the prompt often steers the model better than a paragraph of adjectives.
Generating a scene list in JSON mode
For the shot list stage you want output that code can read. JSON mode enforces a parseable object. Pass response_format={"type": "json_object"}, name the keys in the prompt and keep temperature low. This example uses the Python openai package with this site's base URL and the model ID uncensored.
import json, os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nsfwvideogenerator.cc/v1",
api_key=os.environ["NOTRACK_API_KEY"],
)
SYSTEM = open("system_prompt.txt").read()
BIBLE = open("story_bible.txt").read()
def shot_list(scene_text):
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": (
"Story bible:\n" + BIBLE +
"\n\nScene script:\n" + scene_text +
"\n\nReturn a JSON object with key 'shots': a list of objects with "
"'number', 'seconds', 'camera', 'action' and 'video_prompt'."
)},
],
response_format={"type": "json_object"},
temperature=0.3,
seed=7,
)
data = json.loads(resp.choices[0].message.content)
return data["shots"]
for shot in shot_list(open("scene_03.txt").read()):
print(shot["number"], shot["seconds"], shot["video_prompt"])
Validate the result before you hand it on. Check that shots exists, that seconds is a number, and that the prompt strings are not empty. If parsing fails, retry once. Failed or refused requests are not charged, so a retry costs nothing extra for an errored call.
Settings that matter for creative text
Different stages want different settings, and the API passes the usual ones through: temperature, top_p, stop, seed and the frequency and presence penalties.
- Outlines and dialogue: temperature 0.8 to 1.0 for variety. Generate two or three variants and pick one.
- Shot lists: temperature 0.2 to 0.3, plus a fixed
seedso a rerun of the same input is comparable. - Repetition: long scenes sometimes loop on the same phrase. A small frequency penalty, such as 0.3, helps.
- Length control:
max_tokensis optional, but a cap of 800 for a scene keeps the output tight. Astopsequence such as"END SCENE"lets you end at a marker you ask the model to write. - Streaming: turn on
stream: trueif a writer watches the output live. Remember that a stream holds its concurrency slot until it ends.
The quickstart lists every supported parameter, and the endpoints are POST /v1/chat/completions and GET /v1/models.
Using the 100k context window for continuity
Continuity is the usual failure in generated scripts: a name changes, an age drifts, a prop disappears. The context window is 100,000 tokens, prompt plus completion, and that is large enough to put the whole story bible, the outline and several finished scenes into every call. You do not need a retrieval system for a project at this scale. Paste the facts in and let the model read them each time.
Context is not free, but it is cheap. Suppose your bible and outline total 20,000 tokens and you write 50 scenes, each call returning about 600 tokens:
- Input: 50 x 20,000 = 1,000,000 tokens x $0.15 per 1M = $0.15
- Output: 50 x 600 = 30,000 tokens x $0.50 per 1M = $0.015
- Total: $0.165 for all 50 scenes
Add a shot-list pass over the same 50 scenes with 3,000 tokens in and 500 tokens out each: input 150,000 tokens costs $0.0225 and output 25,000 tokens costs $0.0125, a further $0.035. The full script and shot lists cost about $0.20, which is less than the trial credit of $0.50 that you can claim from the API key page.
Keep in mind that the window must hold both prompt and answer. A 20,000 token bible leaves plenty of room, but a 95,000 token prompt leaves little for the completion.
Reviewing and fixing the output
Treat every generated scene as a first draft. Three checks catch most problems before they reach a video tool. First, run a consistency pass: send the finished script back with the story bible and ask the model to list any place where a name, age, location or timeline differs. A second call with a low temperature is cheap and often finds drift you missed by eye. Second, read the dialogue aloud. Lines that look fine on screen can be clumsy when spoken, and a voice-over actor or a text-to-speech tool will expose them at once. Third, check that the shot durations add up to the length you planned. Models are loose with arithmetic, so add the seconds fields in code instead of trusting a total the model wrote.
When a scene misses the mark, resist rewriting the whole system prompt. Add one corrective instruction to the user message, such as "shorter action lines" or "more dialogue, less description", and regenerate that scene alone. Keeping the bible and system prompt fixed while you vary one instruction at a time makes it clear which change helped. The seed parameter is useful here, because a fixed seed with a small prompt edit isolates the effect of the edit.
Limits, honesty and next steps
A few plain constraints before you build. The model is text only, so every video, image and voice track has to come from other tools. It is one open-weight model run by an independent provider, and it is not the official API of any big vendor. Quality varies with the prompt, so plan for a review pass by a person on every script; treat the output as a draft.
On throughput, a full key allows 8 concurrent requests and 300 per minute, while a trial key allows 2 and 60. If you write scenes in parallel, size your worker pool to match. A 429 with rate_limited or concurrency means slow down; one with a Retry-After: 5 header means the service is briefly overloaded, so wait five seconds and try again. Prompts are not used for training.
Paid credit starts at a $20 top-up, any whole amount up to $500, with +5% from $50, +10% from $100 and +15% from $200. Payment is crypto only, USDT on TRC20 or USDC on Base, and credit never expires. Current terms are on the pricing page. For a project like the one above, $20 covers dozens of full scripts.
