# Face Generator > Photorealistic portraits of people who do not exist, steered by broad attributes. For > placeholder avatars, character references and mock-ups. Live at > https://face-generator.skillsafe.ai/ ## What it is Face Generator generates portrait photographs of entirely fictional people. Nothing it produces is a photograph of a real person, and it will not attempt one: requests for the likeness of a named individual, a public figure, or someone the user knows are refused in the browser before anything is sent or charged. Two lanes over one work object — a face, or a set of them. ### Lane 1: portrait (an image run) Fourteen attribute controls are compiled in the browser into one complete photographic brief, which is sent to an image model. The controls are: - **Who** — age range, presentation, heritage cue, hair, facial hair, eyewear, wardrobe, mood - **Camera** — framing, lens, lighting, background - **Treatment** — era, treatment (editorial, documentary, cinematic, 35mm film, medium format, black and white, plain ID photo, studio beauty, corporate headshot) Plus batch size (1–6), a variation seed, and free-text notes. Each face in a batch is its own metered run — a batch of six is six runs, sent two at a time. Every compiled brief opens with a fixed clause declaring the subject fictional. That clause is prepended by the compiler, not stored in an editable field, so it cannot be removed by the user or by a pasted note. The brief also carries a fixed negative-constraint clause forbidding text, watermarks, logos, borders and duplicated faces inside the frame. Within one batch, each face gets a different small distinguishing detail (an uneven hairline, a gap in the front teeth) drawn deterministically from the seed, so a batch of six is six people rather than six renders of one. ### Lane 2: cast (a text run) Describe a project — a film, a game, a landing page, a board game — and get a cast sheet of invented characters. Each character carries a name, a role, a one-line description, a casting note, a `look` paragraph, and a complete attribute set drawn from the same controlled vocabulary the portrait form uses. Every character has a "Shoot this face" button that loads them into the portrait lane. ## What it refuses - **Likenesses of real people.** A guard runs over every free-text field. It fires on likeness constructions ("looks like", "in the likeness of", "modelled after", "doppelganger of", "spitting image of") aimed at a proper name, a public-figure marker ("a celebrity", "the president", "my ex"), on standalone likeness-transfer terms ("deepfake", "face swap", "impersonate"), and on a real office or profession followed by a name ("President Lincoln", "singer Adele"). It also runs over the `look` line the cast lane writes — a model-authored description is not trusted more than a typed one. - **Sexualised imagery**, at any age, in any field. Naming a *fictional* character is not blocked and never should be: inventing a person and giving them a name is the app's normal case. The line the guard draws is likeness intent, not capitalisation. ## What it costs - The attribute vocabulary, the compiled brief, the brief lint, the likeness guard and both bundled examples are free and work signed out. - Rendering is a metered run on the user's own SkillSafe credits, priced **per image**. The app always quotes per-image cost multiplied by batch size — never a single-image figure standing in for a batch. - One renderer: GPT Image 2. It reserves about 2,652 credits (~$0.27) per image and has settled at about 96 credits (~$0.01) in practice — the hold is deliberately far above the real cost. `flux-klein` is advertised by the platform and quotes cleanly through `/estimate`, but every run against it on this deployment fails with an internal error, so this app does not offer it. - Cast sheets are a separate, token-priced run on the app's text model. ## Where the images go Generated faces are uploaded to the user's own app storage and displayed through short-lived signed URLs from the platform API host. They are not data URIs and not device-local blobs, so a shoot reopened from history on another device still shows its faces. Deleting a face deletes the stored file. If storage fails, the face is still shown from the session's bytes and the caption says so. ## Programmatic use `https://face-generator.skillsafe.ai/api.html` documents the API. Summary: - Base URL `https://api.skillsafe.ai/v1/app-api`, responses in a `{data}` / `{error}` envelope. - **Portrait (image) run** — POST `/run` with `{"instruction": "", "$model": "gpt-image"}`. The `$model` override is what routes the run to an image model; without it the run goes to the app's text model and returns prose. The finished job's payload is `output.images[0].b64` (base64) and `output.images[0].content_type`; `output.output` is empty for image runs. One run produces one image — a batch is N runs. - **Cast run** — POST `/run-stream` (or `/run`) with `{"task": "cast", "project": "...", "count": 5, "tone": "documentary", "cast_instructions": ""}`. Returns one JSON object; the schema is in the instruction set. - `/estimate` is free and returns the hold for **one** image on an image model, regardless of brief length. Multiply by the batch size yourself. ## Honest limitations - The renderer chooses everything the attributes do not pin down, and its choices are not evenly distributed. Set presentation and heritage explicitly if a batch needs a particular mix. - Hands, jewellery and text-bearing objects are the usual failure points. - A face is not reproducible from the seed alone: the seed fixes the brief, not the model's sampling. Two runs of an identical brief give two different people. - Per-user file storage is capped by the platform. Deleting faces you no longer need is the intended maintenance, and the app provides a per-face delete. ## Provenance Original implementation. Built on the SkillSafe apps platform: static bundle under a strict CSP, declared `shoots` collection for history, `ss.files` for image storage, and an image model reached through a `$model` override.