Speaker Selection — API
Speaker selection helps you target the right face when a clip or image contains multiple people. You can either let Sync Labs auto-detect the active speaker (video only) or provide a user-selected point from your UI and forward it via the active_speaker_detection DTO on /v2/generate. For using speaker selection in the web app, see the guide.
When to use what
- Auto-detect (video only): fastest setup; best for single/obvious speaker clips. Set
auto_detect: trueand skip manual fields. - Manual selection (video or image): best for multiple people or when you want deterministic control. Provide a reference frame and a point on the speaker’s face, or supply bounding boxes if you already have detections for that frame.
Image inputs (sync-3 only) support manual speaker selection but not auto-detect. The backend rejects auto_detect: true for images.
Workflow: selecting a speaker in video
Capture a reference frame
Seek the video to a frame where the target speaker’s face is visible. Keep track of the frame index you show in the UI.
Collect a point on the face
Record the [x, y] coordinates (in the same coordinate system/pixels as your extracted frame) for the clicked point on the speaker’s face. Keep the frame index and coordinates paired.
Optional: provide bounding boxes instead
If you already ran face detection over the video, send bounding_boxes as a per-frame array. Each entry is four integers, [x1, y1, x2, y2] (top-left to bottom-right), or null or [] when no face is present. This replaces the need for frame_number + coordinates.
For long videos with many frames, use bounding_boxes_url instead to point to an external JSON file — this avoids large request payloads.
Match transcript speakers to faces
For a completed video transcription, speaker analysis can identify a face for each transcript speaker. It supports video up to 2 minutes long and up to 8 speakers.
- Read
GET /v2/transcriptions/{id}/speaker-analysis. Analysis may already be available. If it has not run, callPOSTon the same path with the transcription’srevisionandsourceVideoUrl. To retry anunavailableresult, also sendretry: true. Poll theGETendpoint while the status isprocessing. - Choose a speaker whose status is
matched. CallPOST /v2/transcriptions/{id}/speaker-analysis/face-track-sliceswithrevision,speakerId,startFrame,endFrame, andfps. These frame bounds refer to the full source video; the end frame is excluded. - Pass the returned
urlas the segment’soptionsOverride.active_speaker_detection.bounding_boxes_url. The file contains one bounding box per segment frame. Ifurlis null, the face is absent from that segment; use another selection method or leave it unlipsynced.
For example, a segment from 5 to 10 seconds at 30 fps uses startFrame: 150 and endFrame: 300 in the slice request. Manual frame_number in that segment’s optionsOverride still starts at 0.
An uncertain speaker has no reliable face match. Use the returned reason and ask the user to select a face, or use auto-detect. If the API returns 409 because the revision changed, fetch the current transcription and analysis before retrying. Analysis allows 3 requests per minute; face-track slicing allows 60.
Workflow: selecting a speaker in images (sync-3)
When your image contains multiple faces, you can specify which one to lipsync by providing manual coordinates.
Run face detection on the image
Detect faces in your input image and display bounding boxes in your UI. Use the image’s native pixel dimensions as the coordinate space.
ActiveSpeaker DTO fields
See the full API reference for active_speaker_detection.
auto_detect(boolean): let Sync Labs pick the active speaker automatically. Defaults tofalsewithin an explicitactive_speaker_detectionobject. If the whole object is omitted on a supported video dubbing request, Sync enables auto-detection. Set it tofalseto disable automatic selection. Manual face selections, speaker mappings, and dialogue edits keep their own settings.v3(boolean, optional): enable ASD v3.frame_number(number): zero-based frame index that corresponds to the provided coordinates. At the top level, count from the start of the input video. In a segment’soptionsOverride, count from the start of that segment. For a segment starting at 5 seconds in a 30 fps video, source frame 150 is segment frame 0.coordinates([x, y]): reference point on the speaker’s face inframe_number.bounding_boxes(([x1, y1, x2, y2] | [] | null)[], optional): per-frame array of bounding boxes across the video. Each entry corresponds to that frame. Set it to exactly four integers,[x1, y1, x2, y2](x1,y1= top-left;x2,y2= bottom-right), for the detected face. Usenullor[]for a frame with no face. Any other entry, such as two or five coordinates or a fractional value, fails the request with a 400 validation error. No generation is created. The same rule applies tobounding_boxesin a segment’soptionsOverride. Use this instead offrame_number+coordinateswhen you already run detection over the clip.bounding_boxes_url(string, optional): URL pointing to a JSON file containing the bounding boxes. Use this instead of inlinebounding_boxesto avoid large request payloads. The JSON file must contain abounding_boxesarray with one entry per frame, matching the format above.
Request examples
TypeScript SDK
cURL (HTTP)
TypeScript SDK (bounding boxes instead of coordinates)
Image input with speaker selection (sync-3)
Using bounding_boxes_url (for large payloads)
For long videos, host the bounding boxes in an external JSON file to keep request payloads small. The JSON must follow this format:
Each array entry corresponds to one frame: [x1, y1, x2, y2] for a detected face, or null when no face is present. The number of entries must match the total frame count.

