From 3faba84a8bf2c0f3931034bb79e969d7d8a27715 Mon Sep 17 00:00:00 2001 From: Adir Amsalem Date: Thu, 5 Mar 2026 10:05:58 +0000 Subject: [PATCH] fix: align avatar-live model name and path with backend The Python SDK used model name 'avatar-live' with path '/v1/avatar-live/stream', but the backend registers the model as 'live_avatar' and serves all realtime models on '/v1/stream' (model passed as query param). This mismatch caused 404 errors for Python SDK users trying to use Avatar Live. Changes: - Rename model from 'avatar-live' to 'live_avatar' (matches backend + JS SDK) - Change url_path from '/v1/avatar-live/stream' to '/v1/stream' (matches backend) - Update RealTimeModels type, example, playground, and tests accordingly --- decart/models.py | 8 ++++---- decart/realtime/webrtc_connection.py | 2 +- examples/avatar_live.py | 2 +- playground/playground.py | 4 ++-- tests/test_models.py | 6 +++--- tests/test_realtime_unit.py | 16 ++++++++-------- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/decart/models.py b/decart/models.py index 1de9dba..33c0b08 100644 --- a/decart/models.py +++ b/decart/models.py @@ -4,7 +4,7 @@ from .types import FileInput, MotionTrajectoryInput -RealTimeModels = Literal["mirage", "mirage_v2", "lucy_v2v_720p_rt", "lucy_2_rt", "avatar-live"] +RealTimeModels = Literal["mirage", "mirage_v2", "lucy_v2v_720p_rt", "lucy_2_rt", "live_avatar"] VideoModels = Literal[ "lucy-dev-i2v", "lucy-fast-v2v", @@ -182,9 +182,9 @@ class ImageToImageInput(DecartBaseModel): height=720, input_schema=BaseModel, ), - "avatar-live": ModelDefinition( - name="avatar-live", - url_path="/v1/avatar-live/stream", + "live_avatar": ModelDefinition( + name="live_avatar", + url_path="/v1/stream", fps=25, width=1280, height=720, diff --git a/decart/realtime/webrtc_connection.py b/decart/realtime/webrtc_connection.py index 98b183a..746d1f5 100644 --- a/decart/realtime/webrtc_connection.py +++ b/decart/realtime/webrtc_connection.py @@ -246,7 +246,7 @@ async def on_ice_connection_state_change(): self._pc.addTransceiver("audio", direction="recvonly") logger.debug("Added video+audio transceivers (recvonly) for subscribe mode") else: - if model_name == "avatar-live": + if model_name == "live_avatar": self._pc.addTransceiver("video", direction="recvonly") logger.debug("Added video transceiver (recvonly) for avatar-live mode") self._pc.addTrack(local_track) diff --git a/examples/avatar_live.py b/examples/avatar_live.py index 32b6e6f..c8157e3 100644 --- a/examples/avatar_live.py +++ b/examples/avatar_live.py @@ -85,7 +85,7 @@ async def main(): print("\nCreating Decart client...") async with DecartClient(api_key=api_key) as client: - model = models.realtime("avatar-live") + model = models.realtime("live_avatar") print(f"Using model: {model.name}") frame_count = 0 diff --git a/playground/playground.py b/playground/playground.py index 08c6551..c014698 100644 --- a/playground/playground.py +++ b/playground/playground.py @@ -91,9 +91,9 @@ def _check_deps() -> None: # ── Constants ──────────────────────────────────────────────────────────────── -REALTIME_MODELS = ["mirage", "mirage_v2", "lucy_v2v_720p_rt", "lucy_2_rt", "avatar-live"] +REALTIME_MODELS = ["mirage", "mirage_v2", "lucy_v2v_720p_rt", "lucy_2_rt", "live_avatar"] CAMERA_MODELS = {"mirage", "mirage_v2", "lucy_v2v_720p_rt", "lucy_2_rt"} -AVATAR_MODELS = {"avatar-live"} +AVATAR_MODELS = {"live_avatar"} BANNER = """ ╔══════════════════════════════════════╗ diff --git a/tests/test_models.py b/tests/test_models.py index 0d0e0ef..4f776d4 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -18,12 +18,12 @@ def test_realtime_models() -> None: assert model.url_path == "/v1/stream" # avatar-live model - model = models.realtime("avatar-live") - assert model.name == "avatar-live" + model = models.realtime("live_avatar") + assert model.name == "live_avatar" assert model.fps == 25 assert model.width == 1280 assert model.height == 720 - assert model.url_path == "/v1/avatar-live/stream" + assert model.url_path == "/v1/stream" def test_video_models() -> None: diff --git a/tests/test_realtime_unit.py b/tests/test_realtime_unit.py index 6cf95a0..42b2ce9 100644 --- a/tests/test_realtime_unit.py +++ b/tests/test_realtime_unit.py @@ -357,12 +357,12 @@ async def set_event(): def test_avatar_live_model_available(): """Test that avatar-live model is available""" - model = models.realtime("avatar-live") - assert model.name == "avatar-live" + model = models.realtime("live_avatar") + assert model.name == "live_avatar" assert model.fps == 25 assert model.width == 1280 assert model.height == 720 - assert model.url_path == "/v1/avatar-live/stream" + assert model.url_path == "/v1/stream" @pytest.mark.asyncio @@ -400,14 +400,14 @@ async def test_avatar_live_connect_with_initial_image(): api_key=client.api_key, local_track=mock_track, options=RealtimeConnectOptions( - model=models.realtime("avatar-live"), + model=models.realtime("live_avatar"), on_remote_stream=lambda t: None, initial_state=ModelState(image=b"fake image bytes"), ), ) assert realtime_client is not None - assert realtime_client._model_name == "avatar-live" + assert realtime_client._model_name == "live_avatar" mock_image_to_b64.assert_called_once() # Verify initial_image was passed to connect mock_manager.connect.assert_called_once() @@ -448,7 +448,7 @@ async def test_avatar_live_set_image(): api_key=client.api_key, local_track=mock_track, options=RealtimeConnectOptions( - model=models.realtime("avatar-live"), + model=models.realtime("live_avatar"), on_remote_stream=lambda t: None, ), ) @@ -614,7 +614,7 @@ async def test_avatar_live_set_image_timeout(): api_key=client.api_key, local_track=mock_track, options=RealtimeConnectOptions( - model=models.realtime("avatar-live"), + model=models.realtime("live_avatar"), on_remote_stream=lambda t: None, ), ) @@ -659,7 +659,7 @@ async def test_avatar_live_set_image_server_error(): api_key=client.api_key, local_track=mock_track, options=RealtimeConnectOptions( - model=models.realtime("avatar-live"), + model=models.realtime("live_avatar"), on_remote_stream=lambda t: None, ), )