from pydantic import BaseModel, Field, ConfigDict, TypeAdapter from typing import Literal, Union, Annotated class LipsyncMessage(BaseModel): model_config = ConfigDict(ser_json_bytes="base64", val_json_bytes="base64") class LipsyncConfigMessage(LipsyncMessage): type: Literal["config"] = "config" video_fps: int audio_sample_rate: int class LipsyncConfigAckMessage(LipsyncMessage): type: Literal["config_ack"] = "config_ack" class LipsyncAudioInputMessage(LipsyncMessage): type: Literal["audio_input"] = "audio_input" audio_data: bytes class LipsyncVideoInputMessage(LipsyncMessage): type: Literal["video_input"] = "video_input" video_frame: bytes class LipsyncInterruptAudioMessage(LipsyncMessage): type: Literal["interrupt_audio"] = "interrupt_audio" class LipsyncSyncedOutputMessage(LipsyncMessage): type: Literal["synced_result"] = "synced_result" video_frame: bytes audio_frame: bytes class LipsyncErrorMessage(LipsyncMessage): type: Literal["error"] = "error" message: str LipsyncClientMessage = Annotated[ Union[LipsyncConfigMessage, LipsyncAudioInputMessage, LipsyncVideoInputMessage, LipsyncInterruptAudioMessage], Field(discriminator="type"), ] LipsyncServerMessage = Annotated[ Union[LipsyncConfigAckMessage, LipsyncSyncedOutputMessage, LipsyncErrorMessage], Field(discriminator="type") ] LipsyncServerMessageAdapter = TypeAdapter(LipsyncServerMessage)