ViMax Character Portrait Registry: How Front, Side, and Back Views Are Generated
ViMax's character portrait registry is a JSON-backed dictionary that stores pre-rendered front, side, and back portrait images for every character, along with textual descriptions used during video generation.
The HKUDS/ViMax open-source repository implements a sophisticated character management system that ensures visual consistency across video scenes. The character portrait registry acts as a centralized cache, eliminating redundant image generation while providing reference materials for consistent character depiction from multiple angles.
What is the ViMax Character Portrait Registry?
The registry functions as a persistent data structure that maps character identifiers to their corresponding portrait assets. According to the source code in pipelines/script2video_pipeline.py, the system creates this registry once per run and persists it to character_portraits_registry.json to enable reuse across sessions.
Registry Structure and Persistence
Each entry in the registry uses the character's identifier_in_scene (e.g., "hero") as the top-level key. The JSON structure stores three distinct views:
{
"CharacterA": {
"front": {
"path": ".../front.png",
"description": "A front view portrait of CharacterA."
},
"side": {
"path": ".../side.png",
"description": "A side view portrait of CharacterA."
},
"back": {
"path": ".../back.png",
"description": "A back view portrait of CharacterA."
}
}
}
Each view object contains:
path: Absolute file path to the generated PNGdescription: A short human-readable description used for reference-image selection during frame generation
How ViMax Generates Front, Side, and Back Views
The CharacterPortraitsGenerator class in agents/character_portraits_generator.py implements a sequential generation strategy that uses the front view as an identity anchor for subsequent angles.
Front View Generation
The front view serves as the foundation for character identity. The generate_front_portrait method constructs a generation prompt using prompt_template_front and invokes the image generation agent:
- Location:
agents/character_portraits_generator.pylines 17-24 and 44-55 - Approach: Generates directly from the character's static and dynamic feature strings
- Output: Base identity image used for subsequent view generation
Side View Generation
The side view generation maintains character consistency by referencing the existing front portrait. The generate_side_portrait method explicitly passes the front image as a reference:
# From agents/character_portraits_generator.py lines 61-73
reference_image_paths=[front_image_path]
- Template: Uses
prompt_template_sideto guide angle transformation - Reference Strategy: Supplies
front_image_pathasreference_image_pathsto preserve identity features while rotating the perspective 90 degrees
Back View Generation
Similarly, the back view reuses the front portrait as a reference but modifies the prompt to indicate facial feature occlusion:
- Method:
generate_back_portrait(lines 78-90 inagents/character_portraits_generator.py) - Template: Uses
prompt_template_backwith instructions to hide facial features - Consistency: Maintains hair, clothing, and physical proportions via the same
reference_image_pathsmechanism
Retry Logic and Error Handling
All three generation methods are wrapped with a tenacity retry decorator to handle transient AI-service failures:
@retry(stop=stop_after_attempt(3), ...)
This ensures pipeline robustness when calling external image generation APIs.
Orchestration Flow in the Pipeline
The Script2VideoPipeline coordinates registry creation through the generate_character_portraits method (lines 48-73 in pipelines/script2video_pipeline.py).
Initialization Check
The pipeline first checks for existing character_portraits_registry.json. If present, it loads the registry and skips regeneration, optimizing for repeated runs.
Concurrent Generation
When generation is required, the pipeline:
- Iterates over every
CharacterInScenelacking registry entries - Launches
generate_portraits_for_single_characterconcurrently for each character - Executes sequential generation within each character task: front → side → back
The resulting images are saved to working_dir/character_portraits/<idx>_<identifier>/ before being registered in the global JSON structure (lines 80-108).
Registry Consumption
During frame generation, generate_frames_for_single_camera accesses the registry to supply available_image_path_and_text_pairs for reference-image selection, ensuring characters appear consistent across different camera angles in the final video.
Code Examples
Creating the Registry
pipeline = Script2VideoPipeline(config)
registry = await pipeline.generate_character_portraits(
characters=extracted_characters,
character_portraits_registry=None, # forces fresh generation if no file
style="studio anime"
)
# `registry` now matches the JSON structure shown above
Generating a Side Portrait After Front Exists
front_path = "/tmp/character_portraits/0_hero/front.png"
side_output = await CharacterPortraitsGenerator(image_gen).generate_side_portrait(
character=hero_character,
front_image_path=front_path
)
side_output.save("/tmp/character_portraits/0_hero/side.png")
Reading the Persisted Registry
import json
import os
reg_path = os.path.join(workdir, "character_portraits_registry.json")
with open(reg_path, "r", encoding="utf-8") as f:
registry = json.load(f)
hero_views = registry["hero"]
print(hero_views["front"]["path"]) # → ".../front.png"
Summary
- ViMax character portrait registry stores front, side, and back views as JSON with file paths and descriptions for each character.
- View generation occurs sequentially: front first, then side and back using the front image as a reference to maintain identity consistency.
- Persistence via
character_portraits_registry.jsonallows reuse across pipeline runs, stored inpipelines/script2video_pipeline.py. - Error resilience comes from tenacity decorators wrapping all generation methods in
agents/character_portraits_generator.py. - Pipeline integration enables the frame generation step to select appropriate reference images based on camera angles.
Frequently Asked Questions
Where is the ViMax character portrait registry stored?
The registry persists as character_portraits_registry.json in the working directory. The generate_character_portraits method in pipelines/script2video_pipeline.py handles both reading existing registries and writing new ones, making the system restart-friendly.
How does ViMax maintain character consistency across different views?
ViMax maintains consistency through reference image chaining. The generate_side_portrait and generate_back_portrait methods explicitly pass the front view's file path as reference_image_paths to the image generation agent. This technique, implemented in agents/character_portraits_generator.py, ensures hair color, clothing, and facial structure remain identical while only the viewing angle changes.
What happens if image generation fails during portrait creation?
All portrait generation methods are decorated with @retry(stop=stop_after_attempt(3), …) from the tenacity library. If the AI service returns an error or timeout, the system automatically retries up to three times before failing, preventing temporary network issues from breaking the entire video generation pipeline.
How does the pipeline use the registry during frame generation?
During the generate_frames_for_single_camera phase, the pipeline queries the registry to populate available_image_path_and_text_pairs. This allows the system to select the appropriate view (front, side, or back) based on the camera angle described in the shot, ensuring the generated frame references the correct character orientation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →