Private virtual portrait library
ModelArk · Seedance 2.0 & 2.5 · Asset management for consistent characters in video generation
docs.byteplus.com/en/docs/ModelArk/2333565 ↗
- The upload asset (CreateAsset) API is asynchronous. System processing may result in queuing, which can increase the time required for storage; higher latency is expected for uploading video.
- SLA for uploading time is not guaranteed.
- You must ensure that the uploaded virtual portrait meets the following conditions:
- You legally own the asset and have full rights to use and dispose of it. The asset does not contain unauthorized third-party trademarks or logo content.
- The asset must not resemble any real human person's portrait, must not be plagiarized or misappropriated, and must not infringe on any third party's portrait rights.
- The asset does not contain content that violates regulations, contravenes public order and morals, or infringes on the legal rights of third parties.
The Dreamina Seedance 2.0 (Seedance 2.0) and Dreamina Seedance 2.5 (Seedance 2.5) models have comprehensive multi-modal capabilities. To ensure creators can fully leverage the powerful video generation capabilities of Seedance 2.0 and 2.5, you can upload virtual portraits to a private asset library for more stable video generation results.
The workflow for using the private asset library is as follows:

Workflow: Activate Advanced Creation Rights → Create asset group → Upload asset → Get Asset ID → Use in video generation
Prerequisites
To access the full features of the Asset Library, you need to activate the Advanced Creation Rights. Refer to Dreamina Seedance Advanced Creation Rights Purchase Guide.
Structure of the asset library
- Asset Group: Each asset file is an Asset, and each Asset belongs to an Asset Group.
- Asset groups allow flexible management of assets. For example, assets of the same person can be grouped into one Asset Group for easy management.
- Asset: A file (image, video or audio) that is trusted by the Seedance 2.0 and Seedance 2.5 models for use in video generation. Currently, only AIGC virtual portrait assets are supported.
- Only assets required for inference need to be added to the library; do not add assets that are not required for inference.
- Only the Asset ID of assets already added to the library can be used for video generation; assets for regular image/video generation do not need to be added to the library.
- Each uploaded asset must be preprocessed. You can poll the GetAsset API to check the asset status (the asset can only be used for video generation when the status is
Active).
Taking uploading a character image asset as an example:
Single image file format requirements:
- Format: jpeg, png, webp, tiff, gif, heic/heif
- Aspect ratio (width/height): (0.4, 2.5)
- Width and height (px): (300, 6000)
- Each image file must be less than 30 MB.
To ensure that the character's face, clothing details, and other features in the generated video are consistent with the reference image, we recommend providing the following types of reference images for the virtual portrait:
Best practices for portrait asset content:
Full-body reference image requirements
- Layout: Vertical
- Image content: Full-body frontal image of the person
Example: full-body reference image (vertical, frontal)
Facial close-up image requirements
- Layout: Vertical
- Image content: Frontal close-up of the person without expression, above the shoulders, with the face centered and no occlusion
Example: facial close-up reference image (vertical, frontal, above shoulders)
Assets API list
Asset (group) creation
| API | Description |
|---|---|
| POSTCreateAssetGroup | Create an asset group. When creating an asset group for the first time, you must specify GroupType. Once set, this field cannot be changed. |
| POSTCreateAsset | Create an asset. This interface can be used to upload personal assets. After creating an asset, call GetAsset to check if the asset has been processed successfully. |
Asset (group) management
- POST
ListAssetGroups— query the list of asset groups - POST
ListAssets— query the list of assets - POST
GetAsset— query asset information - POST
GetAssetGroup— query asset group information - POST
UpdateAssetGroup— update asset group information - POST
UpdateAsset— update asset information - POST
DeleteAsset— delete an asset - POST
DeleteAssetGroup— delete an asset group
Rate limits
- QPS: Maximum total request count per second; request will return an error when this limit is exceeded.
- QPM: Maximum total request count per minute; requests will return an error when this limit is exceeded.
| API | Rate limits by account |
|---|---|
| CreateAssetGroup | 10 QPS |
| CreateAsset | API rate limits vary by rights type. For detailed limits, see Dreamina Seedance Advanced Creation Rights Purchase Guide. |
| ListAssetGroups | 10 QPS |
| ListAssets | 10 QPS |
| GetAsset | 100 QPS |
| GetAssetGroup | 10 QPS |
| UpdateAsset | 10 QPS |
| UpdateAssetGroup | 10 QPS |
| DeleteAsset | 10 QPS |
| DeleteAssetGroup | 5 QPS |
Tutorial
Upload assets to the virtual portrait library (API & UI console)
You can upload your own virtual portraits to the private asset library.
- You legally own the asset and have full rights to use and dispose of it. The asset does not contain unauthorized third-party trademarks or logo content.
- The asset must not resemble the portrait or likeness of any natural person, must not involve plagiarism or misappropriation of any natural person's portrait or likeness.
- The asset does not contain content that violates laws and regulations, public order and good morals, or infringes on the legal rights of third parties.
ModelArk will conduct a security review of the assets you upload. Once approved, you can use the asset for video generation.
You can use OpenAPI interfaces or upload assets in the Model Playground.
Use the console
Open Model Playground > My assets > Virtual Portrait > Manage assets.
- Create an asset group.
- Upload assets to the asset group.
ModelArk Console — My assets → Virtual Portrait → Manage assets
Use the API
- CreateAssetGroup: Create an asset group
- CreateAsset: Upload assets to the group
CreateAssetGroup — Create an asset group
- Calling the Assets API requires Access Key authentication. For details, refer to API access key management.
- For API parameter information, please refer to Virtual portrait library API reference.
Use the POST CreateAssetGroup API to create an asset group. Include the following fields in the request body:
- Name: The name of the asset group.
- Description: The description of the asset group.
- GroupType: Optional. Defaults to
AIGC(virtual portrait asset). Currently, only AIGC is supported. - ProjectName: Optional. Specifies the resource project name. Defaults to
default. Resources in a project can only be used by inference endpoints within that project.
ProjectName is not specified in the request, the asset group will be created in the default project by default. You need to use this field to ensure the asset group is created in the correct project.package main
import (
"fmt"
"github.com/bytedance/sonic"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/credentials"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/session"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/universal"
)
func main () {
config := byteplus.NewConfig().WithCredentials(credentials.NewStaticCredentials( "<your_ak>" , "<your_sk>" , "" )).WithRegion( "ap-southeast-1" )
sess, _ := session.NewSession(config)
resp, err := universal.New(sess).DoCall(
universal.RequestUniversal{
ServiceName: "ark" ,
Action: "CreateAssetGroup" ,
Version: "2024-01-01" ,
HttpMethod: universal.POST,
ContentType: universal.ApplicationJSON,
},
& map [ string ]any{
"Name" : "<GROUP_NAME>" ,
"Description" : "<GROUP_DESC>" ,
"ProjectName" : "default" ,
},
)
if err != nil {
fmt.Printf( "error: %v\n" , err)
return
}
if resp == nil {
return
}
respData, err := sonic.Marshal(resp)
fmt.Println( string (respData))
{
"Id" : "group-20260318033332-*****"
CreateAsset — Upload an asset
Use the POST CreateAsset API to upload an asset.
Provide the following in the request:
- GroupId: Required. Asset group ID.
- URL: Required. Accessible image URL.
- AssetType: Required. Support uploading image/video/audio assets. You need to specify the asset type:
Image/Video/Audio. For specific restrictions on asset files, see the Assets API documentation. - Name: Optional. Asset name, which can be used for asset management, such as the asset file name. This field is used only for fuzzy search when calling the ListAssets API and is not included in model inference.
- Moderation: Optional. Specifies whether to turn off the Content Pre-filter review for the current asset.
- By default, the Content Pre-filter review is on.
- To skip most non-baseline content security review policies, set this parameter to
"Moderation": {"Strategy": "Skip"}.
- ProjectName: Optional. Specifies the resource project name. Defaults to
default.
ProjectName is not specified in the request, the asset will be uploaded to the default project by default.Notes:
- Each request uploads a single asset file.
- This request returns the asset ID. You can use the
GetAssetAPI to view whether the upload was successful.
package main
import (
"fmt"
"github.com/bytedance/sonic"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/credentials"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/session"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/universal"
)
func main () {
config := byteplus.NewConfig().WithCredentials(credentials.NewStaticCredentials( "<YOUR_AK>" , "<YOUR_SK>" , "" )).WithRegion( "ap-southeast-1" )
sess, _ := session.NewSession(config)
resp, err := universal.New(sess).DoCall(
universal.RequestUniversal{
ServiceName: "ark" ,
Action: "CreateAsset" ,
Version: "2024-01-01" ,
HttpMethod: universal.POST,
ContentType: universal.ApplicationJSON,
},
& map [ string ]any{
"GroupId" : "group-20260324142802-f7wmx" ,
"URL" : "<IMAGE_URL>" ,
"AssetType" : "Image" ,
"Moderation" : map [ string ]any{ // Skip the Content Pre-filter review, must turn off content pre-filter on the console first
"Strategy" : "Skip" ,
},
"ProjectName" : "default" ,
},
)
if err != nil {
fmt.Printf( "error: %v\n" , err)
return
}
if resp == nil {
return
}
respData, err := sonic.Marshal(resp)
fmt.Println( string (respData))
{
"Id" : "asset-20260318071009-*****"
Retrieve virtual portraits (API & Console)
You can retrieve virtual portrait assets using the following methods.
- Console: In the ModelArk Console > My assets > Virtual Portrait, you can search and view uploaded virtual portrait assets.
- API:
- POST GetAsset: Retrieve a single asset
- POST ListAssets: Query assets
- POST ListAssetGroups: Query asset group information
Retrieve information of a single asset
You can use POST GetAsset to retrieve information for a single asset by specifying the asset ID.
package main
import (
"fmt"
"github.com/bytedance/sonic"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/credentials"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/session"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/universal"
)
func main () {
config := byteplus.NewConfig().WithCredentials(credentials.NewStaticCredentials( "<YOUR_AK>" , "<YOUR_SK>" , "" )).WithRegion( "ap-southeast-1" )
sess, _ := session.NewSession(config)
resp, err := universal.New(sess).DoCall(
universal.RequestUniversal{
ServiceName: "ark" ,
Action: "GetAsset" ,
Version: "2024-01-01" ,
HttpMethod: universal.POST,
ContentType: universal.ApplicationJSON,
},
& map [ string ]any{
"Id" : "asset-20260324143042-*****" ,
"ProjectName" : "default" , // Make sure to specify the correct project name where the asset is stored
},
)
if err != nil {
fmt.Printf( "error: %v\n" , err)
return
}
if resp == nil {
return
}
respData, err := sonic.Marshal(resp)
fmt.Println( string (respData))
{
"GroupId" : "group-20260318033332-7vw4m" ,
"Status" : "Active" ,
"Moderation" : {
"Strategy" : "Default"
},
"CreateTime" : "2026-03-18T03:57:10Z" ,
"AssetType" : "Image" ,
"UpdateTime" : "2026-03-18T03:57:14Z" ,
"LastInferenceTime" : "2026-07-24T10:08:49+08:00" ,
"ProjectName" : "default" ,
"Id" : "asset-20260318035710-*****" ,
"Name" : "" ,
"URL" : "https://ark-media-asset-ap-southeast-1.tos-ap-southeast-1.volces.com/300060****/03301616086559****.jpg?X-Tos-Algorithm=***********"
LastInferenceTime indicates the most recent time when an asset was used to submit a video generation task. You can periodically check LastInferenceTime and proactively delete assets that have not been used for a long time to save storage costs.Query asset information
You can use POST ListAssets to query assets. Supports:
- Querying by group ID (
GroupId), asset statuses (Statuses), and asset name (Name). Filter assets that match the query. - Fuzzy search using
Nameand precise search usingGroupId, making it easier to retrieve required assets. - Sorting results using
SortByandSortOrder.
ListAssets supports NextToken pagination and page-number pagination. For pagination methods, parameters, and examples, see Virtual portrait library API reference.package main
import (
"fmt"
"github.com/bytedance/sonic"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/credentials"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/session"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/universal"
)
func main () {
config := byteplus.NewConfig().WithCredentials(credentials.NewStaticCredentials( "<your_ak>" , "<your_sk>" , "" )).WithRegion( "ap-southeast-1" )
sess, _ := session.NewSession(config)
resp, err := universal.New(sess).DoCall(
universal.RequestUniversal{
ServiceName: "ark" ,
Action: "ListAssets" ,
Version: "2024-01-01" ,
HttpMethod: universal.POST,
ContentType: universal.ApplicationJSON,
},
& map [ string ]any{
"Filter" : map [ string ]any{
"GroupIds" : [] string { "group-20260324142802-*****" },
"GroupType" : "AIGC" ,
"Statuses" : [] string { "Active" , "Processing" }, // Supported statuses: Active (Upload successfully, Asset ID available for use), Processing, Failed
},
"MaxResults" : 2 ,
"SortBy" : "CreateTime" ,
"SortOrder" : "Desc" ,
},
)
if err != nil {
fmt.Printf( "list assets error: %v\n" , err)
return
}
if resp == nil {
return
}
respData, err := sonic.Marshal(resp)
fmt.Println( string (respData))
{
"Items" : [
{
"Id" : "asset-20260318035710-kctzf" ,
"Name" : "" ,
"AssetType" : "Image" ,
"CreateTime" : "2026-03-18T03:57:10Z" ,
"UpdateTime" : "2026-03-18T03:57:14Z" ,
"LastInferenceTime" : "2026-07-24T10:08:49+08:00" ,
"ProjectName" : "default" ,
"URL" : "https://ark-media-asset-ap-southeast-1.tos-ap-southeast-1.volces.com/300060****/03301616086559****.jpg?X-Tos-Algorithm=***********" ,
"GroupId" : "group-20260318033332-*****" ,
"Status" : "Active" ,
"Moderation" : {
"Strategy" : "Default"
}
},
{
"GroupId" : "group-20260318033332-*****" ,
"Status" : "Active" ,
"Id" : "asset-20260318034804-wtnjr" ,
"Name" : "" ,
"URL" : "image_url" ,
"AssetType" : "Image" ,
"CreateTime" : "2026-03-18T03:48:04Z" ,
"UpdateTime" : "2026-03-18T03:48:08Z" ,
"LastInferenceTime" : "2026-07-24T02:08:49Z" ,
"ProjectName" : "default" ,
"Moderation" : {
"Strategy" : "Default"
}
}
],
"NextToken" : "****bmNyeXB0ZWRfY3Vyc29yIjoiLi4****"
Query asset groups
Use POST ListAssetGroups to query asset group information.
- Supports fuzzy search for asset group names (
Name) or provides multiple asset groups (GroupId). - If there are multiple asset groups, the
Namefield can be used for fuzzy search.
ListAssetGroups supports NextToken pagination and page-number pagination. For pagination methods, parameters, and examples, see Virtual portrait library API reference.package main
import (
"fmt"
"github.com/bytedance/sonic"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/credentials"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/session"
"github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/universal"
)
func main () {
config := byteplus.NewConfig().WithCredentials(credentials.NewStaticCredentials( "<YOUR_AK>" , "<YOUR_SK>" , "" )).WithRegion( "ap-southeast-1" )
sess, _ := session.NewSession(config)
resp, err := universal.New(sess).DoCall(
universal.RequestUniversal{
ServiceName: "ark" ,
Action: "ListAssetGroups" ,
Version: "2024-01-01" ,
HttpMethod: universal.POST,
ContentType: universal.ApplicationJSON,
},
& map [ string ]any{
"Filter" : map [ string ]any{
"Name" : "<FIGURE_GROUP>" , // Support fuzzy search
"GroupIds" : [] string { "group-20260324142802-*****" , "group-20260324142910-*****" },
"GroupType" : "AIGC" ,
},
"MaxResults" : 1 ,
"SortBy" : "CreateTime" ,
"SortOrder" : "Desc" ,
},
)
if err != nil {
fmt.Printf( "error: %v\n" , err)
return
}
if resp == nil {
return
}
respData, err := sonic.Marshal(resp)
fmt.Println( string (respData))
{
"Items" : [
{
"UpdateTime" : "2026-03-18T03:33:32Z" ,
"Id" : "group-20260318033332-*****" ,
"Name" : "figure_group_1" ,
"Description" : "Figure group 1" ,
"GroupType" : "AIGC" ,
"ProjectName" : "default" ,
"CreateTime" : "2026-03-18T03:33:32Z"
}
],
"NextToken" : "****bmNyeXB0ZWRfY3Vyc29yIjoiLi4****"
Update/delete assets or asset group
You can call UpdateAsset, UpdateAssetGroup, DeleteAsset, and DeleteAssetGroup to update or delete assets and asset groups.
We recommend periodically checking LastInferenceTime by using GetAsset or ListAssets, and proactively deleting assets that have not been used for a long time to save storage costs.
Example: Upload assets and use GetAsset to retrieve asset information
The following example creates an asset, queries the asset Status, and determines whether to continue polling based on the status. The code executes the following logic:
- createAsset: Upload resources and obtain AssetId
- waitForAssetActive: Start querying and repeatedly call
getAssetStatusto check the current asset status - Determine based on Status:
Processing→ Continue pollingActive→ Return URL (end). Once the status is Active, the Asset ID (in URI format) can be used for video generation.Failed→ Return error (end)
- Return the result and print the output
BP_Upload_Asset_Get_Info.go — The query result is illustrated as follows:
asset status: Active
asset is active, URL =
Sample code in other programming languages
Download: bp-demo.zip
ListAssets, replace ACTION and BODY in the demo code.Generate video using portrait assets
After obtaining the Asset ID, private portrait assets can be used to generate video.
For details, see Use preset digital characters.
Use the asset URI in the content._url.url field of the Video Generation API to generate video.
asset://<Asset_Id>Image 1 and Video 1.Do not use an Asset ID directly in the prompt.
Example: "The girl in Image 1 is wearing the outfit from Image 2 and is arranging items on the counter…"
Sample code:
import os
import time
# Install SDK: pip install arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url= "https://ark.ap-southeast.bytepluses.com/api/v3" ,
# Get API Key: https://ai.byteplus.com/ark/region:ap-southeast-1/apikey
api_key=os.environ.get( "ARK_API_KEY" ),
)
if __name__ == "__main__" :
print ( "----- create request -----" )
create_result = client.content_generation.tasks.create(
model= "dreamina-seedance-2-0-260128" , # Replace with Model ID
content=[
{
"type" : "text" ,
"text" : "Vertical HD close-up video of a beauty blogger (Image 1). She has bold, glamorous makeup with no facial shine or glare and a sweet smile. She holds a face cream jar (Image 2), presents it directly to the camera. The background is fresh and minimalist. Energetic and sweet style. English voiceover: 'I found my holy grail face cream! It has a cloud-like creamy texture that absorbs instantly. Perfect for post-all-nighter rescue, deep hydration and moisturization—my skin glows naturally even without makeup!' "
},
{
"type" : "image_url" ,
"image_url" : {
"url" : "asset://asset-20260225023032-gnzwk"
},
"role" : "reference_image"
},
{
"type" : "image_url" ,
"image_url" : {
"url" : "https://ark-doc.tos-ap-southeast-1.bytepluses.com/doc_image/r2v_ref_image.png"
},
"role" : "reference_image"
},
],
generate_audio= True ,
ratio= "16:9" ,
duration= 11 ,
watermark= True ,
)
print (create_result)
print ( "----- polling task status -----" )
task_id = create_result. id
while True :
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded" :
print ( "----- task succeeded -----" )
print (get_result)
break
elif status == "failed" :
print ( "----- task failed -----" )
print ( f"Error: {get_result.error} " )
break
else :
print ( f"Current status: {status} , Retrying after 30 seconds..." )
FAQs
1. Why is it not possible to generate video or retrieve asset information after assets are uploaded successfully?
The asset library is isolated by Project (ProjectName).
- When generating video, inference must be performed using the inference endpoint in the project where the asset is stored.
- If the asset upload is successful but retrieving the asset via the API fails, it may be because different
ProjectNamevalues were specified during upload and retrieval. - The default value for
ProjectNameisdefault. If this field is not specified, resources are created in thedefaultproject. - It is recommended to manage assets within the same project.
For more information about project, see the related IAM docs.
ProjectName is not specified in the request, the asset group will be created in the default project by default.2. How to manage user permissions for the asset library?
You can use Access control (IAM) to finely manage user actions in the asset library. Settings can be customized through the following steps:
Create a custom policy
- Open Access control > Create policy.
- Input the policy name.
- Switch to the JSON editor, paste the custom policy below into the editor, and click submit to save.
{
"Statement" : [
{
"Effect" : "Allow" ,
"Action" : [
"ark:*Asset*"
],
"Resource" : [
"*"
]
}
]
Grant permissions to users/user groups
- Click User management > User / User group, select the user or user group to grant permissions to.
- In Policy, select the policy created in Step 1.
- (Optional) In Limit to project resources, select the project to which the policy applies.
- Click submit.
After completing the above actions, the user or user group can manage assets in the corresponding project.
For more information about IAM, please refer to the IAM docs.
3. How should I reference uploaded assets in the prompt (content.text)?
In the prompt, reference assets using the format "asset type + index", for example: Image 1, Video 1, Audio 1.
For example, the sample below includes five reference images and one reference audio file. Use the prompt format:
- Reference: Image 1, Image 2, Image 3, Image 4, Image 5 (and Audio 1)
- Prompt: see the plain text block below
Create a fresh, creamy-painting–style short drama with a light, upbeat guitar track driving quick beat cuts. Use a cream-white base with peach-pink highlights, soft lighting, no visual effects—emotion conveyed through expressions. 0–2s: Two fast cuts: the CEO from Image 1 accidentally bumps into the female lead wearing the outfit from Image 2 (character from Image 3); they freeze and lock eyes, then a hand close-up as the CEO pulls off his suit jacket and drapes it over her shoulders. Gentle guitar starts; soft SFX of a coffee cup dropping and fabric brushing. 2–6s: Three fast cuts: the female lead, wrapped in his jacket, looks down and smiles shyly (cheeks flushed, close-up); the CEO watches her back with a faint smile and says "我们一起走吧," voice style referenced from Audio 1 (profile shot); the two share a black umbrella in the rain, fingertips touch then quickly pull back (near shot). Rainy backdrop references Image 4; each cut hits a light drum accent with rain and umbrella SFX, a subtle soft-mist look. 6–8s: Slow-motion eye-contact smiles; the text portion from Image 5 appears at the lower right, with small text "NEW EP DAILY" at the lower left. Minimal pale-pink petals drift; the guitar resolves gently as the frame freezes on their side-by-side profiles.
curl --location 'https://ark.ap-southeast-1.bytepluses.com/api/v3/contents/generations/tasks' \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer $ARK_API_KEY' \
-d '{
"model": "seedance-2-0-260128",
"content": [
{
"type": "text",
"text": "Create a fresh, creamy-painting–style short drama with a light, upbeat guitar track driving quick beat cuts. Use a cream-white base with peach-pink highlights, soft lighting, no visual effects—emotion conveyed through expressions. 0–2s: Two fast cuts: the CEO from 【Image 1】 accidentally bumps into the female lead wearing the outfit from 【Image 2】 (character from 【Image 3】); they freeze and lock eyes, then a hand close-up as the CEO pulls off his suit jacket and drapes it over her shoulders. Gentle guitar starts; soft SFX of a coffee cup dropping and fabric brushing. 2–6s: Three fast cuts: the female lead, wrapped in his jacket, looks down and smiles shyly (cheeks flushed, close-up); the CEO watches her back with a faint smile and says “我们一起走吧,” voice style referenced from 【Audio 1】 (profile shot); the two share a black umbrella in the rain, fingertips touch then quickly pull back (near shot). Rainy backdrop references 【Image 4】; each cut hits a light drum accent with rain and umbrella SFX, a subtle soft-mist look. 6–8s: Slow-motion eye-contact smiles; the text portion from 【Image 5】 appears at the lower right, with small text “NEW EP DAILY” at the lower left. Minimal pale-pink petals drift; the guitar resolves gently as the frame freezes on their side-by-side profiles."
},
{
"type": "image_url",
"role": "reference_image",
"image_url": {
"url": "asset://asset-20260224213248-ghm5g"
}
},
{
"type": "image_url",
"role": "reference_image",
"image_url": {
"url": "asset://asset-20260224213248-4lb57"
}
},
{
"type": "image_url",
"role": "reference_image",
"image_url": {
"url": "asset://asset-20260224213248-rc7b7"
}
},
{
"type": "image_url",
"role": "reference_image",
"image_url": {
"url": "asset://asset-20260224213248-wpgsn"
}
},
{
"type": "image_url",
"role": "reference_image",
"image_url": {
"url": "asset://asset-20260224213248-9wrmp"
}
},
{
"type": "audio_url",
"role": "reference_audio",
"audio_url": {
"url": "asset://asset-20260224213248-g5nv7"
}
}
],
"generate_audio": true,
"ratio": "16:9",
"duration": 11,
"watermark": false
Virtual portrait library API reference
For complete API parameters, request/response schemas, error codes, and rate limit details, see the official Virtual portrait library API reference ↗.