
    qi/:                     (   d Z ddlZddlZddlmZmZ ddlZddlm	Z	 ddl
mZmZmZ ddlmZmZmZ ddlmZmZ 	 ddlZ G d de      Z G d de      Zy# e$ r7Z e	j0                  de         e	j0                  d	        ed
e       dZ[ww xY w)a  Krisp turn analyzer for end-of-turn detection using Krisp VIVA SDK.

This module provides a turn analyzer implementation using Krisp's turn detection
(Tt) API to determine when a user has finished speaking in a conversation.

Note: This analyzer uses a different model than KrispVivaFilter. The model path
can be specified via the KRISP_VIVA_TURN_MODEL_PATH environment variable or
passed directly to the constructor.
    N)OptionalTuple)logger)KrispVivaSDKManagerint_to_krisp_frame_durationint_to_krisp_sample_rate)BaseTurnAnalyzerBaseTurnParamsEndOfTurnState)MetricsDataTurnMetricsDatazException: z?In order to use KrispVivaTurn, you need to install krisp_audio.zMissing module: c                   .    e Zd ZU dZdZeed<   dZeed<   y)KrispTurnParamsae  Configuration parameters for Krisp turn analysis.

    Parameters:
        threshold: Probability threshold for turn completion (0.0 to 1.0).
            Higher values require more confidence before marking turn as complete.
        frame_duration_ms: Frame duration in milliseconds for turn detection.
            Supported values: 10, 15, 20, 30, 32.
    g      ?	threshold   frame_duration_msN)	__name__
__module____qualname____doc__r   float__annotations__r   int     T/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/audio/turn/krisp_viva_turn.pyr   r   (   s     Iusr   r   c                       e Zd ZdZddddddee   dee   dee   ded	df
 fd
Zd Z	defdZ
def fdZed	efd       Zed	ee   fd       Zed	efd       Zed	efd       Zdeded	efdZd	eeee   f   fdZd Z xZS )KrispVivaTurnzTurn analyzer using Krisp VIVA SDK for end-of-turn detection.

    Uses Krisp's turn detection (Tt) API to determine when a user has finished
    speaking. This analyzer requires a valid Krisp model file to operate.
    N )
model_pathsample_rateparamsapi_keyr    r!   r"   r#   returnc                $   t         |   |       	 t        j                  |       d| _        	 |xs t        j                  d      | _	        | j                  s t        j                  d       t        d	      | j                  j                  d
      st        d      t        j                  j                  | j                        st!        d| j                         |xs
 t#               | _        d| _        d| _        d| _        t-               | _        d| _        d| _        g | _        t6        j8                  | _        d| _        d| _        d| _         |r|nd}	 | jC                  |      | _        y# t
        $ r}d| _        t        d|       d}~ww xY w# t
        $ r5}t        j                  d| d       d| _        t        d|       |d}~ww xY w# t
        $ r) | j                  rt        jD                          d| _         w xY w)ah  Initialize the Krisp turn analyzer.

        Args:
            model_path: Path to the Krisp turn detection model file (.kef extension).
                If None, uses KRISP_VIVA_TURN_MODEL_PATH environment variable.
            sample_rate: Optional initial sample rate for audio processing.
                If provided, this will be used as the fixed sample rate.
            params: Configuration parameters for turn analysis behavior.
            api_key: Krisp SDK API key. If empty, falls back to
                the KRISP_VIVA_API_KEY environment variable.

        Raises:
            ValueError: If model_path is not provided and KRISP_VIVA_TURN_MODEL_PATH is not set.
            Exception: If model file doesn't have .kef extension.
            FileNotFoundError: If model file doesn't exist.
            RuntimeError: If Krisp SDK initialization fails.
        )r!   )r#   TFz Failed to initialize Krisp SDK: NKRISP_VIVA_TURN_MODEL_PATHzEModel path is not provided and KRISP_VIVA_TURN_MODEL_PATH is not set.z.Model path for KrispVivaTurn must be provided.z.kefz%Model is expected with .kef extensionzModel file not found: i>  )Failed to create turn detection session: exc_info)#super__init__r   acquire_sdk_acquired	ExceptionRuntimeErrorosgetenv_model_pathr   error
ValueErrorendswithpathisfileFileNotFoundErrorr   _params_tt_session_preload_tt_session_samples_per_frame	bytearray_audio_buffer_speech_triggered_last_probability_frame_probabilitiesr   
INCOMPLETE_last_state_speech_stopped_time_e2e_processing_time_ms_last_metrics_create_tt_sessionrelease)selfr    r!   r"   r#   epreload_sample_rate	__class__s          r   r+   zKrispVivaTurn.__init__=   s   2 	[1	G''8!%D
-	)TRYY7S-TD##[ !!QRR##,,V4 GHH77>>$"2"23'*@AQAQ@R(STT!6_%6DL#D'+D$&*D#!*D &+D"%)D"(*D%-88D9=D%<@D(<@D 2=+%[+/+B+BCV+W(M  	G!&D!A!EFF	GN  [HLW[\+/("%Nqc#RSYZZ[
  	!!#++-%*"	sA   E6 D-G F 6	F?FF	G%0GGG 2Hc                 :  K   | j                   r[	 t        | d      r| j                  d| _        t        | d      r| j                  d| _        t	        j
                          d| _         yy# t        $ r$}t        j                  d| d       Y d}~yd}~ww xY ww)z1Release SDK reference when analyzer is destroyed.r:   Nr;   FzError in __del__: Tr(   )	r-   hasattrr:   r;   r   rH   r.   r   r3   )rI   rJ   s     r   cleanupzKrispVivaTurn.cleanup   s     
F4/D4D4D4P'+D$4!67D<T<T<`/3D,#++-%*"   F1!5EEFs/   BAA+ )B+	B4BBBBc                    	 t        j                         }| j                  |_        t        j                         }t        |      |_        t        | j                  j                        |_
        ||_        t        || j                  j                  z  dz        | _        t         j                  j                  |      }|S # t         $ r.}t#        j$                  d| d       t'        d|       |d}~ww xY w)aV  Create a turn detection session with the specified sample rate.

        Args:
            sample_rate: Sample rate for the session

        Returns:
            krisp_audio.TtFloat instance

        Raises:
            ValueError: If sample rate or frame duration is not supported
            RuntimeError: If session creation fails
          z/Failed to create Krisp turn detection session: Tr(   N)krisp_audio	ModelInfor2   r6   TtSessionConfigr   inputSampleRater   r9   r   inputFrameDuration	modelInfor   r<   TtFloatcreater.   r   r3   r/   )rI   r!   
model_infott_cfgtt_instancerJ   s         r   rG   z KrispVivaTurn._create_tt_session   s    	]$..0J"..JO 002F%=k%JF"(CDLLDbDb(cF%)F '*;9W9W+W[_*_&`D#%--44V<K 	]LLJ1#NY]^!PQRPSTU[\\	]s   B>C 	C8
)C33C8c                    | j                   |k(  ryt        | 	  |       	 | j                  | j                         | _        | j                          y# t        $ r+}t        j                  d| d       d| _        Y d}~yd}~ww xY w)zSet the sample rate and create/update the turn detection session.

        Args:
            sample_rate: The sample rate to set.
        Nr'   Tr(   )	_sample_rater*   set_sample_raterG   r:   clearr.   r   r3   )rI   r!   rJ   rL   s      r   r_   zKrispVivaTurn.set_sample_rate   s|     +,	$#66t7H7HIDJJL 	$LLDQCHSWX#D	$s   0A 	B!BBc                     | j                   S )zGet all probabilities from the last append_audio call.

        Returns:
            List of probability values for each frame processed in the last append_audio call.
        )rA   rI   s    r   frame_probabilitiesz!KrispVivaTurn.frame_probabilities   s     (((r   c                     | j                   S )zGet the last turn probability value computed.

        Returns:
            Last probability value, or None if no frames have been processed yet.
        )r@   rb   s    r   last_probabilityzKrispVivaTurn.last_probability        %%%r   c                     | j                   S )zCheck if speech has been detected and triggered analysis.

        Returns:
            True if speech has been detected and turn analysis is active.
        )r?   rb   s    r   speech_triggeredzKrispVivaTurn.speech_triggered   rf   r   c                     | j                   S )zGet the current turn analyzer parameters.

        Returns:
            Current turn analyzer configuration parameters.
        )r9   rb   s    r   r"   zKrispVivaTurn.params   s     ||r   buffer	is_speechc                    | j                   :t        j                  d       t        j                  | _        t        j                  S | j                  :t        j                  d       t        j                  | _        t        j                  S 	 | j                  j                  |       g | _	        t        | j                        dz  }|| j                  z  }|dk(  r%t        j                  | _        t        j                  S || j                  z  }|dz  }t        | j                  d|       }| j                  |d | _        t        j                  |t        j                        }|j                  t        j                         dz  }	|	j#                  d| j                        }
t        j                  }|
D ]m  }|r7| j$                  st        j&                  d	       d| _        d
| _        d| _        n1| j$                  r%| j*                  t-        j.                         | _        | j                   j1                  |j3                               }|dk  r|| _        | j                  j7                  |       | j$                  s|| j8                  j:                  k\  s| j*                  \t-        j.                         | j*                  z
  dz  | _        t=        dd
|| j(                        | _        t        j@                  d       t        jB                  }| jE                           n || _        |S # tF        $ r=}t        jH                  d| d
       t        j                  }|| _        |cY d}~S d}~ww xY w)a  Append audio data for turn analysis.

        Args:
            buffer: Raw audio data bytes to append for analysis.
            is_speech: Whether the audio buffer contains detected speech.

        Returns:
            Current end-of-turn state after processing the audio.
        Nz<Turn detection session not initialized, returning INCOMPLETEz7Samples per frame not initialized, returning INCOMPLETE   r   )dtypeg      @z&Speech detected, turn analysis startedTrQ   r   )	processoris_completeprobabilitye2e_processing_time_mszKrisp turn completez#Error during Krisp turn detection: r(   )%r:   r   warningr   rB   rC   r<   r>   extendrA   lenbytesnp
frombufferint16astypefloat32reshaper?   tracerE   rD   timeperf_counterprocesstolistr@   appendr9   r   r   rF   debugCOMPLETEr`   r.   r3   )rI   rj   rk   total_samplesnum_complete_framescomplete_samples_countbytes_to_processaudio_to_processaudio_int16audio_float32framesstateframeprobrJ   error_states                   r   append_audiozKrispVivaTurn.append_audio   s    #NNYZ-88D!,,,""*NNTU-88D!,,,V	%%f- )+D% 2 23q8M"/43J3J"J"a'#1#<#< %000%84;R;R%R"59$T%7%78I9I%JK!%!3!34D4E!FD--(8IK'..rzz:WDM"**2t/F/FGF"--E   .11%MN7;4-1D*04D- --$2K2K2S484E4E4G1
 ''//? !8 *.&))006
 ))ddll6L6L.L00< --/$2K2KK 8!4 .=&5(,(,373O3O	.* ':<*33EJJL].b  %DL 	LL>qcBTR(33K*D		s3   A2L0 F L0 L0 BL0 0	M692M1+M61M6c                 L   K   | j                   }d| _         | j                  |fS w)zAnalyze the current audio state to determine if turn has ended.

        Returns:
            Tuple containing the end-of-turn state and optional metrics data.
            Returns the last state determined by append_audio().
        N)rF   rC   )rI   metricss     r   analyze_end_of_turnz!KrispVivaTurn.analyze_end_of_turn_  s,      $$!((s   "$c                 ~    d| _         | j                  j                          t        j                  | _        d| _        y)z-Reset the turn analyzer to its initial state.FN)r?   r>   r`   r   rB   rC   rD   rb   s    r   r`   zKrispVivaTurn.clearl  s2    !&  ")44$(!r   )r   r   r   r   r   strr   r   r+   rO   rG   r_   propertylistrc   r   re   boolrh   r"   rw   r   r   r   r   r   r`   __classcell__)rL   s   @r   r   r   6   s0    %)%),0P SMP c]	P
 )P P 
PdF]c ]>$3 $$ )T ) ) &(5/ & & &$ & &   j5 jT jn jX)5+AV1V+W ))r   r   )r   r0   r   typingr   r   numpyrx   logurur   pipecat.audio.krisp_instancer   r   r   %pipecat.audio.turn.base_turn_analyzerr	   r
   r   pipecat.metrics.metricsr   r   rR   ModuleNotFoundErrorrJ   r3   r.   r   r   r   r   r   <module>r      s    
  "   
 c b @, n  {)$ {))  ,FLL;qc"#FLLRS
&qc*
++,s   A B2BB