o
    iQ9                     @   s  d Z ddlmZmZmZ ddlZddlmZ ddlm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZ ddlmZ ddlmZ dd	lm Z m!Z!m"Z" dd
l#m$Z$ ddl%m&Z& ddl'm(Z(m)Z) G dd de$Z*G dd de&Z+G dd de)Z,G dd de(Z-dS )a;  HeyGen implementation for Pipecat.

This module provides integration with the HeyGen platform for creating conversational
AI applications with avatars. It manages conversation sessions and provides real-time
audio/video streaming capabilities through the HeyGen API.

The module consists of three main components:
- HeyGenInputTransport: Handles incoming audio and events from HeyGen conversations
- HeyGenOutputTransport: Manages outgoing audio and events to HeyGen conversations
- HeyGenTransport: Main transport implementation that coordinates input/output transports
    )AnyOptionalUnionN)logger)AudioRawFrameBotConnectedFrameBotStartedSpeakingFrameBotStoppedSpeakingFrameCancelFrameClientConnectedFrameEndFrameFrameInputAudioRawFrameInterruptionFrameOutputAudioRawFrame
StartFrameUserStartedSpeakingFrameUserStoppedSpeakingFrame)FrameDirectionFrameProcessorFrameProcessorSetup)NewSessionRequest)LiveAvatarNewSessionRequest)HeyGenCallbacksHeyGenClientServiceType)BaseInputTransport)BaseOutputTransport)BaseTransportTransportParamsc                       s   e Zd ZdZdedef fddZdef fddZ fd	d
Z	de
f fddZdef fddZdef fddZdefddZdefddZ  ZS )HeyGenInputTransportzInput transport for receiving audio and events from HeyGen conversations.

    Handles incoming audio streams from participants and manages audio capture
    from the Daily room connected to the HeyGen conversation.
    clientparamsc                    s*   t  j|fi | || _|| _d| _dS )zInitialize the HeyGen input transport.

        Args:
            client: The HeyGen transport client instance.
            params: Transport configuration parameters.
            **kwargs: Additional arguments passed to parent class.
        FN)super__init___client_params_initializedselfr!   r"   kwargs	__class__ W/home/ubuntu/.local/lib/python3.10/site-packages/pipecat/transports/heygen/transport.pyr$   8   s   
zHeyGenInputTransport.__init__setupc                    *   t  |I dH  | j|I dH  dS )znSetup the input transport.

        Args:
            setup: The frame processor setup configuration.
        Nr#   r/   r%   r)   r/   r+   r-   r.   r/   K      zHeyGenInputTransport.setupc                    &   t   I dH  | j I dH  dS )z"Cleanup input transport resources.Nr#   cleanupr%   r)   r+   r-   r.   r6   T      zHeyGenInputTransport.cleanupframec                    s8   t  |I dH  | jrdS d| _| |I dH  dS )z{Start the input transport.

        Args:
            frame: The start frame containing initialization parameters.
        NT)r#   startr'   set_transport_readyr)   r9   r+   r-   r.   r:   Y   s   zHeyGenInputTransport.startc                    (   t  |I dH  | j I dH  dS )zpStop the input transport.

        Args:
            frame: The end frame signaling transport shutdown.
        Nr#   stopr%   r<   r+   r-   r.   r?   h      zHeyGenInputTransport.stopc                    (   t  |I dH  | j I dH  dS )zyCancel the input transport.

        Args:
            frame: The cancel frame signaling immediate cancellation.
        Nr#   cancelr%   r?   r<   r+   r-   r.   rC   q   r@   zHeyGenInputTransport.cancelparticipant_idc                    s8   | j jrtd|  | j|| jI dH  dS dS )zStart capturing audio from a participant.

        Args:
            participant_id: The participant to capture audio from.
        z6HeyGenTransport start capturing audio for participant N)r&   audio_in_enabledr   infor%   capture_participant_audio_on_participant_audio_datar)   rD   r-   r-   r.   start_capturing_audioz   s   z*HeyGenInputTransport.start_capturing_audioaudio_framec                    s*   t |j|j|jd}| |I dH  dS )z'Handle received participant audio data.)audiosample_ratenum_channelsN)r   rL   rM   rN   push_audio_frame)r)   rK   r9   r-   r-   r.   rH      s   z/HeyGenInputTransport._on_participant_audio_data)__name__
__module____qualname____doc__r   r   r$   r   r/   r6   r   r:   r   r?   r
   rC   strrJ   r   rH   __classcell__r-   r-   r+   r.   r    1   s    			r    c                       s   e Zd ZdZdedef fddZdef fddZ fd	d
Z	de
f fddZdef fddZdef fddZejfdedef fddZdedef fddZdedefddZ  ZS )HeyGenOutputTransportzOutput transport for sending audio and events to HeyGen conversations.

    Handles outgoing audio streams to participants and manages the custom
    audio track expected by the HeyGen platform.
    r!   r"   c                    s0   t  j|fi | || _|| _d| _d| _dS )zInitialize the HeyGen output transport.

        Args:
            client: The HeyGen transport client instance.
            params: Transport configuration parameters.
            **kwargs: Additional arguments passed to parent class.
        FN)r#   r$   r%   r&   r'   	_event_idr(   r+   r-   r.   r$      s
   
zHeyGenOutputTransport.__init__r/   c                    r0   )zoSetup the output transport.

        Args:
            setup: The frame processor setup configuration.
        Nr1   r2   r+   r-   r.   r/      r3   zHeyGenOutputTransport.setupc                    r4   )z#Cleanup output transport resources.Nr5   r7   r+   r-   r.   r6      r8   zHeyGenOutputTransport.cleanupr9   c                    sX   t  |I dH  | jrdS d| _| j|| jI dH  | |I dH  | j  dS )z|Start the output transport.

        Args:
            frame: The start frame containing initialization parameters.
        NT)r#   r:   r'   r%   audio_chunk_sizer;   transport_readyr<   r+   r-   r.   r:      s   zHeyGenOutputTransport.startc                    r=   )zqStop the output transport.

        Args:
            frame: The end frame signaling transport shutdown.
        Nr>   r<   r+   r-   r.   r?      r@   zHeyGenOutputTransport.stopc                    rA   )zzCancel the output transport.

        Args:
            frame: The cancel frame signaling immediate cancellation.
        NrB   r<   r+   r-   r.   rC      r@   zHeyGenOutputTransport.cancel	directionc                    st   |t jkr.t|tr| jdurtd t|j| _nt|t	r.| j
| jI dH  d| _t ||I dH  dS )zPush a frame to the next processor in the pipeline.

        Args:
            frame: The frame to push.
            direction: The direction to push the frame.
        Nz"self._event_id is already defined!)r   
DOWNSTREAM
isinstancer   rW   r   warningrT   idr	   r%   agent_speak_endr#   
push_framer)   r9   rZ   r+   r-   r.   r`      s   
	



z HeyGenOutputTransport.push_framec                    s   t  ||I dH  t|tr#| j| jI dH  | ||I dH  t|tr;| j	 I dH  | ||I dH  dS t|t
rS| j I dH  | ||I dH  dS dS )ae  Process frames and handle interruptions.

        Handles various types of frames including interruption events and user speaking states.
        Updates the HeyGen client state based on the received frames.

        Args:
            frame: The frame to process
            direction: The direction of frame flow in the pipeline

        Note:
            Special handling is implemented for:
            - InterruptionFrame: Triggers interruption of current speech
            - UserStartedSpeakingFrame: Initiates agent listening mode
            - UserStoppedSpeakingFrame: Stops agent listening mode
        N)r#   process_framer\   r   r%   	interruptrW   r`   r   start_agent_listeningr   stop_agent_listeningra   r+   r-   r.   rb      s   


z#HeyGenOutputTransport.process_framereturnc                    s"   | j t|j| jI dH  dS )zrWrite an audio frame to the HeyGen transport.

        Args:
            frame: The audio frame to write.
        NT)r%   agent_speakbytesrL   rW   r<   r-   r-   r.   write_audio_frame
  s   z'HeyGenOutputTransport.write_audio_frame)rP   rQ   rR   rS   r   r   r$   r   r/   r6   r   r:   r   r?   r
   rC   r   r[   r   r`   rb   r   boolri   rU   r-   r-   r+   r.   rV      s    			rV   c                   @   s*   e Zd ZU dZdZeed< dZeed< dS )HeyGenParamszConfiguration parameters for the HeyGen transport.

    Parameters:
        audio_in_enabled: Whether to enable audio input from participants.
        audio_out_enabled: Whether to enable audio output to participants.
    TrE   audio_out_enabledN)rP   rQ   rR   rS   rE   rj   __annotations__rl   r-   r-   r-   r.   rk     s   
 rk   c                       s   e Zd ZdZe ddddfdejdededee dee dee	e
ef  d	ee f fd
dZdd ZdefddZdefddZdefddZdefddZdefddZdefddZ  ZS )HeyGenTransporta  Transport implementation for HeyGen video calls.

    When used, the Pipecat bot joins the same virtual room as the HeyGen Avatar and the user.
    This is achieved by using `HeyGenTransport`, which initiates the conversation via
    `HeyGenApi` and obtains a room URL that all participants connect to.

    Event handlers available:

    - on_client_connected(transport, participant): Participant connected to the session
    - on_client_disconnected(transport, participant): Participant disconnected from the session

    Example::

        @transport.event_handler("on_client_connected")
        async def on_client_connected(transport, participant):
            ...
    Nsessionapi_keyr"   
input_nameoutput_namesession_requestservice_typec                    sp   t  j||d || _t|||||t| j| j| jdd| _d| _	d| _
d| _| d | d | d dS )a  Initialize the HeyGen transport.

        Sets up a new HeyGen transport instance with the specified configuration for
        handling video calls between the Pipecat bot and HeyGen Avatar.

        Args:
            session: aiohttp session for making async HTTP requests
            api_key: HeyGen API key for authentication
            params: HeyGen-specific configuration parameters (default: HeyGenParams())
            input_name: Optional custom name for the input transport
            output_name: Optional custom name for the output transport
            session_request: Configuration for the HeyGen session
            service_type: Service type for the avatar session

        Note:
            The transport will automatically join the same virtual room as the HeyGen Avatar
            and user through the HeyGenClient, which handles session initialization via HeyGenApi.
        )rq   rr   )on_connectedon_participant_connectedon_participant_disconnected)rp   ro   r"   rs   rt   	callbacksNru   on_client_connectedon_client_disconnected)r#   r$   r&   r   r   _on_connected_on_participant_connected_on_participant_disconnectedr%   _input_output_HeyGen_participant_id_register_event_handler)r)   ro   rp   r"   rq   rr   rs   rt   r+   r-   r.   r$   3  s(   

zHeyGenTransport.__init__c                    s4   |  dI dH  | jr| jt I dH  dS dS )z%Handle bot connected to LiveKit room.ru   N)_call_event_handlerr~   r`   r   r7   r-   r-   r.   r{   g  s
   zHeyGenTransport._on_connectedrD   c                    s4   t d| d |dkr| |I d H  d S d S )NHeyGen participant z disconnectedheygen)r   debug_on_client_disconnectedrI   r-   r-   r.   r}   m  s
   z,HeyGenTransport._on_participant_disconnectedc                    sP   t d| d |dkr$| |I d H  | jr&| j|I d H  d S d S d S )Nr   z
 connectedr   )r   r   _on_client_connectedr~   rJ   rI   r-   r-   r.   r|   r  s   z)HeyGenTransport._on_participant_connectedrf   c                 C      | j st| j| jd| _ | j S )zGet the input transport for receiving media and events.

        Returns:
            The HeyGen input transport instance.
        r!   r"   )r~   r    r%   r&   r7   r-   r-   r.   inputy     zHeyGenTransport.inputc                 C   r   )zGet the output transport for sending media and events.

        Returns:
            The HeyGen output transport instance.
        r   )r   rV   r%   r&   r7   r-   r-   r.   output  r   zHeyGenTransport.outputparticipantc                    s6   |  d|I dH  | jr| jt I dH  dS dS )zHandle client connected events.ry   N)r   r~   r`   r   r)   r   r-   r-   r.   r     s
   z$HeyGenTransport._on_client_connectedc                    s   |  d|I dH  dS )z"Handle client disconnected events.rz   N)r   r   r-   r-   r.   r     s   z'HeyGenTransport._on_client_disconnected)rP   rQ   rR   rS   rk   aiohttpClientSessionrT   r   r   r   r   r   r$   r{   r}   r|   r   r   r   r   r   r   rU   r-   r-   r+   r.   rn      s:    4

rn   ).rS   typingr   r   r   r   logurur   pipecat.frames.framesr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   "pipecat.processors.frame_processorr   r   r   .pipecat.services.heygen.api_interactive_avatarr   &pipecat.services.heygen.api_liveavatarr   pipecat.services.heygen.clientr   r   r   pipecat.transports.base_inputr   pipecat.transports.base_outputr   !pipecat.transports.base_transportr   r   r    rV   rk   rn   r-   r-   r-   r.   <module>   s"   @_ 