Vidu S Digital Human
Full request body example:
If avatar.id is not provided and only image_uri is submitted, the service will automatically call the "image upload" interface, and return that asset's avatar.id in the response's live.avatar.id.
When enabled, the text content of the user's input audio / the digital human's output audio is returned via WebSocket.
Used to control interrupt-related parameters, to better capture the content of a user's turn.
Used to control the output details of the language model, to accommodate different user needs.
Used to control the time before automatic disconnection when there is no input, to avoid a session hanging indefinitely with no call activity.
AuthorizationstringReplace {your api key} with your token
live_idstringPath parameter, must be greater than 0, and must belong to the account corresponding to the current API Key.
The App WebSocket is used to initialize the session, send text, interrupt, and hang up. It does not transmit audio or video media.
live_idstringRequired, the live.id returned when creating the live session.
conn_idstringOptional, client connection ID; if not provided, the server will generate one.
type | Name | Direction | Description |
|---|---|---|---|
`1` | `conn_init` | App → live | Connection initialization; must be sent after the WS is opened. |
`2` |
Query custom voices: GET /live/v1/voices → { "voices": [{ "voice": "my_custom_voice" }] }
Delete a custom voice: DELETE /live/v1/voices/{"my_custom_voice"}
With this interface you can first upload a local image to Vidu, to use as the digital human image when creating a session. Passing the image in this way as the digital human's image can greatly reduce the time needed to create the digital human. Note: images will be automatically deleted after 90 days.
Supports URL and base64 formats, only 1 image [of a single person] is supported, full-body / half-body, any style. Format: PNG / JPG / JPEG / WEBP; image size ≤ 50MB; base64-decoded byte length < 20M, and must include a content type prefix, e.g. data:image/png;base64,{base64_encode}
Method | HTTP request | Description |
|---|---|---|
Path parameter avatar_id (string): the digital human persona asset ID. See "Data structure - Asset object" for the returned object fields.
AuthorizationstringReplace {your api key} with your token
idstring*Deletes a digital human persona asset; content that already references this asset is unaffected. Path parameter avatar_id (string): the digital human persona asset ID.
A successful deletion returns an empty object (HTTP 200).
GET /live/v1/avatars, pagination parameters are passed via the query string.
pager.pageintegerPage number, starting from 0, default 0
pager.pageszintegerNumber of items per page, default 10, maximum 100
Returns: total (integer, total count), items (array, elements are asset objects, see "Data structure - Asset object" for structure).
search_user_memory)The HTTP JSON protocol that a business-side external memory API must follow.
memory_retrieval and knowledge_retrieval are both optional fields, corresponding respectively to the digital human's ability to call external memory retrieval and external knowledge retrieval during a conversation. See the [External Memory API] and [External Knowledge API] sections for the protocol details.
AuthorizationstringReplace {your api key} with your token
call_modestring*Interaction method, enum values:audio: audio onlyvideo: audio and video
avatar.personastring*The digital human's persona, up to 50,000 characters. See the "Recommended persona templates" section for details
avatar.image_uristring*Choose either avatar.image_uri or avatar.id
The digital human's appearance image URL, supports image URL and base64. Supports only 1 image [of a single person], full-body / half-body, any style. Format: PNG / JPG / JPEG / WEBP; image size ≤ 50MB; base64-decoded byte length < 20M, and must include a content type prefix, e.g.
`conn_init_ack` |
live → App |
Initialization result. `success=true` indicates the real-time control link is ready. |
`5` | `call_hangup` | App → live | App proactively hangs up. |
`6` | `force_hangup` | live → App | Server forces a hangup, e.g. timeout, risk control, insufficient credits, or service-side closure. |
`7` | `audio_interrupted` | App → live | User interrupts the current AI output. |
`99` | `text_msg` | App → live | Sends a text message. |
When conn_init_ack.success=false, the meaning of error_code and handling recommendations are described consistently in the error response section. This section only retains the request, success response, and failure response examples.
Field | Description |
|---|---|
`msg_id` | Client-generated message ID, for correlating client-side logs. |
`content` | Text content sent to the digital human. |
`timestamp` | Client send time, millisecond timestamp. |
The server currently does not return a separate business ack for text_msg; the digital human's reply is output via RTC audio/video, and some text responses may also be delivered via WS.
Used for a user to interrupt the current AI output. There is currently no separate ack; the client can handle this based on subsequent audio stopping, changes in the digital human's response, or its own UI state.
hangup_reason | Common scenario |
|---|---|
`user_end` | User proactively ended the call. |
`timeout` | Session reached the maximum duration. |
`audit_violation` | Triggered a content safety or risk control policy. |
`credit_insufficient` | Insufficient credits. |
`sip_closed` / `provider_closed` | Closed on the service side or the digital human rendering side. |
`sip_reconnect_timeout` / `client_reconnect_timeout` | Disconnection exceeded the reconnection grace period. |
`external` | Closed by backend or external control. |
In addition to listening for type=6, the client must also listen for WebSocket close / error events as a fallback. After proactively hanging up, it is recommended to first close the WebSocket, then call the RTC SDK's leaveChannel().
Used to dynamically update some session configuration while a session is in progress (after conn_init_ack success=true), without needing to hang up and rebuild the session.
avatar, vad, llm retain their original values;knowledge_retrieval / memory_retrieval are replaced as a whole group — passing them in overwrites the entire group's configuration, and sub-fields within the group not passed use default values.Updatable fields and constraints (follows the types and ranges used when creating a session; knowledge_retrieval / memory_retrieval groups are replaced as a whole, other fields only need to pass the parts that need updating):
Field | Type | Value / Constraint | When it takes effect | Handling of invalid values |
|---|---|---|---|---|
`avatar.voice` | String | Existing voice or cloned voice ID | Takes effect after the current playback ends (immediately if not playing) | Voice does not exist → update fails |
`avatar.persona` | String | ≤ 50,000 characters | Takes effect after the current playback ends (immediately if not playing) | Too long → update fails |
`vad.type` | String | server / semantic | Next turn | Not an enum value → rejected |
`vad.threshold` | float | \[0, 1.0\], only effective when type=server | Next turn | Out of range → rejected |
`vad.silence_duration_ms` | int | \[200, 6000\] ms, only effective when type=server | Next turn | Out of range → rejected |
`knowledge_retrieval.enabled` | bool | true / false |
The update result is returned via session_update_ack:
Field | Description |
|---|---|
`success` | Whether this update was accepted as a whole; when false, none of the fields take effect and the original configuration is retained |
`error_code / error_msg` | Failure error code and reason (returned on failure, empty on success) |
Why AliRTC appears here: the Live backend is responsible for session creation, authentication, control signaling, and digital human orchestration, but it does not directly forward microphone, camera, or digital human audio/video to the App via WebSocket. Real-time media streams require low-latency transmission, device capture, codec handling, packet loss recovery, and subscription callbacks, so they are carried by the AliRTC SDK.
During integration, two links must be established simultaneously: the App WebSocket handles control, and AliRTC handles media. The two links are parallel and both are required.
Link | What it carries | Typical actions |
|---|---|---|
App WebSocket | Control signaling | `conn_init` to start, `text_msg` for text interaction, `audio_interrupted` to interrupt, `call_hangup` to hang up. |
AliRTC | Real-time media stream | Publishes the App's microphone audio; in `video` mode, publishes camera video; subscribes to the digital human's audio and video. |
rtc object returned by the create-live interface is the source of join credentials; the client does not need to generate the token itself.rtc.token: the authentication information passed to joinChannel.rtc.user_id: the current App user's identity in the RTC room, used as the second parameter of joinChannel.rtc.channel_id: the RTC room identifier created by the server, mainly used for logging, subscription callbacks, and troubleshooting; the client usually does not need to construct it itself.Concept | Description |
|---|---|
`channel` | The RTC room corresponding to one live session. Only users who join the same channel can send and receive media streams with each other. |
`publish` | Pushes the local microphone or camera to the RTC room, so the server and digital human link can hear or see the user. |
`subscribe` | Pulls a remote user's audio or video from the RTC room. In this scenario, the remote users are mainly the digital human audio stream and digital human video stream. |
The client uses the rtc.token and rtc.user_id returned by create-live to join the channel, then publishes the local microphone; in video mode, it also needs to publish the camera.
Mode | channel_id | App-side responsibilities |
|---|---|---|
`audio` | `live-audio-{live_id}` | Publish microphone audio, subscribe to the digital human's audio. |
`video` | `live-user-{live_id}` | Publish microphone and camera, subscribe to the digital human's video stream. |
With default subscription enabled, remote audio is usually automatically subscribed to and played by the SDK; actual playback may still be affected by browser autoplay policies. Remote video needs a <video autoplay playsinline> container prepared, and the remote view should be bound once the subscription state becomes subscribed.
If you cannot see the remote video, first confirm that RTC joined has already appeared in the logs, then confirm whether the digital human's publishing user is online, and whether videoSubscribeStateChanged or screenShareSubscribeStateChanged has entered the subscribed state. If the browser blocks autoplay, guide the user to click play or resume playback after a user gesture.
Role | User ID format |
|---|---|
User | `live-user-{creatorID}-{liveID}` |
Digital human audio | `live-bot-{creatorID}-{liveID}` |
Digital human video stream | `live-video-push-{creatorID}-{liveID}` |
The client generally joins directly using the rtc information returned by the create interface, without needing to construct the token or channel itself. The ID rules above are mainly used for logging, subscription callbacks, and troubleshooting.
AuthorizationstringReplace {your api key} with your token
pager.pageintegerPage number, starting from 0; if not provided, the default value is used.
pager.pageszintegerNumber of items per page. Defaults to 10 if ≤ 0; truncated to 100 if > 100.
pager.page_tokenstringReserved field; page / pagesz are primarily used currently.
Create |
POST /live/v1/avatars |
Create a digital human persona asset |
Get | GET /live/v1/avatars/{id} | Query a single digital human persona asset |
Delete | DELETE /live/v1/avatars/{id} | Delete a digital human persona asset |
List | GET /live/v1/avatars | Paginated list query |
POST /live/v1/avatars, request body is JSON.
Repeatedly submitting the same image will create a new asset record and directly reuse the already-generated description (the new record's status will be success); on first creation, the service will asynchronously generate a description for the image, and processing progress and result are reflected in the returned asset's status field.
Request parameters:
image_uristringPersona appearance image, supports a public http(s) URL or data URI
namestringOptional display name; empty if not provided
Request example
Response fields
idstringDigital human persona asset ID (can be passed in as avatar.id)
image_uristringAccess URL for the persona image
namestringDisplay name
statusstringDescription generation status, see the "status enum" below for values
created_atstringCreation time
updated_atstatus enum
Value | Meaning |
|---|---|
created (1) | Created, waiting to generate description |
processing (6) | Generating description |
success (11) | Generation succeeded |
failed (12) | Generation failed (terminal state, needs to be re-created) |
AuthorizationstringReplace {your api key} with your token
audio_urlstring*Reference audio, supports a public URL or data URI, length 1 to 2048. Supported formats: WAV (16bit), MP3, M4A; recommended audio duration 10~20 seconds, maximum 60 seconds; file size < 10MB.
voicestring*Voice name, length 1 to 64; entered as avatar.voice when creating a live session. Only digits, upper/lowercase letters, and underscores allowed. (Note: the voice name must not be duplicated)
textstringReference audio text, to help the server validate consistency between the audio and text, maximum 4096 characters.
languagestringReference audio language, e.g. , , maximum 16 characters. Supports (Chinese), (English), (German), (Italian), (Portuguese), (Spanish), (Japanese), (Korean), (French), (Russian), (Thai), (Indonesian), (Arabic), (Czech), (Danish), (Dutch), (Finnish), (Hebrew), (Hindi), (Icelandic), (Malay), (Norwegian), (Persian), (Polish), (Swedish), (Tagalog), (Turkish), (Urdu), (Vietnamese).Chinese dialects: Northeastern (), Shaanxi (), Sichuan (), Henan (), Changsha (), Tianjin (), Hangzhou (), Liaoning (), Shenyang (), Anshan ()
endpoint and authorization come from the memory_retrieval configuration in the CreateLive request.user_id, character_id, database filter conditions, embedding vectors, or sensitive information toggles.live_idstring*The current live ID, usable for logging, debugging, or mapping to server-side context
querystring*The model-generated natural-language retrieval intent; should not just be a mechanical copy of the user's original words
reasonstring*An explanation from the model of why the current reply needs memory retrieval, useful for logging, debugging, and risk control
memory_typesstringThe memory types to retrieve
time_hintstringA time-range hint, e.g. "recently," "last time," "long-term preference"
memory_types enum
Type | Meaning |
|---|---|
`preference` | User preferences, e.g. diet, language, tools, response style |
`profile` | Basic user information, e.g. occupation, location, role |
`history` | Past conversation facts, historical choices |
`project` | Projects or long-term tasks the user is currently working on |
`constraint` | Explicit user restrictions, e.g. don't use Python, limited budget |
`relationship` | Interpersonal relationships, team members, contacts |
`style` | The user's preferred output style, tone, format |
`other` | Other uncertain types |
The external API should return JSON. It is recommended to return only the memories array; has_more does not need to be returned.
memories[].summary: the core content shown to the model, recommended to be a short natural-language sentence, not a large amount of raw chat history.memories[].type: memory type, recommended to be consistent with the memory_types enum in the request.memories[].confidence: confidence level, recommended range 0..1. High confidence can be used naturally; medium confidence should be used with caution; low confidence should be confirmed with the user rather than treated directly as fact.memories[].updated_at: update time, RFC3339 recommended. When old and new memories conflict, prefer the newer memory, but still consider the current user input.memories[].source: memory source, e.g. , .When the external API returns a non-2xx status, the system normalizes the tool result into an error output submitted to the model. The system limits the response body size; an overly large response will be treated as response_too_large. It is still recommended to return structured JSON:
The live service has a built-in unauthenticated fake provider, used for local integration testing, demos, and built-in persona memory retrieval. It is not a production user long-term memory service, and does not write to or persist real user memory.
This interface does not require Authorization. If aggregated through a gateway, the path may be:
The fake provider does not validate live_id — even if not provided, it will always return the built-in memory for character 01. It always reads the live.builtin_avatars["01"].memories from the live service configuration, and does not switch characters based on live_id or character_id. Internal rules: read built-in memory → filter by memory_types → simple match-ranking by query/time_hint against summary/keywords → truncate by max_results.
Creation validation still requires authorization to be non-empty; the fake provider ignores this header.
The current fake persona memory demo always returns perceivable memories for the built-in character character_id="01". It is recommended to also use character 01 when creating a live session, so that the appearance matches the persona memory returned by the fake API. Recommended approach: first call the fake memory API directly to let the user see what "memories" were returned, then ask the digital human the same or a related question in conversation, so the user clearly perceives that the digital human used the data returned by the API.
Recommended demo questions quick reference:
Query to call the API first | Question to then ask the digital human | Obvious memory point expected in the reply |
|---|---|---|
`What does the user like Lingfei to call them` | `Do you remember what nickname I like you to call me?` | `Ah Che` |
`The password the user and Lingfei previously agreed on` | `What was the password we agreed on before?` | `The moon has awakened` |
`What format does the user like Lingfei to give suggestions in` | `Give me a bedtime relaxation suggestion for tonight, in the way I like.` | State the conclusion first, then add two or three supporting reasons |
Example (nickname memory), first call the API:
API returns:
The user then asks the digital human "Do you remember what nickname I like you to call me?", and the expected reply naturally includes Ah Che.
When facing the end user, the character should naturally express "I remember..." and should not say "I called an API / tool / fake provider."
search_knowledge)The HTTP JSON protocol that a business-side external knowledge API must follow.
endpoint and authorization come from the knowledge_retrieval configuration in the CreateLive request.user_id, creator_id, character_id, collection_ids, document_ids, database filter conditions, embedding vectors, permission toggles, or sensitive information toggles.live_idstring*The current live ID, usable for logging, debugging, or mapping to server-side context
querystring*The model-generated natural-language retrieval intent; should not just be a mechanical copy of the user's original words
reasonstring*An explanation from the model of why the current reply needs knowledge retrieval, useful for logging, debugging, and risk control
knowledge_typesstringThe knowledge types to retrieve
time_hintstringA time or version hint, e.g. "latest," "2026 version," "recently updated"
knowledge_types enum
Type | Meaning |
|---|---|
`faq` | Frequently asked questions, standard Q&A |
`document` | Product documentation, explanatory documents, long document excerpts |
`policy` | Policies, rules, restrictions, compliance descriptions |
`product` | Product capabilities, parameters, feature descriptions |
`procedure` | Operational processes, integration steps, usage guides |
`troubleshooting` | Troubleshooting guides, error code descriptions, issue diagnosis steps |
`other` | Other uncertain types |
The external API should return JSON. It is recommended to return only the knowledge array.
knowledge[].content: the core content shown to the model, recommended to be a short natural-language sentence or short paragraph, not a large amount of raw document content.knowledge[].title / source / url: helps the model judge the source and, when necessary, cite the basis; url is optional.knowledge[].type: knowledge type, recommended to be consistent with the knowledge_types enum in the request.knowledge[].confidence: confidence level, recommended range 0..1. High confidence can be used naturally; medium confidence should be used with caution; low confidence should be confirmed with the user or stated as not having found clear information.knowledge[].updated_at: update time, RFC3339 recommended. When old and new material conflict, prefer the newer material, but still consider the current user input.When the external API returns a non-2xx status, the system normalizes the tool result into an error output submitted to the model. The system limits the response body size; an overly large response will be treated as response_too_large. It is still recommended to return structured JSON:
The live service has a built-in unauthenticated fake provider, used for local integration testing, demos, and external user testing. It is not a production knowledge base service, and does not write to or persist real knowledge content.
This interface does not require Authorization. If aggregated through a gateway, the path may be:
The fake provider does not validate live_id — even if not provided, it will still return built-in demo knowledge. It always reads the built-in demo knowledge from the live service, and does not switch knowledge bases based on live_id or character_id. Internal rules: read built-in candidates → filter by knowledge_types → simple match-ranking by query/time_hint against title/content/keywords → truncate by max_results.
Creation validation still requires authorization to be non-empty; the fake provider ignores this header.
Recommended approach: first call the fake knowledge API directly to let the user see what material the interface returned, then ask the digital human the same or a related question in conversation, so the user clearly perceives that the digital human used the data returned by the API.
First call the API:
API returns:
The user then asks the digital human "How do I claim the firefly badge? What's the password?", and the expected reply naturally uses the booth location B3-17 and the password Blue Whale Seven.
AuthorizationstringReplace {your api key} with your token
idstring*data:image/png;base64,{base64_encode}avatar.idstring*Choose either avatar.image_uri or avatar.id
See the image upload section for details
avatar.voicestringVoice; uses the default if not specified. Vidu supports voice cloning, see the [Voice Cloning Interface]. Default: Tina
avatar.greeting_instructionstringOpening greeting prompt, ≤ 200 characters, default greeting prompt: "The livestream has just started. Please proactively give the audience a short, warm, natural opening line in Chinese that fits the persona. Speak it directly, don't use narration."
avatar.farewell_enabledbooleanWhether to automatically generate a polite farewell video. Defaults to false; if set to true, a few seconds of farewell video will play at the end, which the user can retrieve via a continued RTC pull stream
avatar.persona_enhancebooleanWhether to optimize the persona; defaults to false. If true, the prompt will be expanded and optimized
avatar.idle_actionbooleanWhether the digital human automatically performs natural movements while not speaking; defaults to false
idle_timeout_secondsintegerTime before automatic disconnection when there is no input. Default 7200s, range 10 ~ 7200s
7200*.enabledboolean*Whether to enable this capability
*.endpointstringThe retrieval API address. Must be an http(s) absolute URL accessible from the live server
Required:Required when enabled
*.authorizationstringForwarded as the Authorization header to the external API, and validated to be non-empty
Required:Required when enabled
*.timeout_msintegerRequest timeout, maximum 30000 (ms)
audio.enable_transcriptionbooleanWhen true, the results of the user's speech-to-text / the digital human's output audio-to-text are returned via WebSocket. Adds signal_type events: type=9 (input audio transcription), type=10 (output audio transcription)
falsevad.typestringEnum values:server: filters filler words / background noisesemantic: interrupts the current response as soon as the user starts speaking
servervad.thresholdnumberStrength of filtering for onomatopoeia / noise, range [0, 1.0], lower means less filtering. Only effective when vad.type=server
0.5vad.silence_duration_msintegerHow long to wait after speech ends before triggering a response, range [200, 6000], in ms. Only effective when vad.type=server
400vad.idle_timeout_msintegerHow long the model waits before proactively initiating a conversation after silence timeout, 0 or [500, 30000], in ms. 0 means do not proactively initiate a conversation
0llm.temperaturenumberCreativity, range [0.0, 2.0)
0.7llm.top_pnumberQuality lower bound, range (0.0, 1.0]
0.8llm.top_kintegerRange [0, 100]
20llm.frequency_penaltynumberPrevents repetition/stumbling, range > 0.
Default 1.0: no penalty;
< 1: encourages repetition;
> 1: penalizes repetition, the larger the value the less repetition
1.0llm.presence_penaltynumberTopic breadth, range [0, 2]
0.3llm.seedintegerRange 0 ~ 2³¹−1. Default -1: random seed
\-1llm.max_tokensintegerMaximum output length of the model, range 1 ~ 64K
50— |
`knowledge_retrieval.endpoint` | String | Accessible http(s) absolute URL, required when enabled | Next turn | Invalid URL / missing while enabled → rejected |
`knowledge_retrieval.authorization` | String | Non-empty, forwarded as the external API's Authorization | Next turn | Empty while enabled → rejected |
`knowledge_retrieval.timeout_ms` | int | ≤ 30000 ms | Next turn | Out of range → rejected |
`memory_retrieval.enabled` | bool | true / false | Next turn | — |
`memory_retrieval.endpoint` | String | Accessible http(s) absolute URL, required when enabled | Next turn | Invalid URL / missing while enabled → rejected |
`memory_retrieval.authorization` | String | Non-empty | Next turn | Empty while enabled → rejected |
`memory_retrieval.timeout_ms` | int | ≤ 30000 ms | Next turn | Out of range → rejected |
`llm.seed` | int | \-1 (random) or 0 \~ 2³¹−1 | Next turn | Out of range → rejected |
`llm.max_tokens` | int | 1 \~ 64K | Next turn | Out of range → rejected |
`llm.frequency_penalty` | float | > 0 | Next turn | ≤ 0 → rejected |
`llm.presence_penalty` | float | \[0, 2\] | Next turn | Out of range → rejected |
`llm.top_k` | int | \[0, 100\] | Next turn | Out of range → rejected |
`llm.top_p` | float | (0.0, 1.0\] | Next turn | Out of range → rejected |
`llm.temperature` | float | \[0.0, 2.0) | Next turn | Out of range → rejected |
rtc.token_expire_at: the token expiration time, Unix seconds; a new live session should be created after it expires.Update time
zhenzhendeitptesjakofrruthidarcsdanlfihehiismsnofaplsvtltrurviDongbeiShannxiSichuanHenanChangshaTianjinHangzhouLiaoningShenyangAnshanmax_resultsintegerMaximum number of results to return. The live side limits this to 1..10; it is recommended that the external API also enforce a limit
long_term_memoryexplicit_user_statement"memories": [], do not return plain text (e.g. "nothing found").max_resultsintegerMaximum number of results to return. The live side limits this to 1..10; it is recommended that the external API also enforce a limit
"knowledge": [], do not return plain text (e.g. "nothing found").{
"call_mode": "video",
"character_id": "1",
"avatar": {
"persona": "You are Sweet Tina. My voice is like warm milk tea — sweet and warm, but I'm never sloppy when it comes to solving problems!",
"image_uri": "https://scene.cf.vidu.studio/media-asset/070302-ZFkgvJxBTM0ZQJoO.png",
"voice": "Tina"
},
"audio": {
"enable_transcription": true
},
"vad": {
"type": "semantic",
"threshold": 0.5,
"silence_duration_ms": 200,
"idle_timeout_ms": 500
},
"llm": {
"temperature": 0.7,
"top_p": 0.8,
"top_k": 20,
"frequency_penalty": 1,
"presence_penalty": 0.3,
"seed": -1,
"max_tokens": 50
},
"idle_timeout_seconds": 7200,
"memory_retrieval": {
"enabled": true,
"endpoint": "https://api.example.com/memory/search",
"authorization": "Bearer memory-api-token",
"timeout_ms": 3000
},
"knowledge_retrieval": {
"enabled": true,
"endpoint": "https://api.example.com/knowledge/search",
"authorization": "Bearer knowledge-api-token",
"timeout_ms": 3000
}
}application/jsonResponse fields
live.statusstringSession status: waiting, prepared, on_live, ending, ended.
live.created_atstringCreation time, Unix seconds.
live.start_timestringActual start time, usually written once both sides are ready.
application/jsonlive.end_timestringEnd time.
live.trace_idstringTrace ID used for troubleshooting; recommended to include when reporting issues.
live.billed_secondsstringBilled duration in seconds, usually counted starting from when the session is ready.
live.credits_coststringCredits consumed by this live session.
{
"type": 1,
"live_id": "1234567890",
"user_id": "10000",
"conn_id": "app-conn-1",
"seq_id": 1,
"payload": {}
}{
"audio_url": "https://example.com/reference.wav",
"voice": "my_custom_voice",
"text": "This is the text corresponding to the reference audio",
"language": "zh"
}curl --request GET \
--url 'https://{host}/live/v1/lives/string' \
--header 'Authorization: string'curl --request POST \
--url 'https://{host}/live/v1/voices/clone' \
--header 'Authorization: string' \
--header 'Content-Type: application/json' \
--data '{
"audio_url": "string",
"voice": "string",
"text": "string",
"language": "string"
}'curl --request GET \
--url 'https://api.vidu.com/live/v1/avatars/{id}' \
--header 'Authorization: vda_<api_key>'curl --request DELETE \
--url 'https://api.vidu.com/live/v1/avatars/{id}' \
--header 'Authorization: vda_<api_key>'application/jsonResponse fields
live.idstringRoom ID, required in all subsequent steps — be sure to save it
live.statusstringAt this point it is waiting, the digital human is not yet ready
live.live_durationintegerMaximum duration of this session (seconds); auto-disconnects on timeout
rtc.tokenstringCredential for entering the video room, valid for 1 hour by default
application/jsonapplication/jsonapplication/jsonrtc.user_idstringYour username in the RTC channel
rtc.token_expire_atstringToken expiration time (Unix timestamp); a new session must be created after it expires
{
"type": 1,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 1,
"payload": {
"conn_init": { "version": 1 }
}
}{
"type": 2,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 2,
"payload": {
"conn_init_ack": {
"success": true,
"error_code": "",
"error_msg": "",
"server_timestamp": 1710000000
}
}
}{
"type": 2,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 2,
"payload": {
"conn_init_ack": {
"success": false,
"error_code": "NOT_READY",
"error_msg": "live sip endpoint not ready",
"server_timestamp": 1710000000
}
}
}{
"type": 99,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 10,
"payload": {
"text_msg": {
"msg_id": "client-msg-1",
"content": "Hello, please introduce yourself",
"timestamp": 1710000000000
}
}
}{
"type": 7,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 11,
"payload": {}
}{
"type": 5,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 12,
"payload": {
"hangup": { "hangup_reason": "user_end" }
}
}{
"type": 6,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"payload": {
"hangup": { "hangup_reason": "timeout" }
}
}{
"type": 97,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"seq_id": 20,
"payload": {
"session_update": {
"avatar": { "voice": "Tina" },
"vad": { "type": "server", "threshold": 0.5, "silence_duration_ms": 400 },
"llm": { "temperature": 0.7, "top_p": 0.8, "max_tokens": 50 }
}
}
}{
"type": 98,
"live_id": "1234567890",
"conn_id": "app-conn-1",
"payload": {
"session_update_ack": {
"success": true,
"error_code": "",
"error_msg": ""
}
}
}await aliRtc.setDefaultSubscribeAllRemoteAudioStreams(true);
await aliRtc.setDefaultSubscribeAllRemoteVideoStreams(true);
await aliRtc.joinChannel(rtc.token, rtc.user_id);
await aliRtc.publishLocalAudioStream(true);
if (callMode === 'video') {
await aliRtc.publishLocalVideoStream(true);
}<video id="remoteVideo" autoplay playsinline></video>const remoteVideoElement = document.getElementById('remoteVideo');
aliRtc.on('remoteUserOnLineNotify', (userId) => {
console.log('remote user online', userId);
});
aliRtc.on('videoSubscribeStateChanged', (userId, oldState, newState) => {
if (newState === 'subscribed') {
// streamType=1 indicates the remote camera stream. In video mode, digital human video usually goes through this callback.
aliRtc.setRemoteViewConfig(remoteVideoElement, userId, 1);
remoteVideoElement.play().catch(() => {
console.warn('remote video autoplay failed');
});
}
});
aliRtc.on('screenShareSubscribeStateChanged', (userId, oldState, newState) => {
if (newState === 'subscribed') {
// streamType=2 indicates the remote screen-share stream; if the server uses this stream type, the view also needs to be bound.
aliRtc.setRemoteViewConfig(remoteVideoElement, userId, 2);
}
});{
"live_id": "1234567890",
"query": "User's preferred coding style, programming language preference, script output style",
"reason": "The user asked to generate a script according to their previously preferred coding style, and the current context has no relevant preference information.",
"memory_types": ["preference", "style"],
"time_hint": "long-term preference",
"max_results": 5
}{
"memories": [
{
"id": "mem_101",
"summary": "The user prefers concise code, avoids over-abstraction, and clear variable naming.",
"type": "style",
"confidence": 0.94,
"updated_at": "2026-06-01T09:00:00+08:00",
"source": "long_term_memory"
},
{
"id": "mem_102",
"summary": "The user usually prefers Go examples; if the user explicitly requests Python, Python may be used.",
"type": "preference",
"confidence": 0.86,
"updated_at": "2026-05-20T13:00:00+08:00",
"source": "long_term_memory"
}
]
}{
"memories": [],
"error": "invalid_request"
}{
"memory_retrieval": {
"enabled": true,
"endpoint": "https://api.vidu.com/live/v1/fake-memory/search",
"authorization": "fake"
}
}{
"live_id": "1234567890",
"query": "What does the user like Lingfei to call them",
"reason": "Verify whether the fake memory provider can return nickname memory",
"memory_types": ["relationship"],
"max_results": 3
}{
"memories": [
{
"id": "persona_01_relationship_nickname_001",
"summary": "The user likes Lingfei to call them \"Ah Che\".",
"type": "relationship",
"confidence": 1,
"updated_at": "2026-07-10T00:00:00+08:00",
"source": "fake_persona_memory"
}
]
}{
"live_id": "1234567890",
"query": "Troubleshooting steps when Vidu real-time digital human creation fails",
"reason": "The user asked about the specific troubleshooting process, and the current context has no product documentation content.",
"knowledge_types": ["procedure", "troubleshooting"],
"time_hint": "latest version",
"max_results": 5
}{
"knowledge": [
{
"id": "doc_001_chunk_03",
"title": "Real-time Digital Human Creation Troubleshooting Guide",
"content": "If CreateLive returns a SIP creation failure, first check call_mode, avatar.image_uri, the SIP provider's return code, and the live log trace_id.",
"type": "troubleshooting",
"source": "ops_runbook",
"updated_at": "2026-07-01T10:00:00+08:00",
"confidence": 0.92,
"url": "https://kb.example.com/docs/live-troubleshooting"
}
]
}{
"knowledge": [],
"error": "invalid_request"
}{
"knowledge_retrieval": {
"enabled": true,
"endpoint": "https://api.vidu.com/live/v1/fake-knowledge/search",
"authorization": "fake",
"timeout_ms": 1000
}
}{
"live_id": "1234567890",
"query": "How to claim the firefly badge, what is the password",
"reason": "Verify whether the fake knowledge provider can return the exclusive demo material",
"knowledge_types": ["document"],
"max_results": 3
}{
"knowledge": [
{
"id": "live_knowledge_product_demo_badge_001",
"title": "Vidu Live Demo Badge Claim Rules",
"content": "In the 2026 fake knowledge demo, when a user asks how to claim the firefly badge, the digital human should answer: go to booth B3-17 and say the password \"Blue Whale Seven\" to claim the firefly badge. This rule is only used to verify the search_knowledge tool call.",
"type": "document",
"source": "fake_live_knowledge",
"updated_at": "2026-07-10T00:00:00+08:00",
"confidence": 1
}
]
}curl --request POST \
--url 'https://{host}/live/v1/lives' \
--header 'Authorization: string' \
--header 'Content-Type: application/json' \
--data '{
"call_mode": "string",
"avatar": {
"persona": "string",
"image_uri": "string",
"id": "string",
"voice": "string",
"greeting_instruction": "string",
"farewell_enabled": true,
"persona_enhance": true,
"idle_action": true
},
"idle_timeout_seconds": 7200,
"audio": {
"enable_transcription": false
},
"vad": {
"type": "server",
"threshold": 0.5,
"silence_duration_ms": 400,
"idle_timeout_ms": 0
},
"llm": {
"temperature": 0.7,
"top_p": 0.8,
"top_k": 20,
"frequency_penalty": 1,
"presence_penalty": 0.3,
"seed": -1,
"max_tokens": 50
}
}'{
"live": {
"id": "123456789",
"status": "waiting",
"live_duration": 600,
"call_mode": "video"
},
"rtc": {
"app_id": "xxxx",
"channel_id": "live-user-123456789",
"user_id": "live-user-1001-123456789",
"token": "base64-token...",
"token_expire_at": "1750003600"
}
}curl --request GET \
--url 'https://{host}/live/v1/lives?pager.page=0&pager.pagesz=0&pager.page_token=string' \
--header 'Authorization: string'{
"total": 12,
"lives": [
{
"id": "1234567890",
"status": "ended",
"call_mode": "video",
"billed_seconds": 120,
"credits_cost": 20
}
],
"next_page_token": ""
}Request example
Request example
wss://{host}/live/ws/live/connect?live_id={live_id}&conn_id={conn_id}
Authorization: Token vda_xxxPOST <memory_retrieval.endpoint>
Content-Type: application/json
Accept: application/json
Authorization: <memory_retrieval.authorization>POST /v1/fake-memory/search
Content-Type: application/jsonPOST /live/v1/fake-memory/searchPOST <knowledge_retrieval.endpoint>
Content-Type: application/json
Accept: application/json
Authorization: <knowledge_retrieval.authorization>POST /v1/fake-knowledge/search
Content-Type: application/jsonPOST /live/v1/fake-knowledge/search