"""Phase 4 component test: library mode pre-bake of speaking-base clips. Verifies: - ``set_avatar`` under ``mode=library`` populates ``speaking_base_frames`` with ``library_base_clip_count`` entries. - Each cached entry has shape ``[T, H, W, 3]`` uint8. Run: docker compose exec voice-chat python -m tests.component.test_04_library_prebake """ from __future__ import annotations import sys import numpy as np from server.video import VideoConfig, VideoEngine from tests.component._common import ensure_sample_avatar, get_logger log = get_logger("test_04") def run(): avatar_path = ensure_sample_avatar() cfg = VideoConfig.from_dict( { "enabled": True, "mode": "library", "resolution": 480, "fps": 16, "library": {"base_clip_count": 2, "base_clip_seconds": 3}, } ) engine = VideoEngine(cfg) log.info("Loading models...") engine.load_models() log.info("Pre-baking 2 library clips...") engine.set_avatar(avatar_path) assert len(engine.speaking_base_frames) == 2, \ f"expected 2 base clips, got {len(engine.speaking_base_frames)}" for i, frames in enumerate(engine.speaking_base_frames): assert isinstance(frames, np.ndarray) assert frames.ndim == 4 and frames.shape[-1] == 3 assert frames.dtype == np.uint8 log.info(" clip %d: shape=%s", i, frames.shape) assert engine.get_idle_clip() is not None log.info("PASS: library pre-bake complete") if __name__ == "__main__": run()