
    qiQ9                     0   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e$      Z* G d de&      Z+ G d de)      Z, G d de(      Z-y)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                        e Zd ZdZdedef fdZdef fdZ fdZ	de
f fd	Zdef fd
Zdef fdZdefdZdefdZ x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                 P    t        |   |fi | || _        || _        d| _        y)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__s       U/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/transports/heygen/transport.pyr'   zHeyGenInputTransport.__init__8   s-     	*6*!    setupc                    K   t         |   |       d{    | j                  j                  |       d{    y7 (7 w)znSetup the input transport.

        Args:
            setup: The frame processor setup configuration.
        Nr&   r1   r(   r,   r1   r.   s     r/   r1   zHeyGenInputTransport.setupK   <      gmE"""ll  ''' 	#'   A?"AAAAc                    K   t         |           d{    | j                  j                          d{    y7 '7 w)z"Cleanup input transport resources.Nr&   cleanupr(   r,   r.   s    r/   r9   zHeyGenInputTransport.cleanupT   6     goll""$$$ 	 $   A=!A?AAframec                    K   t         |   |       d{    | j                  ryd| _        | j                  |       d{    y7 27 w)z{Start the input transport.

        Args:
            frame: The start frame containing initialization parameters.
        NT)r&   startr*   set_transport_readyr,   r=   r.   s     r/   r?   zHeyGenInputTransport.startY   sN      gmE""" &&u--- 	# 	.s!   AA	,AAAAc                    K   t         |   |       d{    | j                  j                          d{    y7 '7 w)zpStop the input transport.

        Args:
            frame: The end frame signaling transport shutdown.
        Nr&   stopr(   rA   s     r/   rD   zHeyGenInputTransport.stoph   :      gl5!!!ll!!! 	"!   A>!AA A Ac                    K   t         |   |       d{    | j                  j                          d{    y7 '7 w)zyCancel the input transport.

        Args:
            frame: The cancel frame signaling immediate cancellation.
        Nr&   cancelr(   rD   rA   s     r/   rI   zHeyGenInputTransport.cancelq   :      gnU###ll!!! 	$!rF   participant_idc                    K   | j                   j                  rGt        j                  d|        | j                  j                  || j                         d{    yy7 w)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,   rK   s     r/   start_capturing_audioz*HeyGenInputTransport.start_capturing_audioz   s\      <<((KKPQ_P`ab,,88 ? ?   )s   AA#A!A#audio_framec                    K   t        |j                  |j                  |j                        }| j	                  |       d{    y7 w)z'Handle received participant audio data.)audiosample_ratenum_channelsN)r   rU   rV   rW   push_audio_frame)r,   rS   r=   s      r/   rP   z/HeyGenInputTransport._on_participant_audio_data   sA     "###//$11

 ##E***s   AAA	A)__name__
__module____qualname____doc__r   r    r'   r   r1   r9   r   r?   r   rD   r   rI   strrR   r   rP   __classcell__r.   s   @r/   r"   r"   1   sm    ""  "&(!4 (%
. ." ""+ "
# 
+M +r0   r"   c                        e Zd ZdZdedef fdZdef fdZ fdZ	de
f fd	Zdef fd
Zdef fdZej"                  fdedef fdZdedef fdZdedefdZ x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                 ^    t        |   |fi | || _        || _        d| _        d| _        y)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+   s       r/   r'   zHeyGenOutputTransport.__init__   s6     	*6* "r0   r1   c                    K   t         |   |       d{    | j                  j                  |       d{    y7 (7 w)zoSetup the output transport.

        Args:
            setup: The frame processor setup configuration.
        Nr3   r4   s     r/   r1   zHeyGenOutputTransport.setup   r5   r6   c                    K   t         |           d{    | j                  j                          d{    y7 '7 w)z#Cleanup output transport resources.Nr8   r:   s    r/   r9   zHeyGenOutputTransport.cleanup   r;   r<   r=   c                 2  K   t         |   |       d{    | j                  ryd| _        | j                  j                  || j                         d{    | j                  |       d{    | j                  j                          y7 z7 :7 #w)z|Start the output transport.

        Args:
            frame: The start frame containing initialization parameters.
        NT)r&   r?   r*   r(   audio_chunk_sizer@   transport_readyrA   s     r/   r?   zHeyGenOutputTransport.start   s      gmE""" ll  (=(=>>>&&u---$$& 	# 	?-s4   BBABBB1B2 BBBc                    K   t         |   |       d{    | j                  j                          d{    y7 '7 w)zqStop the output transport.

        Args:
            frame: The end frame signaling transport shutdown.
        NrC   rA   s     r/   rD   zHeyGenOutputTransport.stop   rE   rF   c                    K   t         |   |       d{    | j                  j                          d{    y7 '7 w)zzCancel the output transport.

        Args:
            frame: The cancel frame signaling immediate cancellation.
        NrH   rA   s     r/   rI   zHeyGenOutputTransport.cancel   rJ   rF   	directionc                   K   |t         j                  k(  rt        |t              r<| j                  t        j                  d       t        |j                        | _        nDt        |t              r4| j                  j                  | j                         d{    d| _        t        | 5  ||       d{    y7 $7 w)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	   rc   r   warningr]   idr
   r(   agent_speak_endr&   
push_framer,   r=   rk   r.   s      r/   rr   z HeyGenOutputTransport.push_frame   s      111%!89>>-NN#GH!$UXXE#:;ll224>>BBB!%g 	222 C2s$   BCC C:C;CCc                 <  K   t         |   ||       d{    t        |t              rG| j                  j                  | j                         d{    | j                  ||       d{    t        |t              r=| j                  j                          d{    | j                  ||       d{    yt        |t              r=| j                  j                          d{    | j                  ||       d{    yy7 7 7 7 s7 [7 *7 w)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_framern   r   r(   	interruptrc   rr   r   start_agent_listeningr   stop_agent_listeningrs   s      r/   ru   z#HeyGenOutputTransport.process_frame   s       g#E9555e./,,((888//%333e56,,44666//%33378,,33555//%333 9 	6836353s{   DD<DDD.D/1D D!D:D;2D-D.DDDDDDDDDreturnc                    K   | j                   j                  t        |j                        | j                         d{    y7 w)zrWrite an audio frame to the HeyGen transport.

        Args:
            frame: The audio frame to write.
        NT)r(   agent_speakbytesrU   rc   )r,   r=   s     r/   write_audio_framez'HeyGenOutputTransport.write_audio_frame
  s8      ll&&uU[['94>>JJJ 	Ks   =AA A)rY   rZ   r[   r\   r   r    r'   r   r1   r9   r   r?   r   rD   r   rI   r   rm   r   rr   ru   r   boolr}   r^   r_   s   @r/   ra   ra      s      *(!4 (%
' ' " ""+ " JXIbIb 3e 3 3&4 4> 46-@ T r0   ra   c                   .    e Zd ZU dZdZeed<   dZeed<   y)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.
    TrM   audio_out_enabledN)rY   rZ   r[   r\   rM   r~   __annotations__r    r0   r/   r   r     s     "d!"t"r0   r   c                        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
Zd ZdefdZdefdZdefdZdefdZdefdZdefdZ x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                 F   t         |   ||       || _        t        |||||t	        | j
                  | j                  | j                              | _        d| _	        d| _
        d| _        | j                  d       | j                  d       | j                  d       y)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.
        )r   r   )on_connectedon_participant_connectedon_participant_disconnected)r   r   r$   r   r   	callbacksNr   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,   r   r   r$   r   r   r   r   r.   s	           r/   r'   zHeyGenTransport.__init__3  s    8 	JKH#+%%!//)-)G)G,0,M,M
 7;8<&*# 	$$^4$$%:;$$%=>r0   c                    K   | j                  d       d{    | j                  r,| j                  j                  t                      d{    yy7 =7 w)z%Handle bot connected to LiveKit room.r   N)_call_event_handlerr   rr   r   r,   s    r/   r   zHeyGenTransport._on_connectedg  sK     &&~666;;++(():)<===  	7=s!   AA6AAAArK   c                    K   t        j                  d| d       |dk7  r| j                  |       d {    y y 7 w)NHeyGen participant z disconnectedheygen)r   debug_on_client_disconnectedrQ   s     r/   r   z,HeyGenTransport._on_participant_disconnectedm  sA     *>*:-HIX%..~>>> &>s   3><>c                    K   t        j                  d| d       |dk7  rJ| j                  |       d {    | j                  r$| j                  j	                  |       d {    y y y 7 67 	w)Nr   z
 connectedr   )r   r   _on_client_connectedr   rR   rQ   s     r/   r   z)HeyGenTransport._on_participant_connectedr  si     *>*:*EFX%++N;;;{{kk77GGG  &;Gs!   3A0A,.A0$A.%A0.A0ry   c                 ~    | j                   s&t        | j                  | j                        | _         | j                   S )zGet the input transport for receiving media and events.

        Returns:
            The HeyGen input transport instance.
        r#   r$   )r   r"   r(   r)   r   s    r/   inputzHeyGenTransport.inputy  s+     {{.dll4<<XDK{{r0   c                 ~    | j                   s&t        | j                  | j                        | _         | j                   S )zGet the output transport for sending media and events.

        Returns:
            The HeyGen output transport instance.
        r   )r   ra   r(   r)   r   s    r/   outputzHeyGenTransport.output  s+     ||0T\\ZDL||r0   participantc                    K   | j                  d|       d{    | j                  r,| j                  j                  t                      d{    yy7 =7 w)zHandle client connected events.r   N)r   r   rr   r   r,   r   s     r/   r   z$HeyGenTransport._on_client_connected  sO     &&'<kJJJ;;++(()=)?@@@  	K@s!   AA6AAAAc                 D   K   | j                  d|       d{    y7 w)z"Handle client disconnected events.r   N)r   r   s     r/   r   z'HeyGenTransport._on_client_disconnected  s     &&'?MMMs     )rY   rZ   r[   r\   r   aiohttpClientSessionr]   r   r   r   r   r   r'   r   r   r   r   r   r   r   r   r   r^   r_   s   @r/   r   r      s    ,  ,~$(%)[_.22?&&2? 2? 	2?
 SM2? c]2? "%(CEV(V"WX2? {+2?h>? ?
Hc H~  Ac AN Nr0   r   ).r\   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"   ra   r   r   r   r0   r/   <module>r      s   
 ( '       c b L N U U < > L\+- \+~A/ AH	#? 	#uNm uNr0   