Skip to main content
Trinity-2 is our newest avatar generation. A Trinity-2 avatar is built waist-up, torso and both hands included, from a single photo. Its sessions can also do things the older generations can’t:
  • Pick the video’s size and shape. Square, landscape or portrait, at any size from 512 pixels up.
  • Place the avatar on the canvas. Put it anywhere on the frame instead of in the bottom centre.
  • Set a starting camera, then move it live. Zoom, pan, tilt, roll and orbit around the avatar, as a cut or as a smooth glide.
  • Play an intro animation when a Simli Auto session opens.
Everything else works as before: the same session token, the same WebSockets and the same audio format (PCM16, 16 kHz, mono). Trinity-1 and legacy faces ignore every setting on this page and keep their own frame size (512x512 for Trinity-1).

Making a Trinity-2 face

Trinity-2 faces are made with the same endpoints as Trinity-1 faces. Pass gsVersion=GSA_2.0 to both calls; leaving it out makes a Trinity-1 face.
1

Reframe the photo

Send the photo to POST /faces/trinity/preprocess. For Trinity-2 it is reframed to show the person waist-up, with the torso and both hands, on the photo’s own background.The photo must be a JPEG, PNG or WEBP under 5MB and at least 512x512. It needs a person facing the camera, and their head must be at least 15% of the image height. If there are several people, the largest camera-facing head is used.
The response body is the reframed PNG. Keep its TARGET-RATIO header for the next step. Trinity-2 always returns 0 here; pass it back anyway. The warnings header is a JSON array of advice; the image can still be used when it isn’t empty.Not happy with the result? Run it again with retry=true to render at higher quality. That takes about 160 seconds instead of 25.
2

Start the generation

Post the reframed image to POST /faces/trinity, with the TARGET-RATIO value in the target-ratio header. Use the same gsVersion as the preprocess call, because the two generations frame the image differently.
You can skip the preprocess step and post a photo without a target-ratio header. The image is then framed here first, which adds about 25 seconds.
3

Wait for it to finish

Poll GET /faces/trinity/generation_status with the face_id until status is completed (or failed). The states are pending, processing, completed, failed and not_found.
Without face_id, generations lists every generation of yours that is still tracked, oldest first. The top-level fields only describe the most recent one, so if you run several generations at once, read generations. Completed and failed generations stay in the list for 24 hours.

Trinity-2 generations and spacing

  • They use Trinity-2 generations, not face slots. Trinity-1 faces take one of your plan’s face slots. Trinity-2 faces use your Trinity-2 generations instead: one is used when the face is built, and a failed build uses none. A generation that is still queued or building holds one until it finishes. When you have none left, both calls return 403.
  • Generations start at least 10 minutes apart. Each account’s Trinity-2 generations start at least 10 minutes apart. A request sent sooner is still accepted straight away, but it waits in the queue. While it waits, dispatch_after gives the Unix time (in seconds) when it can start. The field is left out when the generation isn’t held.

Framing the video

Four fields set the video’s size and where the avatar sits in it. They are accepted by: Width and height together must make a 1:1, 16:9 or 9:16 frame. They only need to be within a pixel of the exact ratio, so 1366x768 counts as 16:9. Any other shape, a side under 512 or a position outside 0 to 1 gets a 422, even for faces that ignore framing. A canvas larger than the avatar’s frame is filled out with the avatar’s background, and a smaller one crops a window out of it.
POST /compose/token
Simli Auto agents don’t store framing. To frame an agent’s session, put the framing fields in its POST /auto/token request. The session uses the framing from its token.

The camera

The camera field in the requests above sets the camera a session or video starts with. Each value is an offset from the avatar’s own framing. Every field is optional, and a field you leave out has no effect (0, or 1 for zoom). If you leave camera out entirely, the avatar keeps its own framing. Values outside their supported range are not clamped. They are applied as sent, and the response’s warnings array gets an entry for each one, for example camera zoom 6.0 is outside its supported range (0.0, 4.0]; applied as is. The token or video is still made. Only NaN and infinity are rejected, with a 422.

Moving the camera during a session

Both session WebSockets, /compose/webrtc/p2p and /compose/webrtc/livekit, accept a binary CAM_ message. It is the ASCII prefix CAM_ followed by little-endian float32 values, in this order. Note that y comes before x:
  • Values: send the first 4, the first 7 or all 9 values. Any you leave off have no effect.
  • Replacement: each message replaces the whole camera, including the starting camera from the token. Values are offsets from the avatar’s own framing, not from the previous message. Sending 0, 0, 0, 1, 0, 0, 0, 0, 0 goes back to the avatar’s own framing.
  • Gliding: the camera cuts to the new setting. To glide instead, add the ASCII tag LERP and one more float32: the number of seconds the move takes. The glide starts from wherever the camera is now, even partway through an earlier glide. A value of 0 or less is a cut.
  • Size: a message is 20, 32 or 40 bytes long, or 28, 40 or 48 bytes with LERP.
The server answers some camera messages with a text message. None of these replies end the session:

Intro animation (Simli Auto)

POST /auto/start/configurable takes an introAnimation. The avatar plays it when the user joins, together with firstMessage if there is one. It’s off by default, and faces other than Trinity-2 ignore it.