com.thefilmradar/filmlab
name:com.thefilmradar/filmlab
AI film lab for filmmakers: generate and review images/clips with input provenance, cost preflight
- transport:
- remote
- credential class:
- gated
Owner verification
Not yet verified. Verifying proves you control this server and is free, permanently — it never changes a published score.
Start verification →Tools
- lab_abgleichshallow
Prompt check of ONE generated image or clip: does the result show what its prompt asked for? The backend first DESCRIBES the result without seeing the prompt, then splits the prompt into checkable claims (counts as digits, quoted text, identity, place, framing, style; for clips the motion) and scores each. verdict: pass | mismatch | unverified, plus `checks`, `issues` and the neutral `beschreibung`. Runs automatically after every generation (lab_job_status shows it as `abgleich`); call this to read it, or with neu=true to check again. On mismatch: offer at most ONE retry per original, lead the new prompt with the failed claim; never re-run a video on your own. Free for the account (FilmLab carries the cost).
- lab_add_clipshallow
Append a shot to a sequence's timeline. Call it once per shot, in cutting order — `start_time` is computed from the clips already there, so appending in order is enough. The continuity pass reads exactly this timeline: a shot missing here is a shot nobody checks. Returns the new clip's index and the sequence's total duration.
- lab_add_mediashallow
Bring your own video, audio or image into a project — not generated, yours. Two ways: `media_url` (a public http(s) address; the server fetches it, max 100 MB) or `file_name` + `content_type` (you get a signed `upload_url` and the `header` that are part of its signature: PUT the file's raw bytes there within the hour with EXACTLY those headers — the answer's `anleitung` has the ready curl line; a missing header is a 403). Either way the answer is the `asset_key` — use it in lab_timeline_apply as clips[].asset_key (video) or bett.asset_key (audio). Free. Internal addresses are refused.
- lab_analyze_location_imageshallow
Read a photo and extract location fields from it (Gemini Vision, costs quota). Returns the fields — it does NOT create a board; feed the result into lab_create_location yourself. Note the payload: the image travels as base64 inside the call, so keep it small (a downscaled JPEG, not a full-resolution capture).
- lab_animateshallow
Animate a completed image into a clip with a video model. Pick the model from lab_list_models; check the price with get_cost or let the user confirm a card via lab_propose. Costs credits when called without get_cost.
- lab_animate_batchshallow
Animate MANY images into videos in ONE call (max 25 jobs). Prefer this over looping lab_animate: it validates every job BEFORE spending any quota, so an invalid job 12 of 15 does not leave 11 paid-for generations running. Quota is spent once, collectively (one ledger row); refunds stay per-clip, so a partial failure refunds only that clip. Returns a batch_id — poll lab_batch_status with it instead of polling each id separately. `get_cost: true` preflights the whole batch without generating anything.
- lab_apply_rhythmshallow
Compute the sequence's clip durations from the project's cutting preset and — when the tempo allows it — pull the cut points onto the measured beat grid. WRITES the timeline; costs nothing. The old duration of every changed clip is kept in `clip.metadata.dauer_vorher`, so one undo step exists (a second differing run overwrites it — there is no history). Clip count is never changed: no clip is added or removed. SNAPPING IS NOT GUARANTEED, AND A REFUSAL TO SNAP IS A RESULT, NOT A FAILURE — read `gerastet` and `raster.grund` before you repeat anything: 'tempo_unverlaesslich' = measured below the confidence threshold (deliberate; pass trotz_unsicherem_tempo to override), 'nicht_gemessen' = run lab_beatgrid first, 'keine_musikspur'/'musikspur_nicht_aufgeloest' = run lab_bind_audio first, 'rhythmus_ohne_raster' = the preset's rhythm is 'frei' or 'atmend', which means not snapping IS the promise ('auf den Beat', 'auf die Songstruktur' and 'gegen den Takt' are the three that snap), 'toleranz_null' = you passed toleranz_s 0. In every one of those cases the durations are still recomputed from the preset and written — that alone is the difference between 40 and 6 cuts over 30 seconds. Also read `raster.getroffen` of `raster.von`: `gerastet: true` only says snapping ran; this pair says whether it landed. And `geklemmt` lists clips the renderer's own duration clamp moved back OFF the grid.
- lab_aufloesungshallow
Break one scene down into a STRUCTURED shot list of 2, 4 or 6 shots — each with shot size, camera angle, purpose and its own ready prompt, plus one shared floor plan (anchor, axis, light) so the shots cut together. Two families: an 'aufloesung' shows ONE moment from several angles (coverage, dialog, orbit, pov, zwischenschnitte for cutaways …); a 'montage' lets time pass between shots (ursache_wirkung, zeitverlauf, kleiner_bogen …). An unknown art is rejected with the list of known ones. Costs no credits: it is one text-model call and renders nothing; generate the shots afterwards with lab_generate / lab_animate, one prompt each. This is NOT lab_shots_ableiten — that one groups clips that already exist on a timeline; this one plans shots that do not exist yet. By default nothing is written. uebernehmen=true appends the shots as scenes to the project's shot list (mod_shotlist), which the image and video steps read — ask before you set it.
- lab_auto_laufshallow
Auto run with a hard spending cap: the person approves ONE run with an upper limit in credits; inside it you may generate without asking per item, but never above the cap. aktion: anlegen (project_id + deckel_credits → status 'angelegt', nothing can be spent yet) · freigeben (ONLY after the person explicitly approved the cap) · stand (cap, reserved, free, items) · beenden. While a run is active, EVERY paid call in that project reserves its price against the cap — whichever tool makes it; reservations are never refunded (a failed item keeps its share, a retry reserves again), upscales and exports count too. The cap counts credits: runs on the person's OWN provider key (BYOK, 0 credits) are not counted. Other projects are not affected. When the cap would be crossed the backend answers budget_exceeded: stop, report what finished, what is open and the minimum budget still needed. Under budget pressure lower the resolution first, never cut runtime, never drop character or location variants.
- lab_auto_storyboardshallow
Auto-generate a storyboard from a script: an LLM splits the script into scenes, then one storyboard frame is generated per scene. COSTS CREDITS — every scene is one generated image, charged up front for the number of scenes the script is split into (at most max_scenes). Ask the human before running it. CHARACTERS ARE NOT GUESSED: every character who appears in more than one frame first gets a reference image (an existing project character with a reference is reused for free; a new one is created and its reference sheet is charged separately as character_sheet_generate), and every frame showing such a character is generated WITH those references on seedream_5_pro instead of `model`. Frames without a recurring character use `model`. The answer lists `figuren` (name, status, scenes), `figuren_kosten_geschaetzt` and `kosten_je_bild`; prices per model come from lab_list_models. If a reference cannot be made, the frames that need it fail and are refunded — they are never generated without it. The scene split is SYNCHRONOUS and can take up to ~55s and then time out (504) for long scripts; run it in the app if so. The answer lists the new image ids; the frames themselves render in the background as pending images — poll them with lab_job_status (type 'image').
- lab_batch_statusshallow
Aggregated progress of a video batch started by lab_animate_batch. Returns {total, completed, failed, pending, done, items[]} — poll this ONCE per batch instead of calling lab_job_status per clip. `done: true` means nothing is pending any more (some items may still have failed). Each item carries retry_count (an automatic second attempt happened) and fallback_from (the provider was swapped after a content-policy rejection).
- lab_beat_clipsshallow
Turn the still-image clips of a sequence into video clips that exactly fill their beat-snapped slots. Free — this tool itself generates nothing. aktion plan: one job per image clip, ready for lab_animate_batch — start image, the frame's motion (bewegung_en), and the SMALLEST duration the model can deliver that still covers the clip's timeline duration (a shorter video would end early and shift every later cut off the beat). Refuses with 409 if a start image is not accepted yet. Pass the returned `jobs` unchanged to lab_animate_batch (get_cost first, then run). aktion einsetzen: once the videos are done, each finished video replaces its image clip — same duration, source in-point 0. Repeatable; reports what is still open and any video shorter than its slot (left as still). Run lab_beatgrid and lab_apply_rhythm on the sequence BEFORE plan, so the durations are the beat durations.
- lab_beatgridshallow
Measure the TEMPO of the sequence's bound music track and store the beat grid — opens the real file with ffmpeg and analyses it, no guessing and no provider, so it costs nothing but a few seconds. Writes `bpm` and `metadata.beat_grid` on the audio row; it does NOT touch the timeline (`timeline_geaendert: false`). Deterministic and cached: a second call returns the same numbers without downloading again (pass `neu_messen` to force). READ `confidence` AND `verlaesslich` BEFORE YOU CUT. Below the threshold (0.35) lab_apply_rhythm computes durations but deliberately does NOT snap them to the grid — that is a decision, not a failure. Soft material measures badly: a real swing track came out at 0.164, an ordered hard pulse (techno, 128 bpm) at 0.621. Half and double tempo are the classic misreads, so `bpm_alternativen` is part of the answer. `frame_konflikt` reports the collision between beat grid and frame grid, for BOTH renderers: `export` (24 fps, the delivered MP4) and `murnau` (25 fps, the editor timeline). Read `frames_pro_schlag` as a DEVIATION, not a count: it is how far one beat sits from a whole frame, between 0 and 0.5. 0 means beat and frame coincide (100, 125 and 150 bpm at 25 fps do); anything above means beat-accurate and frame-accurate cannot both hold, and the rounding error accumulates across clips — measured on a finished MP4 at 128 bpm: up to 64.7 ms off the audible beat although every cut point had snapped. Shown here, not fixed: that decision belongs to a human. Refusals that name their own remedy: 409 without a bound music track (run lab_bind_audio), 409 when the track is pending (poll lab_list_audio), 502/504 when the audio host is unreachable or slow, 422 when the file carries no usable audio, 503 when ffmpeg is missing.
- lab_bildershallow
See a clip at EXACT seconds: up to 12 frames, in the order you list them, tiled into one image and shown. Use it to check what is on screen where you plan a cut, whether a motion has ended, or whether a face drifted between two moments — lab_contact_sheet spreads frames evenly and cannot answer 'what is at 3.2 s'. A second past the clip's end is rejected by name, not clamped. Works on generated clips (video_id) AND on your own uploaded footage (project_id + asset_key from lab_add_media) — look at it before you cut it. Free (no credits).
- lab_bind_audioshallow
Bind the project's generated audio to a sequence's tracks — ONE call that does both halves of the job, because doing only the first half silently produces a silent film. Half one (`POST …/soundmix`) creates the four empty tracks (dialog, music, sfx, atmo); half two (`POST …/soundmix/resolve-stems`) is what actually attaches the audio rows to them. On 2026-08-28 that split cost a complete silent export: the mix looked configured, and every track was empty. From here it is one tool, and it is idempotent — an existing mix is NOT re-initialised (that would throw away volumes, effects and the other tracks' bindings), only re-resolved. Per track it takes the audio row marked `selected`, otherwise the newest one with a url. Rows still pending have no url and stay unbound. That choice is re-made on every call: generate a second music track and run this again, and the music track follows the NEWER row — unless one row is pinned with `selected`, which is set in the web UI, not from here. Changes state, costs nothing. Next: lab_beatgrid.
- lab_captureshallow
See the CUT at exact seconds of the finished film: up to 12 frames, tiled into one image and shown. Each second is mapped like the export maps it — which clip is on screen, where in its source (src_in_s counts), the export's framing (scaled and letterboxed), title cards drawn. A video whose source is shorter than its clip duration ends early in the export, and everything after it moves forward; this tool follows that, so you see the film that will be rendered. The answer names per frame the clip (position, clip_id), clip start and offset; a clip that would render black says so ('schwarz'). NOT in the image: lens/grade, lower thirds, the AI badge — that needs lab_start_export. Use it after lab_timeline_apply to check cut points before exporting. Free (no credits).
- lab_cast_autopopulateshallow
Create character sheets for the people found in a project's material — the writing counterpart to lab_cast_gaps. Creates at most 6 per call and binds each to the project. Costs an LLM run per call. Run lab_cast_gaps first if you want to see what it would create. The sheets it creates have NO reference image: each one still needs lab_generate_character_reference before lab_generate accepts it as `character_refs`. Fail-open: no script or no AI key returns an EMPTY `created` list with a `note`, not an error.
- lab_cast_gapsshallow
Find people who appear in a project's material (script / cast module) but have NO character sheet yet. Returns up to 6 `missing` entries, each with a name and a short hint from the text. It creates nothing — lab_cast_autopopulate does that. Costs an LLM run, so it is credit-gated. Fail-open by design: no script, no AI key, or an unparseable answer all come back as an EMPTY list (with a `note` saying which) — an empty list is the correct answer, not an error.
- lab_contact_sheetshallow
Build a contact sheet for a generated clip — N frames spread evenly over its runtime, tiled into ONE image — and show it. This is how a clip gets judged at all: MCP has no video content type, so without a sheet a clip is just a URL and a promise. It is also the fastest way to SEE camera drift: measured 2026-08-04, the wander in one clip was a PSNR number until frames sat side by side. The sheet is cached on the video row — a second call returns the same URL without re-rendering (pass force to redo it). Rendering downloads the clip and runs ffmpeg, so the first call takes a few seconds.
- lab_continuity_checkshallow
Start the continuity pass over a sequence — every shot is compared against its PREDECESSOR and, with check_references, against the character and location reference boards. This is the pass that catches drift (the flat that changed between two shots, the cardigan that turned into a coat), which is the actual enemy in AI film, not the cut. Runs in the BACKGROUND: returns a `job_id` with HTTP 202 — poll it with lab_get_job until status is done|failed, the findings sit in the job result. Two refusals worth knowing before you spend time: an empty timeline is rejected with 400 (add shots with lab_add_clip first), and the backend answers 503 if GEMINI_API_KEY is not configured.
- lab_create_charactershallow
Create a character sheet in the cast register. The backend derives an English `prompt_prefix_en` from the fields you give — that prefix is what later describes this person in every image, so the richer the description, the more stable the identity. This is step 1 of 2: a fresh sheet has NO reference image and is therefore not yet usable as `character_refs`. Run lab_generate_character_reference on the returned id to finish it. Free — it writes a row, it burns no credits.
- lab_create_locationshallow
Create a location board. The backend derives an English `prompt_prefix_en` from the fields you give — that prefix is what later anchors every image and clip shot there, so the richer the description, the more consistent the place. Pass project_id to bind the board to a project (recommended: unbound boards are invisible to lab_list_project_locations).
- lab_create_projectshallow
Create a new FilmLab project. Returns the new project id. Optionally set a title.
- lab_create_sequenceshallow
Create a sequence (Stage 9 timeline) inside a project — START HERE to turn generated shots into something the continuity pass can read. The new sequence is EMPTY: add shots with lab_add_clip before anything else works. lab_continuity_check rejects an empty timeline with 400. Returns the sequence record including its `id`.
- lab_delete_locationshallow
DELETE a location board permanently. There is no undo and no soft-archive — the row is removed. Images and clips that were generated with this `location_id` keep their already-rendered prompt, but the board they point at is gone: nothing can be re-anchored to it, and lab_get_location will 404. Confirm with the user before calling this. Use lab_restyle_location if you only want the place to look different.
- lab_depth_mapshallow
Create or read a depth map for a project video in FilmLab: use it for fog, depth of field, relighting or occlusion. Near is white, like Resolve's Depth Map. Free on our own CPU, no credits; processing takes minutes (about 0.5 seconds per frame). Reuses the existing map or running job by default; neu: true starts a new job. Returns status and job_id; when done, tiefe_url is FFV1 gray16 and vorschau_url is a playable H.264 grayscale preview, both signed for download without a browser session. wait_s waits at most 15 seconds (default 0). If still running, call this tool again with the same project_id and video_id, neu: false. Once done, use resolve_ergebnis_an_timeline with vorschau_url to put the preview as a matte above the original clip in Resolve.
- lab_diagnoseshallow
Is everything wired? Backend reachability and latency, identity, credit check, catalog age, last error of this account, host widget support. Traffic light plus one sentence per point. Read-only, free.
- lab_dossiershallow
Build a dossier of a project's takes: one ZIP with an offline index.html (no external resources) plus the media files, named Project_SceneNN_YYYYMMDD-Tnn.ext. modus 'kunde' is for a client and NEVER shows seed or costs, whatever the switches say; 'intern' shows everything that helps to rebuild a take. Both modes carry the AI disclosure (EU AI Act Art. 50) on the page and in the image files. Free (no credits). Runs as a job — poll lab_get_dossier.
- lab_dubshallow
Dub a sequence into another language: either a ready audio track (en_audio_url — e.g. the one lab_dub_tts just produced) OR a cloned voice reading a line of text (voice_id + dub_text), then a controlled visual lipsync runs over the sequence's own footage (ROI-crop + composite for a long static talking-head shot, or the full-frame veed_v2 path for multi-shot sequences and shots where the mouth is partly hidden). ASYNCHRONOUS: returns a job_id immediately: poll lab_job_status until it completes. Needs a cloned voice first — lab_voice_clone makes one, lab_list_voices shows what a project already has.
- lab_dub_ttsshallow
Generate the EN-dub audio track for a sequence via ElevenLabs TTS — SYNCHRONOUS, returns a ready audio_url immediately, no job_id and nothing to poll. Optionally pads the track with silence up to the sequence's own length so a shorter reading doesn't shorten the final cut. Feed the resulting audio_url into lab_dub's en_audio_url to lipsync the sequence to this track.
- lab_dub_voicesshallow
List the ElevenLabs TTS voices available for lab_dub_tts's `voice_id` — this is the EN-dub-track text-to-speech voice list, NOT a project's cloned voices (those are lab_list_voices). Reads only — no state changes, no credits. If ELEVENLABS_API_KEY isn't configured on the backend the list comes back empty and `configured` is false.
- lab_enrich_location_prefixshallow
Append context to a board's `prompt_prefix_en` (plain string concatenation server-side — no AI call, no quota). Idempotent: context already present in the prefix is not duplicated. This does NOT rewrite or regenerate the prefix — for a board whose prefix is empty, too thin or a raw field dump, use lab_restyle_location (it rewrites prompt_prefix_en with an AI call, costs quota) instead of recreating the board.
- lab_export_profilesshallow
List the available export delivery profiles (web, social_vertical, social_youtube, streaming_hdr, cinema, master, alpha_prores4444, alpha_png_sequence) and quality presets (draft, standard, high). Call this before lab_start_export to pick a valid profile/quality. The two alpha profiles keep transparency (ProRes 4444, or one RGBA PNG per frame delivered as a zip) and are REFUSED unless the sequence actually carries an alpha source — a cut-out layer element, or a Switch X transform whose alpha track was kept.
- lab_fassungenshallow
Use when the person asks about earlier states of a cut, wants to go back to a previous version, compare versions, name a version, or create a second cut (e.g. a short version next to the long one). The history and the versions of ONE cut (sequence). Every timeline write (lab_timeline_apply, the editor, the Resolve bridge) first saves the state it replaces; this tool reads those saved states and works with them. Costs nothing. aktion 'liste' (default): the saved states, newest first, with `marke` (a name a person gave a state), plus where this sequence was branched from (`ursprung`, with what changed since the branch point) and which versions were branched from it (`abgezweigt`). 'markieren': give a state a name (`marke`); a named state is never cleaned up — states without a name are capped per sequence. Empty `marke` removes the name. 'vergleichen': what changed since a state — against the current cut, or against another state (`gegen`), clip by clip. 'zurueckholen': write a state back as the current cut; the cut it replaces is saved first, so this is undoable. 'abzweigen': make a NEW sequence (a version — e.g. a broadcast cut next to the festival cut) from a state, or from the current cut without `checkpoint_id`. The new sequence keeps the clip ids and the shot layer, knows its origin, and the branch point gets a name so it stays. There is no merging back: a version is its own cut from then on. Edit it with lab_timeline_apply on the returned sequence id.
- lab_feedbackshallow
Tell the FilmLab team about a bug or a missing feature — it reaches the people who can fix it, the chat does not. Use art 'fehler' when a tool returned something wrong, failed without a clear reason, or contradicted its own description; 'wunsch' when a step you needed does not exist. Write what you called, what you expected and what came back; put ids, arguments and the error text into `kontext` (no secrets, no personal data of third parties). One report per problem. Do not report a refused request that was correct (e.g. 'Project not found' for someone else's project). Needs an account. Free.
- lab_fertigstellenshallow
Finish an accepted DRAFT (a lab_reference_motion run with draft: true) in 1080p — same motion, same seed, same sound, sharper picture. A NEW video row comes back; the draft stays. Works only while the draft is valid and only through the account that ordered it; otherwise the backend refuses with a named reason (entwurf_abgelaufen, entwurf_anderes_konto, entwurf_fehlt, bereits_fertiggestellt) before anything is charged. Never download and re-upload a draft to get here: that is a new run, not this draft. Costs credits when called without get_cost.
- lab_flow_angebotshallow
Price a whole Flow (Pipeline) before running it: one quote over every node, checked against the credit balance and the project's cost cap. `workflow` is a FilmOS workflow in schema v1 (vault/workflows/_schema.md): nodes of type `lab.tool` call FilmLab tools by name, `{{node_id.field}}` passes one node's result into the next, `parallel` and `condition` are supported, `foreach` and `workflow.invoke` not yet. Every node whose tool costs money is priced with that tool's own get_cost preflight; a paid tool without a preflight, or a price that cannot be determined, rejects the whole quote by name — nothing is estimated. Nothing is generated and nothing is charged. Returns `angebot_id` (valid 24 h, for exactly this workflow, these inputs and this project), the total, one line per node, the balance and what the cap still allows.
- lab_flow_fortsetzenshallow
Use when a flow/pipeline run is waiting for approval or a price confirmation and the person gives the go-ahead to continue. Resume a Flow (Pipeline) run that stopped and waits (status 'wartet' with a reason like 'Wartet auf Freigabe'). A run stops when a clip node needs a start image the person has not approved yet — approve the image first (lab_review_asset, verdict accepted), then resume. A run also stops before a node whose price only exists once its input exists (lab_upscale after a clip — the quote listed it as `preis_folgt`): the reason starts with 'Wartet auf Preisbestätigung' and names the exact credits. Resuming IS the confirmation of that price — ask the person first. The confirmed amount travels as max_credits; if the price rises before the run, nothing is charged and the run stops again with the new price. The waiting nodes are tried again; nothing that already ran is repeated.
- lab_flow_startenshallow
Run a Flow (Pipeline) that was quoted with lab_flow_angebot. Pass the SAME workflow and inputs plus the angebot_id — a changed workflow, an expired quote (24 h) or a quote that was already used is refused; get a new quote then. Only after the person confirmed the price. Returns right away with `lauf_id`; the run continues on the server without anyone watching. Follow it with lab_flow_status. Each node calls its FilmLab tool under your account; every tool's own gates still apply (approved keyframe before a paid clip, cost cap of the project). If the cost cap is hit, the whole run stops and nothing after it starts.
- lab_flow_statusshallow
State of a Flow (Pipeline) run started with lab_flow_starten: the run's status (wartet, laeuft, fertig, fehlgeschlagen, abgebrochen) and, per node, its status, attempts, result and error. A node's result is exactly what its tool returned — ids from there go into the next tools.
- lab_freigebenshallow
Release a paused PERSON-reference run (lab_reference_motion with use_depth: 'personen') after the human has looked at its mask preview: this starts the paid model run. Until now only the mask was charged. Show the preview (metadata.personen_referenz_url of the paused clip) first — holes in hair or hands cost a full run if released. A NEW video row comes back; the paused row stays as the record of the mask. The backend refuses with a named reason (nicht_wartend, bereits_freigegeben) before anything is charged. Costs credits when called without get_cost.
- lab_generateshallow
Generate an image on the production pipeline (fal.ai, quota-tracked, persisted to the project's gallery). Waits up to `wait_s` seconds (default 45) for the image and then answers with the finished rows — image_url set, inline previews attached, so the picture is in the answer like lab_job_status with preview. Pass `wait_s: 0` to return right away with rows in status 'pending' (poll lab_job_status with id + project_id then). If the budget runs out, the rows come back as they are and `fertig: false` says so. Default tool is 'flux_pro'; use 'nano_banana_pro' (Gemini 3 Pro Image) for the Papercut-style look. Pass seed_image_url to run img-to-img guided by an existing image URL. `get_cost: true` preflights credits — it returns the price without generating anything. FOR A PERSON WHO MUST LOOK THE SAME across several images, do not re-describe them per prompt: get an id from lab_list_characters (or build one with lab_create_character + lab_generate_character_reference) and pass it as `character_refs`.
- lab_generate_character_referenceshallow
Generate the reference sheet for a character — six core views rendered from the sheet's `prompt_prefix_en`: detail (three-quarter close-up, the identity anchor), frontal (frontal close-up), profile, fullbody (front), fullbody_back (back view: hair and the back of the costume) and costume (the outfit on an invisible mannequin, NO person — use it where the costume is meant, never as a face reference). Back view and costume are derived from fullbody, everything else from detail. The poses pose_sitting, pose_walking, pose_action are optional extras for blocking — not part of the default run and not used as references for image or video models. A seventh view, 'detail_smile', is NOT in the default set and must be asked for: the same close-up with the mouth open and the teeth visible. Render it for every character who SPEAKS — otherwise the model invents the teeth and the jaw the first time they laugh, and the smile arrives as somebody else's mouth. It is an extra view for the mouth, never an identity anchor: a smiling reference carries its smile into every shot, funerals included. MEASURED 2026-09-15 (n=10, criterion fixed beforehand): the teeth land 10/10, but the PERSON only holds in about 4 of 10 even with the anchor active — two runs were plainly a different man. Generate it, then LOOK before you rely on it; the failure is obvious to the eye (a stranger's mouth on your character), not silent. THIS IS WHAT MAKES A SHEET USABLE: until it has run, lab_generate rejects the id as `character_refs`. Step 2 of 2 after lab_create_character. COSTS CREDITS — one provider call per view, so the default run is six. Pass `views` to render fewer. Takes about 25 s PER VIEW (the tool requests them one by one, anchor first), so a full run is 2–3 minutes. If a single request times out, the answer says `noch_in_arbeit` instead of failing: that view is still rendering and already paid for — check it with lab_get_character_sheet, do NOT re-run it. The sheet needs a `prompt_prefix_en`; the backend regenerates one on demand but only best-effort, and answers 400 if that fails too. Views whose image could not be mirrored to R2 are deliberately NOT saved and come back in `nicht_gespiegelt` — those views are missing, not broken, and a re-run renders only what you ask for.
- lab_generate_location_variantsshallow
Generate reference images for a location board (costs quota). Without `variants` the backend picks its default set. The images are what makes a board usable as a visual reference.
- lab_generate_musicshallow
Generate a MUSIC track for a project (Stable Audio via fal.ai) — the first step of the rhythm chain, and the only one that costs credits. ASYNCHRONOUS: the call returns immediately with a row whose `audio_url` is null and `metadata.status` is 'pending'. Nothing is playable and nothing can be bound yet. Poll lab_list_audio (audio_type 'music') until that row's status is 'completed' and audio_url is set — usually under a minute, and the backend gives up after five (status turns 'failed', metadata.error carries the reason, and the credits are refunded). PUT THE TEMPO IN THE PROMPT if you intend to cut on the beat. This is measured, not assumed: a soft swing track measured at confidence 0.164 (unusable), an ordered hard pulse ('techno, 128 bpm, four-on-the-floor') at 0.621. The tempo detector is autocorrelation over an onset envelope — it finds a hard pulse and shrugs at drone, ambient and rubato. Then: lab_bind_audio, lab_beatgrid, lab_apply_rhythm.
- lab_get_charactershallow
Get ONE character sheet in full — every descriptive field plus the three that decide what you can do with it. `prompt_prefix_en` is the text block describing this person; it is what the backend prepends wherever the sheet is used. `reference_images` decides whether the sheet is usable at all: lab_generate REJECTS a character_refs entry without one, before any quota is spent — if it is empty, run lab_generate_character_reference first. `states` carries the state sheets against character drift (costume, light, physical condition); lab_get_character_sheet renders them agent-readable.
- lab_get_character_sheetshallow
The character sheet PREPARED FOR PROMPTING: base prefix, the state sheets by name, which reference views exist, and the ready-made sentence to paste into a lab_generate prompt. Same source as lab_get_character, different shape — use this one when you are about to generate, and lab_get_character when you want the raw record. State sheets exist against character drift: one sheet per costume, light or physical-condition change, so a person stays the same person when the situation changes. THIS IS THE ANSWER to 'same person, different light': character_refs alone routes to i2i and drags the reference's lighting along, so a drastically different light fights the reference. A state sheet puts the change into the TEXT, where the prompt can win. Free.
- lab_get_contextshallow
Read the accumulated context/output for one pipeline module of a project (e.g. the IDEE, STORYBOARD or SHOTS stage). Needs project_id and module name.
- lab_get_dossiershallow
Poll a dossier job by job_id (from lab_dossier). status is queued|processing|done|failed. When done, result.archiv_url is a signed https link to the ZIP that loads WITHOUT a login and expires after 24 h — call again for a fresh one. result.fehlend lists takes that could not be loaded.
- lab_get_exportshallow
Poll an export render job by job_id (from lab_start_export). status is queued|processing|done|failed; when done, the result (output url) is included. Call repeatedly until done|failed. NB: this is the EXPORT poll — different from lab_get_generation. Where the address sits depends on the profile: a rendered film is in video_url, but profile alpha_png_sequence delivers a ZIP of RGBA PNGs and therefore leaves video_url null and puts the address in archiv_url — a .zip under a key called video_url would read as something playable to every client. download_url carries the address in both cases and is the safe one to hand to a user. All result addresses — video_url, download_url, archiv_url and the provenance record herkunft.pdf_url / herkunft.json_url — are signed https links that load WITHOUT a login and expire after 24 h; call lab_get_export again for fresh ones. view_url is the short session-bound form for the web app only.
- lab_get_jobshallow
Get the status of a background job by job_id (status is queued|processing|done|failed). Poll this after starting a long-running generate/export. Returns the job record.
- lab_get_locationshallow
Get ONE location board in full — all descriptive fields plus its reference images and `prompt_prefix_en`. Use it to check what a board actually anchors before generating with it.
- lab_get_projectshallow
Get a single FilmLab project with its full stage state. Needs the project_id (from lab_list_projects).
- lab_get_sequenceshallow
Get ONE sequence in full — timeline (the shots in order), audio_tracks, transitions, duration_seconds and render status. Check `timeline` here before starting a continuity pass: an empty one is the single most common reason the pass refuses.
- lab_get_stateshallow
One call, the whole picture: account (tier, credits, reset), default models with price, jobs in flight, catalog freshness, project count. Pass project_id for that project's sequences, assets and review-queue length. Read-only, free.
- lab_gradeshallow
Apply a deterministic colour grade to an image already in the project gallery — no re-generation, no provider, no credits. The look is computed pixel-exact (exposure, saturation, hue, lightness, contrast, film grain) and lands as a new gallery image the sequencer and export pick up. The same recipe on the same image always yields the same result (grain is fixed-seed), so a look is reproducible across every still. Set from_colorist to start from the project's colorist crew brief (look, contrast, grain) and tune with the sliders on top. At least one adjustment OR from_colorist is required. Synchronous — the graded image_url comes straight back, no polling.
- lab_grade_clipshallow
Set the colour grade of ONE clip in the edit (Murnau), or of the whole programme with `programm: true`. It is the same grade a colourist sets in Murnau's colour workspace, and the export uses it: Murnau bakes the export LUTs when you set it. Only the fields you send change (`zuruecksetzen: true` starts from neutral). Fields and ranges, as the sliders: exposure in stops (−5..5); contrast, saturation, temperature, tint −100..100; hue −180..180; lift/gamma/gain/offset as {x, y, master}, each −1..1 (x/y move the colour wheel); log as {shadow|midtone|highlight: {x, y, master}} — the Log wheels in ACEScct, each acting only on its range of brightness (shadows below ~4 % linear, highlights above ~50 %), master ±1 ≈ ±2 stops there; schritte as a list (≤ 8) of further grades with the same fields (plus name), applied in series after this grade — serial nodes; creative and sek stay on the grade itself; hdr as {dark|shadow|light|highlight: {x, y, master}} — HDR zone wheels centred −3/−1/+1/+3 stops around 18 % grey, master ±1 ≈ ±1.5 stops; curves as {master|r|g|b: [[x,y],…]} 0..1; boost, shadows, highlights −100..100; intensity 0..100 (0 = original). Per clip also `sek` — a secondary correction: {qualifier: {hueCenter, hueWidth, satLow, satHigh, lumLow, lumHigh, softness, invert}, fenster: [{form: kreis|rechteck|verlauf|polygon|bezier, cx, cy, rx, ry, winkel, weich, invert, modus: add|sub, punkte (polygon/bezier only: 3–16 resp. 3–12 [x, y] in the window's own unit space, scaled by rx/ry and turned by winkel — bezier draws a smooth closed curve through them)}], grade: {saturation, exposure, temperature, tint, hue, schutz}} — schutz 0..100 takes the clip's and the programme's grade back inside the selection (100 = ungraded there, e.g. to protect skin); `sek: null` removes it. Any level also takes `warper` — the Color Warper: {huesat|chromalum: {res: 6|12|24, punkte: [[i, j, dx, dy], …]}}; node (row i, column j) sits at (j/res, i/res) and is moved by (dx, dy) in −1..1. huesat plane: x = 0.5 + 0.5·sat·cos(hue), y = 0.5 + 0.5·sat·sin(hue) (lightness kept); chromalum plane: x = sat, y = 1 − lightness (hue kept). Only moved nodes; `warper: null` removes it. Call WITHOUT `grade` to list the clips (clip_id, start/end, current grade, input profile) and the programme grade. Measure first and after with lab_scopes — its `vorschlag.grade` is a computed correction you can pass here as `grade`. Writes state, costs nothing.
- lab_grade_from_resolveshallow
Suggest a FilmLab grade look from a Resolve LUT name or path — read-only, no cost. First call resolve_node_graph_lesen on the local FilmLab bridge (filmlab_bruecke_mcp.py), a SEPARATE MCP server, and pass its lut field here. The agent connects these two calls: this Cloudflare Worker cannot reach the bridge at 127.0.0.1 on the user's computer or fetch the name itself. Only the name is matched; the Resolve LUT file is neither read nor imported, and its exact grade is not reproduced. Returns look, reason, alternatives and sicher (false means the name was not confidently recognised). Apply with lab_grade(look: …) only once the user agrees.
- lab_grade_suggestshallow
Suggest a grade look for a project — read-only, no cost. With image_id, includes the image prompt; without it, uses only the colorist crew brief. Returns a recommended look name with a reason and alternatives; apply it with lab_grade(look: …) once the user agrees.
- lab_herkunftshallow
Declare or list where a project's material comes from: 'eigen' (made by people) or 'ki' (AI-generated or AI-altered). Exports decide the EU AI Act Art. 50 disclosure per clip from this — undeclared material counts as AI. With asset_key + herkunft: declare (the file is checked for an AI mark; one found keeps it AI and the answer says why). With project_id only: list every declaration with its effect (`wirksam`).
- lab_identitaet_pruefenshallow
Check whether still images of a project show the SAME character as its character sheet — before paid clips are made from them. Each image is compared against the sheet's detail and fullbody views. It judges identity (species, build, colouring, head shape, large markings), NOT style, light, pose, place or props — and deliberately NOT micro details like an ear notch or the number of fingers, which no image model holds reliably. Free. Runs in the BACKGROUND: returns a `job_id` with HTTP 202 — poll it with lab_get_job until status is done|failed; the result lists per image passt, sicherheit, abweichungen, begruendung (or error). Up to 16 images per call, all completed images of this project. The sheet needs a reference image (lab_generate_character_reference).
- lab_job_statusshallow
Poll the status of an image or video generation started by lab_generate/lab_animate. There is no single-item status endpoint on the backend — this fetches the project's full image/video list and filters by id, so it needs BOTH project_id and id (the id alone is not enough). status inside the returned item's metadata is 'pending'|'completed'|'failed'; when completed, image_url/video_url is populated. When the run is done, the answer may additionally carry schritte (the step trail of this run) and review (a machine check against the confirmed brief, present once for a run that went through lab_propose/lab_run_proposal — absent for a still-pending run, a run started outside a proposal, or a repeat poll after the one-time check already ran): abweichung lists every field that came back different from what was confirmed, possibly empty; tool means the provider fallback chain degraded the run; bild means a vision check found the result contradicting an explicit statement of the brief (free for the user, once per run; bild_review says why it was skipped). A failed or degraded proposal run may also carry plan_b: alternatives with checked prices and proposal IDs, offered once. Present them to the human; never start them yourself. Call lab_run_proposal only after the human confirms an alternative.For a run that carried a kamerapfad, metadata.kamerapfad says what arrived and, as `angewandt`, WHICH form of it was actually sent — als_text (prose), als_regiebefehle (bracketed director commands, MiniMax/Hailuo), eigene_regie (the prompt already carried bracketed commands, so the path was deliberately NOT added next to them — eigene_regiebefehle lists them) or nicht_ableitbar (nothing of the path reached the prompt, with the reason). `sprache` next to it names the family rule and the source it rests on. For a reference-motion run, metadata.referenz_masse is the reference trail: one row per reference with what it measured (original_px) and, if the backend had to scale it to the model's limits, what it became (angepasst_px) and the address that was actually sent. Look there when a result ignores a reference or looks softer than the source — a silently rescaled reference looks like a badly generated one.
- lab_jobs_inflightshallow
Are any FilmLab generations running RIGHT NOW, across ALL projects? Use this before anything that restarts the backend (a deploy recreates the container and kills running jobs, losing paid credits), or to answer 'is the lab busy?'. Unlike lab_job_status/lab_batch_status this needs no id — it lists every job in queued/processing PLUS every direct image/video/audio/vfx generation currently within its own grace window (lab_generate/lab_animate write straight to their result tables, never to the job queue — omitting job_type covers both; naming one job_type narrows to the job queue only, since a direct generation's type vocabulary differs). Returns {busy, warm[], stale_count, stale[]}: `warm` are jobs that actually progressed within stale_after_seconds and are the ones a restart would destroy; `stale` are queue jobs stuck longer than that (a crashed worker leaves rows in 'processing' forever) — they are reported but do NOT make busy true, otherwise one zombie would block every future deploy. A direct generation is never 'stale' here — past its own grace window it stops being reported by the backend entirely and becomes the orphan sweep's job, not this check's. Carries no prompts or payloads: this view crosses project boundaries, so it returns only type, state and age.
- lab_layersshallow
Produce ONE element on a transparent background: generated, then cut out and stored as an alpha PNG in the project's gallery. This is the counter-move to the one-shot lottery — cast, props and foreground pieces are made SEPARATELY, arranged as a set afterwards and only then unified, so a wrong hand or a wrong lamp is re-made alone instead of re-rolling the whole frame. The element is deliberately optics-neutral: no lens or camera suffix travels with it, because the look is decided later on the finished comp and every layer is meant to inherit the same focal length and bokeh. ASYNCHRONOUS: the row comes back with status pending and image_url null; poll lab_job_status (type 'image') with its id until the url is populated — that url IS the cut-out. Costs credits when called without get_cost.
- lab_letzter_frameshallow
Extract the LAST frame of a finished clip as a new image (returns image_id, image_url, zu_dunkel). Use it as source_image_id to continue one unbroken take, or as a still. A frame that is too dark (zu_dunkel: true) makes a bad start image — say so instead of animating from black. Free (no credits). Chains (lab_verkettung) do this themselves for uebergang=durchgehend.
- lab_list_assetsshallow
List a project's media assets (image/video/audio) with their URLs. Optionally filter by asset_type. Returns up to 20 with a total count. NOTE: asset URLs are on media.andresmarder.com, whose CDN WAF blocks some non-browser User-Agents (e.g. curl's default → 403). Prefer a browser User-Agent, or hand the URL to the user rather than fetching it server-side.
- lab_list_audioshallow
List a project's generated audio rows, newest first — this is the POLL for lab_generate_music. Read two fields: `metadata.status` ('pending' | 'completed' | 'failed') and `audio_url`. A pending row has no url, and nothing downstream works with it: lab_bind_audio silently leaves the track empty (resolve-stems only takes rows that carry a url) and lab_beatgrid has no file to open. A failed row carries `metadata.error` and its credits were refunded. Reads only — no state changes, no credits.
- lab_list_charactersshallow
List the character sheets in the FilmLab cast register (id, name, age, gender, project_name, prompt_prefix_en). Call this BEFORE lab_generate whenever a person must look the same across several images: pass the id you find here as `character_refs` instead of re-describing the person in every prompt. Optional `search` matches name or project name (substring, case-insensitive). It shows YOUR OWN characters plus the public catalog (sheets explicitly made public and bound to no project). Characters of other accounts' projects never appear — projects can be confidential. New characters are private. The register returns at most 50 sheets, newest first, and offers NO paging — 20 are shown here. `total` therefore counts at most 50: with more than 50 sheets it understates, and `search` is the only way to reach the older ones. Nobody there yet? Create a sheet with lab_create_character.
- lab_list_exportsshallow
List past export jobs for a project (each with job_id, status, profile). Returns up to 20 with a total count. Finished rows carry the same signed, login-free result addresses as lab_get_export (download_url, herkunft.pdf_url, …; valid 24 h).
- lab_list_location_scansshallow
List a project's location scans with their reconstruction state — this is the POLL for lab_location_recon and the place the scan ids come from. Read `status`: 'pending' (clip uploaded, nothing reconstructed yet), 'reconstructing', 'done' (splat_url/glb_url/board_url are filled), 'failed' (error says why). Listing is what ADVANCES a running reconstruction from the outside world into the row, so calling this is how the state moves at all. Reads only — no credits.
- lab_list_locationsshallow
List location boards, newest first — START HERE to find a `location_id` for lab_generate / lab_animate. Each entry carries its `prompt_prefix_en`: that is the exact text appended to your prompt as 'Location: …', so you can judge whether the board fits BEFORE spending quota. A board with an EMPTY prefix anchors nothing — it will silently do nothing. Fix it with lab_enrich_location_prefix or pick another board. Only public boards are returned, max 50 from the backend and 20 shown here; if your place is not listed that is a limit, not a failure — create it with lab_create_location.
- lab_list_modelsshallow
The model catalog: what every video or image model can do — resolutions, durations, aspect ratios, audio, reference limits, price per second or per image — grouped by capability class with a one-line explanation per group. Read this before choosing a `tool` for lab_generate/lab_animate/lab_propose; copy ids verbatim. Cached briefly; `stand` says how fresh.
- lab_list_project_locationsshallow
Location boards bound to ONE project. Narrower and more correct than lab_list_locations when you already know the project: it cannot leak boards from a different project with the same title. Boards created before the project binding existed (project_id NULL) deliberately do NOT appear here — use lab_list_locations for those.
- lab_list_projectsshallow
List FilmLab projects (id, title, current pipeline stage). Call this first to find a project_id for the other tools. Shows up to 20 items; `total` counts your active projects (up to 200) and `truncated: true` means the list is cut off — sorted by last change, so older projects drop out of the shown window first.
- lab_list_sequencesshallow
List a project's sequences, newest first. Use it to find a `seq_id` instead of creating a second sequence for the same cut.
- lab_list_voicesshallow
List a project's cloned voices (lab_voice_clone results) — id, label, voice house, sample and preview URLs. This is where a `voice_id` for lab_voice_tts or lab_dub comes from, and where you look up which house a voice belongs to before pricing it. Both houses are listed unless you narrow it. Reads only — no state changes, no credits.
- lab_location_panoramashallow
Generate a 360° equirectangular HDRI panorama of a place (costs quota). Pass loc_id to persist it on that board, so the viewer finds it again; without loc_id it is a one-off.
- lab_location_reconshallow
Reconstruct a real place in 3D from a scan clip: keyframes are pulled from the clip server-side and turned into a point cloud / splat on the location board, so a scouted room can be looked at from angles nobody filmed. THE SCAN IS NOT MADE HERE — it is a walk-around clip uploaded by the FilmLab camera app together with the phone's lens data. This tool takes one that already exists; lab_list_location_scans gives you the ids. SLOW AND NOT A JOB ROW: the answer comes back as 'reconstructing', and the finished state is picked up ONLY by lab_list_location_scans — lab_job_status and lab_get_job will never show this one finish. If the call times out, the reconstruction normally keeps running on the server: list the scans instead of firing it again. Re-running is allowed from any state that is not done.
- lab_look_in_postshallow
Read or set a project's 'look in post' flag. Use it when the person grades in DaVinci Resolve with the FilmLab Look plugin and wants the lens and film look applied there instead of baked into the generated pictures. With project_id only: read. With look_in_post true, image and video prompts of the project no longer ask for grain, halation, vignette, chromatic aberration or soft edges — the plugin adds them in Resolve; false puts them back. It takes effect only while a LensLab lens set is chosen for the project (Pose Director / camera panel in the FilmLab app); without one the flag is stored but changes nothing. The answer always carries look_in_post, optik (the chosen lens set or null), wirkt (whether it takes effect now) and a sentence to pass on.
- lab_look_matchshallow
Check the colour CONTINUITY of a scene in the edit (Murnau): every shot is compared with the scene's reference shot (the first, or `referenz_clip_id`) at the SAME scene points — found by feature matching (ORB + homography) between the two frames, each rendered through its export path. Image-wide statistics would measure the framing, not the grade (measured: up to 5000 K apart with no grade change). At those points: white point (Kelvin and mired), lightness (L*), colour distance (ΔE). Over the threshold (8 mired, L* 4, ΔE 3) a shot gets a `befund` with the number (e.g. '150 K wärmer als die Szene (13 Mired)') and a `vorschlag.grade`: a clip grade fitted so the shot's source colours land on the reference colours, with the deviation expected afterwards. Pass it to lab_grade_clip, then run lab_look_match again. Shots without enough shared content (reverse shot, different subject) come back as `vergleichbar: false` with the reason — nothing is guessed. Scenes come from the sequence's shots (lab_shots); without them give the shots as `clip_ids`. At most 24 shots per call. Writes nothing, costs nothing.
- lab_mixshallow
Set the sound mix of a sequence: per track `volume_db`, `pan`, `mute`, `solo` and `effects`. Every field you send is rendered — the backend rejects what it cannot render (422 with the reason), so a saved mix is the mix you hear. Tracks are the stems `dialog`, `music`, `sfx`, `atmo`, plus `master` (effects only: eq, compressor, limiter). Only the fields you send change; `effects` replaces that track's whole effect list. Effects: gate, eq, deesser, compressor, reverb, limiter — fixed order, one of each per track; give a `preset` (with its written reasoning), a one-knob `knopf` (0–1) or explicit values. Ducking is an effect too: {type:'ducking', quelle:'dialog', amount_db, attack_ms, release_ms} lowers this track while `quelle` is active. `naht_ms` (0–500) fades every seam between the clips of a stem with an equal-power fade — against clicks and room jumps at the cuts of a stem built from pieces; 0 = hard edges. The sfx stem of lab_ton_durchlauf comes with 30. Volume `automation` replaces the track's breakpoints {t_s, db}, in seconds from the sequence start, interpolated linearly in dB; [] clears it, and master does not support it. Call with `katalog: true` (and no tracks) to get every effect, its ranges and the presets with their reasoning. Any change discards the rendered mixdown. Changes state, costs nothing. Next: lab_mix_render, then lab_mix_messen.
- lab_mix_messenshallow
Measure the RENDERED mix: integrated loudness (LUFS), true peak (dBTP) and loudness range (LU) of the master, measured on the mixdown file itself. Per stem the same values, speech-gated (under the dialog / in its pauses), and how many LU each stem sits under (or over) the dialog in dialog passages — exact. A stem's level inside the master is an estimate (stem plus the gain the master applied) and is labelled as such. Needs a current render whose stems are still the ones it was made from: any change with lab_mix discards it, and a newer audio file in a stem makes it stale (409 then — render first). Runs as a BACKGROUND JOB: you get a job_id at once; poll lab_get_job until done — the measurement is in job.result. Measure before and after a change to prove what it did. Writes nothing, costs nothing.
- lab_mix_rendershallow
Render the sequence's mixdown, normalised to a loudness target: `broadcast` (EBU R128), `web` or `youtube`. With `auto_preset` it runs the AUTO-MIX instead: it measures every stem speech-gated (under the dialog vs. in its pauses), sets faders, ducking and a master limiter by the preset (`spielfilm`: music clearly under the dialog; `doku_vo`: the narrator leads), renders, and measures the result. Every auto-mix decision comes back as one sentence with its number, plus missed lower loudness bounds — read them, they are the reasoning you can pass on. Runs as a BACKGROUND JOB: the answer is a job_id at once; poll lab_get_job until status is done (the result — mixdown, measured loudness, the auto-mix report — is in job.result) or failed (job.result.status and detail say why: 422 solo on / dialog muted / no speech, 409 the tracks were edited meanwhile — nothing was overwritten). If a render of the same kind is already running for this sequence, you get THAT job_id back instead of a second render. Costs nothing. Next: lab_get_job, then lab_mix_messen.
- lab_playbookshallow
The rules of one working surface, generated from the code: what the surface is, what an agent can trigger itself, what exists but only by hand, and what does not exist at all. Call this BEFORE answering what is possible on a surface — the three lists come from a table with a code reference per entry, checked in every PR, not from memory. Saying "that does not exist" about something the editor can do is the failure this tool prevents. Surfaces: edit, vfx, audio, idea, script, axis, location, crew, cast, pose, capture.
- lab_prompt_transformshallow
Turn a loose idea into a production-ready image or video prompt — the same Dreamer engine the FilmLab web UI uses (modes: beautify, storyboard, polish, format, shorten, expand, simplify, custom, stiluebernahme). beautify GENERATES (a 50-character thought comes back as a full prompt); polish/format/shorten/expand/simplify PRESERVE what is there. medium=video plus depth=skeleton yields the 15-block production prompt; depth only applies to video. anlass only applies to beautify. custom and stiluebernahme require instruction. For video the answer carries clip_duration_seconds — hand THAT number to lab_animate(duration_seconds), otherwise a prompt timed to 12s gets rendered as lab_animate's 5s default. In an Apps-capable host this opens as a form you can adjust and re-run; elsewhere it answers with the prompt as plain text. Pass `tool` (the registry key you will hand to lab_animate/lab_generate) and the finished prompt is laid out in the skeleton of that model family — location, camera, lens and light land where that family reads them, worded the way it reads them; families without a measured rule keep them appended as before, and the answer says so (prompt_skelett).
- lab_proposeshallow
Propose a generation for the user to confirm: validates the parameters against the catalog, computes the price, and shows a card (widget hosts) or returns the same object as text. NOTHING runs until lab_run_proposal is called with the returned vorschlag_id — by the card's button, or by you after the user said yes. Without a measured price there is no vorschlag_id and no button: the answer then says so instead of offering an estimate as if it were a quote. Free.
- lab_reference_motionshallow
Render a new clip FROM the motion of an existing one: your reference clip leads (camera move, blocking, timing), the model restyles what happens in it. Pass the clip's URL directly — the one you already have from lab_list_assets (asset_type 'video'), lab_job_status or lab_review_queue; nothing is looked up. Reference images bind cast, place and look; in_sec/out_sec cut the reference server-side before it ever reaches the provider, so you pay for the excerpt, not the source. Same backend path as lab_animate's source_video_id, with the fields that only exist there. Costs credits when called without get_cost. WITHOUT a reference clip (leave reference_video_url out), the images and sounds in `referenzen` alone guide the run — only for models whose lab_list_models entry says referenzen_ohne_video: true, and only FACELESS references (ort, stil, bild, stimme, ton): Seedance 2.5 rejects faces as reference images, even invented characters (measured 2026-09-27), so `figur` is refused before anything is charged. For a person, build a still with them first and animate it with lab_animate. Name the references in the prompt as 'reference only, never shown on screen', and avoid the word 'static' for short shots — it tends to return frozen frames.
- lab_referenz_aus_bildshallow
Attach an existing project image (an image_id from lab_umzug, lab_get_job result.bildzeilen or lab_generate) as reference: `ziel: 'figur'` makes it a view of a character (default view 'detail', the face anchor). `personenbezug` is REQUIRED for a character and has no default: 'keine_reale_person' or 'reale_person' — the latter needs a likeness_ref from the Likeness Register and turns the character into a digital double, checked before every later generation. `ziel: 'location'` stores it as the location's reference (viewer, continuity check). It does NOT steer generation — only the description does; `beschreibung_ableiten: true` derives the description from the image (does not overwrite an existing one unless `ersetzen`). An occupied character view answers 409 unless `ersetzen: true`. Free, except the description derivation (one vision call).
- lab_regie_technikenshallow
Directing techniques: camera angle, framing, composition, movement and lighting, each with the emotional effect it creates (wirkung), when to use it (zweck_de), when it backfires (vermeiden_de) and a model-neutral prompt fragment (prompt_en). Search by effect (e.g. wirkung=bedrohung, isolation, sehnsucht) to find the ways to get there, then pass up to three `schluessel` to lab_prompt_transform(techniken) — the fragments are appended verbatim, not rewritten. One angle, one movement and one lighting setup per shot; framing and composition stack. Read-only, free.
- lab_render_framesshallow
See the DELIVERED film: up to 12 frames from the finished export (lab_start_export → lab_get_export status done), tiled into one image and shown. This is the rendered picture WITH everything the render adds — lens/grade, lower thirds, title cards and the AI badge — so use it to check the result, e.g. 'is the lower third readable at 7 s, does the badge cover anything'. lab_capture shows the cut BEFORE rendering (computed from the timeline, without those layers); this tool shows what was actually delivered. Give `sekunden` (seconds into the exported film) or `verteilt` (n frames spread evenly; default 6 when both are missing). A second past the end is an error with the film's length, not a silently clipped frame. Only finished exports with a video (not archive/PNG-sequence profiles). Free (no credits).
- lab_restyle_locationshallow
Restyle an existing board towards a wish (costs quota) — same place, different look, e.g. 'the same flat, twenty years later'. Changes the board itself, so images generated afterwards follow the new style. Also the repair path for a board whose prompt_prefix_en is a raw field dump (lab_create_location returned prefix_generated: false): restyle it with a wish like 'keep the place, write a proper image prompt'.
- lab_review_assetshallow
Review generated assets: set verdict (accepted|rejected|pending) and/or selected. Pass ONE id, or `ids` for a bulk review — after a generation run there are usually dozens to sort, and clicking through them one by one is why the review fields went unused. Rejected assets drop out of the default listings and become prunable. Note: single-id calls make `selected` exclusive per scene (one chosen variant per scene_ref); bulk calls do NOT, because a bulk over one scene would keep resetting itself and only the last id would stay selected.
- lab_review_queueshallow
Browse GENERATED rows (images or videos) — newest first, each with the INPUTS it ran on. Every row carries `inputs[]` (start/reference images, reference videos, character refs — role + url) and `params` (model, mode, resolution, seed…). Read those before comparing two runs: a run without its inputs is a claim with a picture attached, and a comparison described as one-variable has more than once turned out to differ in three. An input whose URL was never recorded appears as `origin: 'unrecorded'` — that is a gap in the write path, NOT a text-to-* run. Two modes. PER PROJECT (pass project_id + type): adds the review filters — verdict, selected_only, scene_ref — and carries `selected`. ACROSS PROJECTS (omit project_id, or pass since/until/tool_used/cursor): the time-range view for 'what ran on August 3rd?'. The review filters do not exist there and are rejected rather than silently dropped. Page with `next_cursor`.
- lab_rezept_montageshallow
The Montage recipe: one recurring character in 8–16 independent everyday gags, cut on the beat into a 9:16 reel of about 6–11 seconds with a music bed. It runs the existing steps in order — gags (lab_situationen), stills with the character and the phone-flash look (auto-storyboard 9:16), identity check with ONE retry per deviating still, a STOP until the human accepts the stills (lab_review_asset), music, sequence, beat grid and rhythm, beat-length clips, placing them, export (social_vertical). If the export contains a synthetic PERSON or VOICE, it needs a release only a signed-in human can give: the recipe STOPS with stopp freigabe_noetig — the human exports that sequence with social_vertical in the web app and confirms the wording; the next weiter takes over that export and checks it. Each call with aktion weiter does exactly ONE step and stores the state in the project, so an interrupted run continues where it stopped; call it again until phase is fertig. MONEY: aktion preis (or get_cost) returns the expected and the maximum price per item and a recommended cap — free. Paid steps run only inside a released lab_auto_lauf (lauf_id) and the recipe checks its free amount before every paid step. The character must already have a sheet with a reference image (lab_create_character with gattung, then lab_generate_character_reference) — it is not part of the price. aktion stand shows the state, abbrechen deletes it (generated material stays).
- lab_run_moduleshallow
Run ONE pipeline module for a project (context is injected from upstream modules + crew agents). SYNCHRONOUS and LLM-heavy: light modules return in seconds; heavy ones can exceed ~55s and then time out (504) — run those in the FilmLab web app instead. Pass an invalid module name to get the list of valid module keys. Returns the module output.
- lab_run_proposalshallow
Run a proposal exactly as shown — same model, same parameters, same price. Called by the card's button, or by you after the user confirmed. Single use: the proposal is consumed BEFORE the run, so a second call is refused instead of paying twice. Valid 15 minutes, for the account that created it. Costs credits. The run is checked against what you confirmed only when it FINISHES; poll lab_job_status and read review there. This answer carries review only if the run completed synchronously.
- lab_schnitt_exportshallow
Export ONE sequence as an editing file for DaVinci Resolve, Premiere or Final Cut, so the cut can be finished there. Costs nothing. fcpxml (recommended for Resolve): V1 as the main storyline with gaps, the sequence's transitions as centered cross dissolves (dropped where the next clip has no head or at a gap), audio stems and V2+ as connected clips. otio: OpenTimelineIO JSON (video and gaps, speed; no audio, no transitions). edl: CMX 3600 (video plus up to 4 audio channels; no transitions). The answer carries the whole file in `inhalt` and a file name — write it to disk for the person. Media are referenced by their FilmLab URLs: in Resolve, File > Import > Timeline, then relink offline clips by file name.
- lab_scopesshallow
Measure ONE clip of the edit as numbers instead of a picture: a frame is rendered through the clip's export path (input profile, grade LUT, secondary correction) and measured — luma percentiles (P1/P50/P99, Rec.709), mean R/G/B, green excess (G minus the mean of R and B: >0 green cast, <0 magenta), vectorscope centroid (Cb, Cr), clipped highlights and crushed shadows. `befund` says what is off in words with the number; `vorschlag.grade` is a correction computed on a sample of the source through the clip's full grade (gamma wheel master first, then exposure, temperature, tint, gain wheel) towards median luma 0.42 and no cast WITHOUT pushing highlights into clipping, with the values it expects — pass it to lab_grade_clip, then measure again. When nothing more is gained, `vorschlag.grade` is null and `grund` says why. Give clip_id (from lab_grade_clip without grade) or zeit_s (seconds on the timeline); default is the middle of the clip. Writes nothing, costs nothing.
- lab_search_catalogshallow
Search the FilmLab universe catalog of AI tools, news and companies. Query must be at least 2 characters. Returns up to 20 matches with a total count.
- lab_sfxshallow
Generate or CLEAN UP a SOUND track other than music — sound effects, ambience/atmosphere, dialog, a voiceover, FOLEY scored to an existing clip, or the repair kinds that take an EXISTING recording apart instead of inventing one: denoise (take the noise out), split (separate it into stems), isolation (keep the voice, drop the rest). All of it goes through the same audio pipeline as lab_generate_music. ASYNCHRONOUS: the call returns immediately with a row whose `audio_url` is null and `metadata.status` is 'pending'. Nothing is playable yet. Poll lab_list_audio (matching audio_type) until that row's status is 'completed' and audio_url is set; a failed row refunds its credits and carries metadata.error. The backend picks the provider for the chosen `art` on its own — there is no `tool` parameter here.
- lab_shotsshallow
Read the SHOT layer of a sequence — which clips form one shot, which scene it plays in, who is in it, and what the continuity pass found. This is the layer above the timeline: lab_get_sequence gives you clips in a row, this one gives you the cut. Costs nothing, writes nothing. Use it before changing a cut: a shot binds clip_ids, so the times come out of the timeline and a shot whose clips you shorten simply gets shorter. Read `clips_ohne_shot` as well — it says how far the meaning lags behind the timeline, and an empty `shots` list usually means nobody has derived them yet (lab_shots_ableiten does that, for free). Every shot reports `clips_verwaist` (clip_ids that no longer exist in the timeline) and `zusammenhaengend` (false when another shot's clip sits between this one's): a torn shot is allowed — one location cut into twice — but it says so, instead of showing a duration longer than the sum of its clips.
- lab_shots_ableitenshallow
Derive the shot layer from what the clips already say about themselves — consecutive clips of the same scene become one shot, and a scene that returns later becomes a second one (one location cut into twice is two shots). Costs nothing: it groups rows and reads titles, it generates nothing. Titles come from the project's shotlist where the scene is in there, so this is more than a regrouping — it fetches meaning the pipeline already produced. SHOTS YOU SET BY HAND SURVIVE. Only derived ones are replaced, and clips already held by a manual shot are left out of the grouping entirely — a derivation does not take handwork's material away. Read `clips_ohne_szene` in the answer: those clips say nothing about where they belong, so each became its own shot. That number is a job for the pipeline, not a fault of this call — and grouping two nameless clips would be a claim about connection that nobody made.
- lab_shots_setzenshallow
State the shot cut yourself: which clips form one shot, what it is called, which scene it plays in. This is the counterpart to lab_shots_ableiten — that one groups by the scene the clips already name, this one is for the judgement no field carries. Costs nothing. Use it where derivation cannot reach: ingested footage has no shotlist by nature, and a sequence whose clips name no scene would come out of a derivation as one shot per clip — the timeline under another name. It is also the ONLY way to build the 'movement' layer (arcs over shots); the derivation only ever writes 'shot'. REPLACES the whole level in one go: every shot of this `rung` that you do not list is gone. The other level is untouched — recutting shots does not throw the arcs away. Refusals happen BEFORE anything is written: an unknown clip_id, or the same clip in two shots of one level. A half-set shot list looks like a result and is none. Read lab_shots first and send its clip_ids back — a shot binds clip identities, not time ranges, so shortening a clip later simply shortens the shot. What you set here counts as handwork: a later lab_shots_ableiten leaves these shots alone and does not touch their clips.
- lab_situationenshallow
Suggest independent visual gags for a character and theme. Free text generation, no images or credits spent. Returns anzahl entries with titel, bild_en and bewegung_en: one moment and one strong action each, no story sequence or references between entries. figur accepts a character-sheet id (uses its prompt_prefix_en) or a free-text character description. Select 8–16 suggestions for lab_auto_storyboard with figur_id.
- lab_start_exportshallow
Start an ASYNC export render of a project sequence. Returns a job_id immediately (status 'queued') — does NOT block. Then poll lab_get_export with that job_id until status is done|failed. Needs the sequence_id to render (an integer from the project's sequences). `derivatives` asks for extra cut-downs of the SAME render (portrait for social) alongside the main file — their URLs come back in the finished job's `derivatives`.
- lab_stems_exportshallow
Hand the sound over to whoever mixes next (Resolve/Fairlight, Pro Tools, a dubbing studio): every stem of the sequence (dialog, music, sfx, atmo) as a 24-bit / 48 kHz stereo WAV, rendered the way it goes into the mix — effects, fader, pan and ducking baked in — plus an M&E file (music + effects + atmo WITHOUT the ducking on the dialog, for dubbed versions). All files start at the start of the sequence and are exactly the same length, so they line up at 00:00 in any DAW. Delivered as ONE zip with stems.json (format, length in samples, loudness/true peak per file) and LIESMICH.txt. The master (EQ/compressor/limiter) and the loudness normalisation are NOT in the stems: their sum is the mix before the master. Needs bound stems (lab_bind_audio). Runs as a BACKGROUND JOB: poll lab_get_job — stems_zip_url is in job.result. Changes nothing in the mix, costs nothing. Picture handover is lab_schnitt_export.
- lab_suggest_durationsshallow
Ask what clip durations the project's cutting preset WOULD give a sequence — and change nothing (`angewendet: false`). Use it to see the consequence before lab_apply_rhythm writes it, or to size a sequence that has no clips yet (pass `anzahl`). It knows nothing about the measured beat grid: the tempo it uses is the text from the preset's music brief ('mittel bis schnell, 100–128'), which is a promise, not a measurement. Only lab_apply_rhythm reaches for the grid that lab_beatgrid measured. Reads only — no state, no credits.
- lab_timeline_applyshallow
Write a WHOLE cut into a sequence in one call — clips in order with their lengths, an optional dissolve between them, an optional bed underneath. This is the counterpart to lab_get_sequence: that one reads the timeline, this one writes it. Prefer it over a chain of lab_add_clip calls whenever you already know the whole cut: a chain that breaks in the middle leaves half a sequence behind, this either applies or refuses. Costs nothing — it validates and writes rows, it generates nothing. Every video_id is checked against the project BEFORE anything is written, so a wrong id is a refusal here and not a gap in the cut nobody notices. Pass `sequence_id` to write into THAT sequence; omit it and a new one is created. Pass `sequence_id` WITHOUT a manifest to read back the stored cut as a manifest — for an agent that already has the sequence_id and wants to see what is in there before changing it. (The Resolve bridge does NOT go through here: it talks to the FilmLab server directly with its own bridge key and does not know this MCP.) Reworking a cut you read back? Keep each clip's `clip_id`. A clip that comes back with its identity keeps its track, its in-point in the source and its scene, and the shots bound to it stay bound; a clip without one is treated as new and gets a fresh identity, which orphans whatever pointed at the old one. Two honest limits: the Resolve bridge applies the clips but reports `uebergang` and the bed's level/fade as not applied (its scripting API has neither a transition call nor a clip volume property). The FilmLab sequence render applies the bed with its level and fade, but NOT `uebergang` yet — dissolves are stored and render as hard cuts (checked 2026-10-03).
- lab_ton_durchlaufshallow
Generate SOUND EFFECTS for a whole sequence, shot by shot — Simon Meyer's pass: every shot is muted, padded with black frames up to the model's minimum length, re-rendered by Seedance 2.5 in editing mode at its low resolution with sound on, and only the generated sound is kept, stretched back to the original timing (the black padding is the sync marker) and laid at the shot's position. The result is ONE sfx track in sequence length, bound to the sequence's sfx stem; the other stems stay as they are. Each piece and its offset are listed in the audio row's metadata (stuecke). Shots come from the sequence itself, in export order and export length — no cut detection. Costs credits, priced per shot over the seconds actually sent (the padding counts); call with get_cost first. ASYNCHRONOUS: returns a job_id; poll the job until done. A shot that fails is refunded on its own and named in fehlende_einstellungen; if the whole run fails, all of it is refunded. The model is told: keep the picture, diegetic sound only, no music, no dialogue, no voices — `hinweis` adds a setting line for every shot.
- lab_transformshallow
Relight and restyle an EXISTING clip while the performance stays untouched (Beeble Switch X): lighting, background and props change, the subject and its motion do not. The source is the clip of a generated-video row — or, with asset_id, an uploaded file that stands in for it. in_sec/out_sec cut the source server-side first, so a long take can be transformed in pieces. ASYNCHRONOUS: a new video row comes back as pending; poll it with lab_job_status. Costs credits when called without get_cost.
- lab_umzugshallow
Bring Midjourney exports into a project (FilmLab calls this 'Umzug'). Midjourney has no API, so the person downloads their images or ZIP and this tool carries them on. Give EXACTLY ONE of: `dateien` (names/types/sizes of local files → signed PUT addresses with a ready curl line; PUT the raw bytes, then call again with `quellen` from `weiter`), `quellen` (after the PUT: starts the import job → job_id; poll lab_get_job — result.bildzeilen lists image_id and datei per image (the prompt per image comes with `bilder: true`), result.gesperrt names refused images with the reason, result.ungeprueft images whose check was unreachable), `prompts` (pasted Midjourney prompts, one per line → parameters split and what does not carry over, e.g. --sref codes; free, no job), `anker` ({name, image_ids ≤ 12} → a look anchor for lab_generate's anker_id; images of real people are refused) or `bilder: true` (the project's imported images with image_id and prompt). Every imported image is declared AI material (EU AI Act Art. 50) — no herkunft question. An image_id works directly in lab_animate (source_image_id), as a seed in lab_generate and in lab_referenz_aus_bild. Uploading is free.
- lab_upscaleshallow
Enlarge an EXISTING clip (Topaz, passed through fal): same shot, same length, same sound — more pixels. There is no prompt here; nothing is re-imagined, the frames are scaled. The source is the clip of a generated-video row. Both the length and the source height are measured server-side before anything is charged, and a source too tall for the larger factor is refused rather than run. ASYNCHRONOUS: a new video row comes back as pending; poll it with lab_job_status. Costs credits when called without get_cost.
- lab_verkettungshallow
Render several clips as CHAINS: within a scene one after another (continuity), across scenes in parallel (speed) — the plan follows scene_ref of each job in order. aktion: plan (free: shows the chains) · preis (free: same checks as a real start; returns preis_geschaetzt_credits, preis_hoechstens_credits (with every allowed retry) and `reicht` against balance, project cap and an active auto run, plus startbilder_offen when a chain's first start image is not approved yet — nothing is created) · starten (COSTS CREDITS, ONLY after the person confirmed the price from aktion=preis). Each clip is charged when it starts; an active lab_auto_lauf cap applies. The FIRST clip of every chain needs an approved start image (keyframe checkpoint, as in lab_animate) unless ohne_keyframe; later clips derive from the chain. Sending starten twice returns the running chain (wiederverwendet: true) instead of paying twice. Transition between clips of a chain (uebergang): schnitt (default) = hard cut to a NEW camera angle — the next clip does NOT start from the last frame; its prompt begins with the previous clip's end state (wardrobe, props, place, light), characters and location come from each job's own character_refs/location_id. A schnitt follow-up clip is TEXT-TO-VIDEO: without character_refs/location_id the person and place hang on one sentence of text — give them for real continuity. CONTINUITY CHECK: in a chain with more than one clip every clip is checked against its prompt BEFORE the next one starts (status pruefen, wartet_auf: abgleich while the check runs — that is not a hung job). On mismatch the clip is re-rendered at most neuversuche times (default 1, prompt led by the failed claims, charged like the clip); if it still deviates the chain STOPS before the next clip is paid (chain status abgebrochen, clip status abweichung, issues and verworfen at the clip). The last clip of a chain gets its retry too but the chain then ends fertig with the verdict at the clip. Single clips are only checked in the background. durchgehend = the last frame becomes the start image — only for one unbroken take. Follow a started chain with lab_get_job(job_id): result.zusammenfassung (laeuft/fertig/abgebrochen), result.ketten (status and grund per chain) and result.clips (keyed by clip index: video_id, status, fehler_klasse). Job status done only means nothing runs any more — check result.zusammenfassung.abgebrochen before reporting success. A failure stops only its own chain. Dispatch rule: continuous scene → one chain with schnitt; one unbroken motion → a single clip ≤ 15 s, else durchgehend; separate scenes, time jumps, costume changes or montage → separate scenes (parallel). Over ~3 minutes total: suggest narrowing the scope first.
- lab_vfxshallow
Run a VFX operation on an image already in the project gallery — the same pipeline the Resolve bridge uses. inpaint (clean plate: what is inside the box disappears, the surroundings close over it) · replace (same path, other intent: something new goes into the box) · relight (no box — the light changes across the whole frame; by default the scene stays exactly as it is, licht_weg 'iclight' instead repaints the background and may change the scenery) · mask (no box — you describe what should be cut out and get the matte back). inpaint/replace need `box` AND `prompt`; relight needs `light_preset` or `prompt` and REJECTS a box; mask needs `prompt` and REJECTS a box too. `box` is given in FRACTIONS of the image (0..1), not pixels — the worker builds the mask. inpaint/replace start at 5 credits per run on the reference area (larger areas cost more); relight costs 4 flat per image (licht_weg 'iclight': from 9, by area); mask costs 1, flat per request. Returns immediately with an operation_id; poll lab_vfx_status until status is done|failed. NOT offered here: composite, move, color_grade — the server knows them and has no consumer for them.
- lab_vfx_presetshallow
Run a video VFX preset on a whole clip. Today only 'gesichter_verpixeln' (pixelate every face) is live. Costs credits per frame — call with dry_run=true first to see the price. With rerender_from (a finished job_id) it re-renders for free with other settings, e.g. exceptions: object ids that stay sharp. Tell the person: "Automatisch verpixelt, ohne Garantie — vor Veröffentlichung prüfen." Poll lab_vfx_preset_status until done|failed.
- lab_vfx_preset_statusshallow
Poll a video VFX preset job. status is queued|proxy|spur|render|done|failed; progress shows frames done. When done: result_url is the finished clip (give it to the person as karte_ansehen), kontakt_url is the review contact sheet, spur.objekte lists detected faces with ids usable as exceptions in lab_vfx_preset(rerender_from, ausnahmen).
- lab_vfx_statusshallow
Poll a VFX operation started with lab_vfx. status is pending|processing|done|failed; when done, result_url carries the finished image. Call repeatedly until done|failed — an image run usually takes under 30 seconds.
- lab_voice_cloneshallow
Clone a voice from real audio or video material into a project (fal.ai minimax voice-clone) — the source for lab_voice_tts and for lab_dub's voice_id+dub_text path. SYNCHRONOUS: the clone runs inside the request and can take a while to return; there is no job_id to poll. The source needs a clean speech track of workable length — too short or silent material is rejected before anything is spent. Voice cloning from real material is consent-sensitive: only clone voices you have the right to use, and the Fish Audio path requires you to say so explicitly.
- lab_voice_ttsshallow
Speak text in a project's cloned voice (via lab_voice_clone) — SYNCHRONOUS, returns a ready audio_url, no job_id. The voice house is whichever one cloned this voice; you do not pick it here. Consent-sensitive like the clone itself: only speak text you have the right to put in that voice's mouth.
- lab_wellenformshallow
Read the sound of a clip (video_id), an audio track (audio_id) or an uploaded file (project_id + asset_key from lab_add_media) as numbers: peak level 0..1 per channel, 16 values per second, up to 60 s per page. Use it to find where music or speech starts, where silence is (below `stille_unter`), and whether a cut lands on a beat or mid-word — before you move cut points. Continue with `weiter_von_s` for the next page. Read-only, free.
- lab_weltshallow
Build a walkable 3D WORLD (Gaussian splat, World Labs Marble) from ONE location picture (costs credits — exact price via get_cost: true). Source: a location board's time variant (loc_id + variante) OR a gallery image of the project (quell_bild_id). stufe 'entwurf' is a cheap draft (about a minute), 'voll' the full world (5-15 min). ASYNCHRONOUS: returns welt_id; poll lab_welt_status. When done, open the studio link, place a camera and save angles — they land in the project gallery and work as seed_image_url for lab_generate. The world only holds near the spot the picture was taken from: reverse shots from inside the room work, flying through walls does not.
- lab_welt_statusshallow
Status of a world from lab_welt: processing | completed | failed. When completed, `studio` is the link to walk it and save angles (free). A failed world has been refunded. Read-only, free. Pass wait_s (up to 15) to wait inside the call.
- lab_whoamishallow
Who is connected: the FilmLab account (email, user id, name, tier, credits) and how this connection signed in (oauth, oauth_geraet, bridge_key, legacy service user, or anonym). For a device sign-in it also lists the device limits (projects, credits, end date). Call it when results look like someone else's — two clients signed in with two accounts see different projects. Works without an account. Read-only, free.
- lab_widerrufshallow
Record a correction in the FilmOS knowledge layer when the user contradicts something you asserted from it. Use this the moment a contradiction is stated — not at the end of the session, and not instead of accepting the correction in your answer. It stores the claim AND what is actually true, owned by the user who said it, so lab_wissen surfaces it first next time. It does not delete anything: a deleted false claim returns with the next ingestion, a corrected one does not. Quote the user's own wording for `korrektur` where you can.
- lab_wissenshallow
Ask the FilmOS knowledge layer — measured craft knowledge from vetted sources, with the KNOWN CORRECTIONS first: documented false assumptions plus what is actually true. Call this before asserting a craft fact you did not measure yourself in this session. Every hit carries its source and its usage_policy; quote within that policy and name the source. An empty result means nothing matched — it never means the claim is true.
- lab_wortzeitenshallow
Every spoken word with its start and end time, for a clip (video_id), an audio track (audio_id) or an uploaded file (project_id + asset_key). Use it to cut pauses without cutting into a word, to time captions, or to land a graphic on an exact word — instead of guessing seconds from the waveform. Up to 20 min of sound per source; the first call transcribes (Fish Audio, about 0.36 USD per audio hour, booked to the operator, not your credits), every later call for the same sound is served from the cache for free. Returns at most 300 s of words per page; continue with `weiter_von_s`. Speech recognition spells names the way they sound — check names before you put them on screen.
- lab_zielgruppeshallow
Read or set a project's audience (zielgruppe) and target markets (zielmaerkte). With project_id only: read. Set zielgruppe 'kinder' or 'jugendliche' whenever the project is made for children, families or teenagers — do it BEFORE creating characters or generating. That switches on blocks for the whole project: the adult mode is off even for unlocked accounts, real people are refused (likeness photos, voice clones, lipsync with a consent id, digital doubles as characters), generation stops instead of running unchecked when the content check is down, and the export must mark the whole film as AI. Setting it fails with a readable conflict while a digital double sits in the cast — take it out first. An empty string clears the audience. zielmaerkte (ISO country codes of the researched European countries plus 'EU'; 'UK' is accepted for GB) blocks nothing: it adds a checklist per country of what the customer must observe when delivering there (age rating scale, national AI label, registration duties for creator channels, advertising rules, warnings). The list replaces the previous one; an empty list clears it. The answer always carries zielgruppe, zielmaerkte, zielgruppe_regeln (the active blocks as sentences) and zielmarkt_checkliste — pass the checklist on to the person, it is not legal advice.
Embed this server’s score
Tool count and median score across every tool in this server’s corpus — honest in a way a single cherry-picked tool’s badge wouldn’t be.
[](https://vouch.tools/servers/e2b19a86-37ee-4a05-ba59-24b79b139e4d)