o
    piP                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZmZmZmZ d dlZd dlmZ d dlmZmZ ejdZG dd deZG d	d
 d
eZG dd dejZG dd dZdS )    N)Path)CallableMappingOptionalUnion)Response)ConnectionError	HTTPErrorzpyannoteai-sdkc                   @      e Zd ZdZdS )PyannoteAIFailedJobz2Raised when a job failed on the pyannoteAI web APIN__name__
__module____qualname____doc__ r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/pyannoteai/sdk/client.pyr   (       r   c                   @   r
   )PyannoteAICanceledJobz8Raised when a job was canceled on the pyannoteAI web APINr   r   r   r   r   r   .   r   r   c                       sB   e Zd ZdZdededef fddZddef fd	d
Z  Z	S )_UploadingCallbackBytesIOaK  BytesIO subclass that calls a callback during the upload process

    Parameters
    ----------
    callback : Callable
        Callback called during upload as `callback(total_in_bytes, completed_in_bytes)`
    total_size : int
        Total size to upload (in bytes)
    initial_bytes : bytes
        Initial bytes to upload
    callback
total_sizeinitial_bytesc                    s"   || _ d| _|| _t | d S )Nr   )r   _completed_size	_callbacksuper__init__)selfr   r   r   	__class__r   r   r   A   s   z"_UploadingCallbackBytesIO.__init__returnc                    s:   t  |}|  jt|7  _| jr| j| j| jd |S )N)total	completed)r   readr   lenr   r   )r   sizedatar   r   r   r$   L   s   z_UploadingCallbackBytesIO.read)r    )
r   r   r   r   r   intbytesr   r$   __classcell__r   r   r   r   r   4   s    r   c                   @   s  e Zd ZdZdZd:dee fddZdefdd	Z	d
edefddZ
d:d
edee defddZedd ZejdeddfddZdedefddZdeeef defddZ		d;deeB eeeeB f B dee dee defddZ							 		d<ded!edB d"edB d#edB d$ed%ed&ed'ed(ed)edB defd*d+Z	 d=ded'edefd,d-Z	.	/							 d>ded0eeef d1ed2ed!edB d"edB d#edB d$ed%ed&ed'edefd3d4Zd?d6ed7edefd8d9ZdS )@Clienta  Official client for pyannoteAI web API

    Parameters
    ----------
    token : str, optional
        pyannoteAI API key created from https://dashboard.pyannote.ai.
        Defaults to using `PYANNOTEAI_API_KEY` environment variable.

    Usage
    -----

    # instantiate client for pyannoteAI web API
    >>> from pyannoteai.sdk import Client
    >>> client = Client(token="{PYANNOTEAI_API_KEY}")

    # upload your audio file to the pyannoteAI web API
    # and store it for a few hours for later re-use.
    >>> media_url = client.upload("/path/to/your/audio.wav")

    # initiate a diarization job on the pyannoteAI web API
    >>> job_id = client.diarize(media_url)

    # retrieve prediction from pyannoteAI web API
    >>> prediction = client.retrieve(job_id)
    zhttps://api.pyannote.ai/v1Ntokenc                 K   s   || _ |ptjdd| _d S )NPYANNOTEAI_API_KEY )r,   osenvirongetapi_key)r   r,   kwargsr   r   r   r   t   s   zClient.__init__responsec                 C   s   |j dkr	td|  dS )z9Raise an exception if the response status code is not 2xxi  z
Failed to authenticate to pyannoteAI API. Please create an API key on https://dashboard.pyannote.ai/ and
provide it either via `PYANNOTEAI_API_KEY` environment variable or with `token` parameter.N)status_coder	   raise_for_status)r   r4   r   r   r   _raise_for_statusx   s
   
	zClient._raise_for_statusrouter!   c                 C   sD   zt j| j | | jd}W n ty   tdw | | |S )a,  Send GET authenticated request to pyannoteAI API

        Parameters
        ----------
        route : str
            API route to send the GET request to.

        Returns
        -------
        response : Response

        Raises
        ------
        ConnectionError
        HTTPError
        )headers
Failed to connect to pyannoteAI web API. Please check your internet connection
or visit https://pyannote.openstatus.dev/ to check the status of the pyannoteAI web API.)requestsr1   API_URL_headersr   r7   )r   r8   r4   r   r   r   _authenticated_get   s   
zClient._authenticated_getjsonc                 C   sF   zt j| j | || jd}W n ty   tdw | | |S )a  Send POST authenticated request to pyannoteAI web API

        Parameters
        ----------
        route : str
            API route to send the GET request to.
        json : dict, optional
            Request body to send with the POST request.

        Returns
        -------
        response : Response

        Raises
        ------
        ConnectionError
        HTTPError
        )r?   r9   r:   )r;   postr<   r=   r   r7   )r   r8   r?   r4   r   r   r   _authenticated_post   s   

zClient._authenticated_postc                 C   s   | j S N)_api_key)r   r   r   r   r2      s   zClient.api_keyr2   c                 C   s<   |st d|| _d| j dt dd| _| d d S )Nz
Failed to authenticate to pyannoteAI web API. Please create an API key on https://dashboard.pyannote.ai/ and
provide it either via `PYANNOTEAI_API_KEY` environment variable or with `token` parameter.zBearer zpyannoteAI-sdk-python/zapplication/json)Authorizationz
User-AgentzContent-Typez/test)
ValueErrorrC   __version__r=   r>   )r   r2   r   r   r   r2      s   
	media_urlc                 C   s   | j dd|id}| d S )aZ  Create a presigned URL to upload audio file to pyannoteAI platform

        Parameters
        ----------
        media_url : str
            Unique identifier used to retrieve the uploaded audio file on the pyannoteAI platform.
            Any combination of letters (a-z, A-Z), digits (0-9), and the characters -./  prefixed
            with media:// is allowed. One would usually use a string akin to a path on filesystem
            (e.g. "media://path/to/audio.wav").

        Returns
        -------
        url : str
            Presigned URL to upload audio file to pyannoteAI platform
        z/media/inputurlr?   )rA   r?   )r   rG   r4   r   r   r   _create_presigned_url   s   zClient._create_presigned_urlfilec                    sb   t  }t|d t fdddD ]}|| qW d   | S 1 s(w   Y  | S )zACompute MD5 hash of a file (used for media_url when not provided)rbc                      s
     dS )Ni   )r$   r   fr   r   <lambda>   s   
 z"Client._hash_md5.<locals>.<lambda>    N)hashlibmd5openiterupdate	hexdigest)r   rK   hash_md5chunkr   rM   r   	_hash_md5   s   
zClient._hash_md5audior   c              	   C   s  d}t |trnd|v r|d }n^d|v rjd}zddl}W n ty'   tdw |d }|d }t|d d	r?|d jdd
}tjddd}|jj	
|j||  |  |j}W d   n1 sdw   Y  ntdtj|}	|du rd| | }t|d}t||	| }
W d   n1 sw   Y  t |tr|dstd| d| |}z(z	tj||
d}W n ty   td| dw W |rtj|rt| n|rtj|rt| w w w |  t d |S )a  Upload audio file to pyannoteAI platform

        Parameters
        ----------
        audio : str or Path or dict
            Path to audio file to be uploaded. Can be a "str" or "Path" instance, or a dict with an
            "audio" key (e.g. {"audio": "/path/to/audio.wav"}).
        media_url : str, optional
            Unique identifier used to retrieve the uploaded audio file on the pyannoteAI platform.
            Any combination of letters {a-z, A-Z}, digits {0-9}, and {-./} characters prefixed
            with 'media://' is allowed. One would usually use a string akin to a path on filesystem
            (e.g. "media://path/to/audio.wav"). Defaults to media://{md5-hash-of-audio-file}.
        callback : Callable, optional
            When provided, `callback` is called during the uploading process with the following signature:
                callback(total=...,     # number of bytes to upload
                         completed=...) # number of bytes uploaded)

        Returns
        -------
        media_url : str
            Same as the input `media_url` parameter when provided,
            or "media://{md5-hash-of-audio-file}" otherwise.
        FrZ   waveformTr   Nz>To process the waveform directly, you need to install `scipy`.sample_ratenumpy)forcez.wav)suffixdeletezRWhen `audio` is a dict, it must provide the path to the audio file in 'audio' key.zmedia://rL   z
Invalid media URI: zp. Any combination of letters {a-z, A-Z}, digits {0-9},
and {-./} characters prefixed with 'media://' is allowed.)r'   z)
Failed to upload audio to presigned URL z|.
Please check your internet connection or visit https://pyannote.openstatus.dev/ to check the status of the pyannoteAI API.aR  
You are using pyannoteAI's temporary storage solution. Your file will be permanently deleted from our servers within 24hs. 
If you are running in production, we highly recommend to use your own storage to reduce network latency and obtain results faster. 
Please check our documentation at https://docs.pyannote.ai/ for more information.)!
isinstancer   scipy.ioImportErrorhasattrr]   tempfileNamedTemporaryFileiowavfilewritenamesqueezeflushrE   r/   pathgetsizerY   rS   r   r$   str
startswithrJ   r;   putr   existsremover6   warningswarn)r   rZ   rG   r   r`   scipyr\   r[   rN   r   r'   presigned_urlr4   r   r   r   upload   st    




zClient.uploadFprecision-2num_speakersmin_speakersmax_speakers
confidenceturn_level_confidence	exclusivemodeltranscriptiontranscription_configc              
   K   sP   |||||||||	d	}|
dur|
|d< | | | jd|d}| }|d S )a,  Initiate a diarization job on the pyannoteAI web API

        Parameters
        ----------
        media_url : str
            media://{...} URL created with the `upload` method or
            any other public URL pointing to an audio file.
        num_speakers : int, optional
            Force number of speakers to diarize. If not provided, the
            number of speakers will be determined automatically.
        min_speakers : int, optional
            Minimum number of speakers.
        max_speakers : int, optional
            Maximum number of speakers.
        confidence : bool, optional
            Enable confidence scores.
        turn_level_confidence: bool, optional
            Enable turn-based confidence scores.
        exclusive: bool, optional
            Enable exclusive speaker diarization.
        model : str, optional
            Defaults to "precision-2"
        transcription : bool, optional
            Enable STT orchestration.
        transcription_config : dict, optional
            STT configuration parameters, including model selection.
        **kwargs : optional
            Extra arguments to send in the body of the request.

        Returns
        -------
        job_id: str

        Raises
        ------
        HTTPError
            If something else went wrong
        )	rH   r   numSpeakersminSpeakersmaxSpeakersr}   turnLevelConfidencer   r   NtranscriptionConfigz/diarizerI   jobIdrU   rA   r?   )r   rG   rz   r{   r|   r}   r~   r   r   r   r   r3   r?   r4   r'   r   r   r   diarizek  s    6
zClient.diarizec                 K   s2   ||d}| | | jd|d}| }|d S )a)  Initiate a voiceprint job on the pyannoteAI web API

        Parameters
        ----------
        media_url : str
            media://{...} URL created with the `upload` method or
            any other public URL pointing to an audio file.
        model : str, optional
            Defaults to "precision-2".
        **kwargs : optional
            Extra arguments to send in the body of the request.

        Returns
        -------
        job_id: str

        Raises
        ------
        HTTPError
            If something else went wrong
        )rH   r   z/voiceprintrI   r   r   )r   rG   r   r3   r?   r4   r'   r   r   r   
voiceprint  s
   

zClient.voiceprintT        voiceprintsexclusive_matchingmatching_thresholdc                 K   sV   |||||||	|
dd |  D ||dd
}|| | jd|d}| }|d S )a  Initiate an identification job on the pyannoteAI web API

        Parameters
        ----------
        media_url : str
            media://{...} URL created with the `upload` method or
            any other public URL pointing to an audio file.
        voiceprints : dict
            Voiceprints.
        exclusive_matching : bool, optional
            Prevent multiple speakers from being matched to the same voiceprint.
            Defaults to True.
        matching_threshold : float, optional
            Prevent matching if confidence score is below this threshold.
            Value is between 0 and 100. Default is 0, meaning all voiceprints are matched.
        num_speakers : int, optional
            Force number of speakers to diarize. If not provided, the
            number of speakers will be determined automatically.
        min_speakers : int, optional
            Minimum number of speakers.
        max_speakers : int, optional
            Maximum number of speakers.
        confidence : bool, optional
            Enable confidence scores.
        turn_level_confidence: bool, optional
            Enable turn-based confidence scores.
        exclusive: bool, optional
            Enable exclusive speaker diarization.
        model : str, optional
            Defaults to "precision-2"
        **kwargs : optional
            Extra arguments to send in the body of the request.

        Returns
        -------
        job_id: str

        Raises
        ------
        HTTPError
            If something else went wrong
        c                 S   s   g | ]	\}}||d qS ))labelr   r   ).0speakerr   r   r   r   
<listcomp>  s    z#Client.identify.<locals>.<listcomp>)r   	threshold)
rH   r   r   r   r   r}   r   r   r   matchingz	/identifyrI   r   )itemsrU   rA   r?   )r   rG   r   r   r   rz   r{   r|   r}   r~   r   r   r3   r?   r4   r'   r   r   r   identify  s&   ;
zClient.identify
   job_idevery_secondsc                 C   s   d}	 |  d|  }|d }|dvrt| q	 |dkr0|dt dd	}t|||d
krD|dt dd	}t||t	d |S )a  Retrieve output of a job (once completed) from pyannoteAI web API

        Parameters
        ----------
        job_id : str
            Job ID.

        Returns
        -------
        job_output : dict
            Job output

        Raises
        ------
        PyannoteAIFailedJob
            If the job failed
        PyannoteAICanceledJob
            If the job was canceled
        HTTPError
            If something else went wrong
        NTz/jobs/status)	succeededcanceledfailedr   outputerrorzPlease contact support.r   a  
You are using periodic polling to retrieve results. 
If you are running in production, we highly recommend to setup a webhook server to obtain results faster, as soon as they are available. 
Please check our documentation at https://docs.pyannote.ai/ for more information.)
r>   r?   timesleepr1   dictr   r   rt   ru   )r   r   r   
job_statusjobr   r   r   r   retrieve-  s    



zClient.retrieverB   )NN)	NNNFFFry   FN)ry   )	Tr   NNNFFFry   )r   )r   r   r   r   r<   r   ro   r   r   r7   r>   r   rA   propertyr2   setterrJ   r   r   rY   r   rx   r(   boolr   r   floatr   r   r   r   r   r   r+   W   s    #

q	

N
(
	

Sr+   )rQ   importlib.metadata	importlibrg   r/   re   r   rt   pathlibr   typingr   r   r   r   r;   r   requests.exceptionsr   r	   metadataversionrF   	Exceptionr   r   BytesIOr   r+   r   r   r   r   <module>   s"   #