U
    ARdg9                  	   @   s  U d dl Z d dlZd dlmZmZmZmZmZ d dlm	Z	m
Z
 d dlmZ d dlZd dlmZmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ erd dlmZ d dlmZ d dl m!Z! ee"e#e j$e j%e j&ddf Z'e
e(d< G dd dZ)e*dZ+e	e(d< e"ee" dddZ,e"eeef e'e"ddddZ-d*e"ee'e"e.ddddZ/dee#e.f ddd Z0de.e#d!d"d#Z1e'ee. e'd!d$d%Z2d+e"ee'e"e.ee. dd'd(d)Z3dS ),    N)TYPE_CHECKINGOptionalTupleUnioncast)Final	TypeAlias)url)runtime	type_util)StreamlitAPIException)Audio)Video)caching)gather_metrics)Any)typing)DeltaGeneratornpt.NDArray[Any]	MediaDatac                	   @   sf   e Zd Zeddddeeeee dddd	Zed
deeeddddZ	e
ddddZdS )
MediaMixinaudio	audio/wavr   N)sample_rater   )dataformat
start_timer   returnc                C   sf   t  }| j }t|d}|r0|dkr0td|sF|dk	rFtd t|||||| | j	d|S )a  Display an audio player.

        Parameters
        ----------
        data : str, bytes, BytesIO, numpy.ndarray, or file opened with
                io.open().
            Raw audio data, filename, or a URL pointing to the file to load.
            Raw data formats must include all necessary file headers to match the file
            format specified via ``format``.
            If ``data`` is a numpy array, it must either be a 1D array of the waveform
            or a 2D array of shape ``(num_channels, num_samples)`` with waveforms
            for all channels. See the default channel order at
            http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
        format : str
            The mime type for the audio file. Defaults to 'audio/wav'.
            See https://tools.ietf.org/html/rfc4281 for more info.
        start_time: int
            The time from which this element should start playing.
        sample_rate: int or None
            The sample rate of the audio data in samples per second. Only required if
            ``data`` is a numpy array.

        Example
        -------
        >>> import streamlit as st
        >>> import numpy as np
        >>>
        >>> audio_file = open('myaudio.ogg', 'rb')
        >>> audio_bytes = audio_file.read()
        >>>
        >>> st.audio(audio_bytes, format='audio/ogg')
        >>>
        >>> sample_rate = 44100  # 44100 samples per second
        >>> seconds = 2  # Note duration of 2 seconds
        >>> frequency_la = 440  # Our played note will be 440 Hz
        >>> # Generate array with seconds*sample_rate steps, ranging between 0 and seconds
        >>> t = np.linspace(0, seconds, seconds * sample_rate, False)
        >>> # Generate a 440 Hz sine wave
        >>> note_la = np.sin(frequency_la * t * 2 * np.pi)
        >>>
        >>> st.audio(note_la, sample_rate=sample_rate)

        .. output::
           https://doc-audio.streamlitapp.com/
           height: 865px

        numpy.ndarrayNz=`sample_rate` must be specified when `data` is a numpy array.zGWarning: `sample_rate` will be ignored since data is not a numpy array.r   )

AudioProtodg_get_delta_path_strr   is_typer   stwarningmarshall_audio_enqueue)selfr   r   r   r   Zaudio_protocoordinatesZis_data_numpy_array r)   </tmp/pip-unpacked-wheel-b9et7o5g/streamlit/elements/media.pyr   +   s    8
zMediaMixin.audiovideo	video/mp4)r   r   r   r   c                 C   s.   t  }| j }t||||| | jd|S )a  Display a video player.

        Parameters
        ----------
        data : str, bytes, BytesIO, numpy.ndarray, or file opened with
                io.open().
            Raw video data, filename, or URL pointing to a video to load.
            Includes support for YouTube URLs.
            Numpy arrays and raw data formats must include all necessary file
            headers to match specified file format.
        format : str
            The mime type for the video file. Defaults to 'video/mp4'.
            See https://tools.ietf.org/html/rfc4281 for more info.
        start_time: int
            The time from which this element should start playing.

        Example
        -------
        >>> import streamlit as st
        >>>
        >>> video_file = open('myvideo.mp4', 'rb')
        >>> video_bytes = video_file.read()
        >>>
        >>> st.video(video_bytes)

        .. output::
           https://doc-video.streamlitapp.com/
           height: 700px

        .. note::
           Some videos may not display if they are encoded using MP4V (which is an export option in OpenCV), as this codec is
           not widely supported by browsers. Converting your video to H.264 will allow the video to be displayed in Streamlit.
           See this `StackOverflow post <https://stackoverflow.com/a/49535220/2394542>`_ or this
           `Streamlit forum post <https://discuss.streamlit.io/t/st-video-doesnt-show-opencv-generated-mp4/3193/2>`_
           for more information.

        r+   )
VideoProtor    r!   marshall_videor&   )r'   r   r   r   Zvideo_protor(   r)   r)   r*   r+   u   s    ,
zMediaMixin.video)r   c                 C   s
   t d| S )zGet our DeltaGenerator.r   )r   )r'   r)   r)   r*   r       s    zMediaMixin.dg)r   r   )r,   r   )__name__
__module____qualname__r   r   strintr   r   r+   propertyr    r)   r)   r)   r*   r   *   s.     I  0r   zuhttp(?:s?):\/\/(?:www\.)?youtu(?:be\.com|\.be)\/(?P<watch>(watch\?v=)|embed\/)?(?P<code>[\w\-\_]*)(&(amp;)?[\w\?=]*)?
YOUTUBE_RE)r	   r   c                 C   s"   t | }|rdjf | S dS )a  Return whether URL is any kind of YouTube embed or watch link.  If so,
    reshape URL into an embed link suitable for use in an iframe.

    If not a YouTube URL, return None.

    Parameters
    ----------
        url : str

    Example
    -------
    >>> print(_reshape_youtube_url('https://youtu.be/_T8LGqJtuGc'))

    .. output::
        https://www.youtube.com/embed/_T8LGqJtuGc
    z$https://www.youtube.com/embed/{code}N)r5   matchr   	groupdict)r	   r6   r)   r)   r*   _reshape_youtube_url   s    
r8   )r(   protor   mimetyper   c                 C   s   |dkrdS t |ttfr |}nt |tjr@|d | }nbt |tjsXt |tjr||d |	 }|dkrvdS |}n&t
|dr| }ntdt| t rt j||| }t|||  nd}||_dS )a  Fill audio or video proto based on contents of data.

    Given a string, check if it's a url; if so, send it out without modification.
    Otherwise assume strings are filenames and let any OS errors raise.

    Load data either from file or through bytes-processing methods into a
    MediaFile object.  Pack proto with generated Tornado-based URL.

    (When running in "raw" mode, we won't actually load data into the
    MediaFileManager, and we'll return an empty URL.)
    Nr   r   zInvalid binary data format: %s )
isinstancer2   bytesioBytesIOseekgetvalue	RawIOBaseBufferedReaderreadr   r"   tobytesRuntimeErrortyper
   existsZget_instanceZmedia_file_mgraddr   Zsave_media_datar	   )r(   r9   r   r:   Zdata_or_filename	read_dataZfile_urlr)   r)   r*   _marshall_av_media   s2    




  rK   r,   )r(   r9   r   r:   r   r   c                 C   sZ   ||_ tjj|_t|trHt|rHt|}|r@||_tjj	|_qV||_nt
| ||| dS )a  Marshalls a video proto, using url processors as needed.

    Parameters
    ----------
    coordinates : str
    proto : the proto to fill. Must have a string field called "data".
    data : str, bytes, BytesIO, numpy.ndarray, or file opened with
           io.open().
        Raw video data or a string with a URL pointing to the video
        to load. Includes support for YouTube URLs.
        If passing the raw data, this must include headers and any other
        bytes required in the actual file.
    mimetype : str
        The mime type for the video file. Defaults to 'video/mp4'.
        See https://tools.ietf.org/html/rfc4281 for more info.
    start_time : int
        The time from which this element should start playing. (default: 0)
    N)r   r-   TypeZNATIVErG   r<   r2   r	   r8   ZYOUTUBE_IFRAMErK   )r(   r9   r   r:   r   Zyoutube_urlr)   r)   r*   r.     s    
r.   )r   r   c                 C   s   ddl }|j| td} t| jdkr*d}n,t| jdkrN| jd }| j } ntd| jdkrt| 	|j
 |fS ||| }| | d }|	|j
}| |fS )a  Validates and normalizes numpy array data.
    We validate numpy array shape (should be 1d or 2d)
    We normalize input data to int16 [-32768, 32767] range.

    Parameters
    ----------
    data : numpy array
        numpy array to be validated and normalized

    Returns
    -------
    Tuple of (bytes, int)
        (bytes, nchan)
        where
         - bytes : bytes of normalized numpy array converted to int16
         - nchan : number of channels for audio signal. 1 for mono, or 2 for stereo.
    r   N)Zdtype      z1Numpy array audio input must be a 1D or 2D array.i  )numpyarrayfloatlenshapeTZravelr   sizeZastypeZint16rE   maxabs)r   npnchanZmax_abs_valueZnp_arrayZscaled_datar)   r)   r*   _validate_and_normalize0  s    

rZ   )r   r   r   c                 C   s   ddl }t| \}}t p}|j|ddV}|| || |d |dd |	| |
 W  5 Q R  W  5 Q R  S Q R X W 5 Q R X dS )z
    Transform a numpy array to a PCM bytestring
    We use code from IPython display module to convert numpy array to wave bytes
    https://github.com/ipython/ipython/blob/1015c392f3d50cf4ff3e9f29beede8c1abfdcb2a/IPython/lib/display.py#L146
    r   Nwb)moderN   NONE)waverZ   r>   r?   openZsetnchannelsZsetframerateZsetsampwidthZsetcomptypeZwriteframesrA   )r   r   r^   ZscaledrY   fpZwaveobjr)   r)   r*   	_make_wava  s    



ra   c                 C   s(   t | dr$|dk	r$ttd| |} | S )z:Convert data to wav bytes if the data type is numpy array.r   Nr   )r   r"   ra   r   )r   r   r)   r)   r*   _maybe_convert_to_wav_bytesv  s    rb   r   )r(   r9   r   r:   r   r   r   c                 C   s<   ||_ t|tr t|r ||_nt||}t| ||| dS )a3  Marshalls an audio proto, using data and url processors as needed.

    Parameters
    ----------
    coordinates : str
    proto : The proto to fill. Must have a string field called "url".
    data : str, bytes, BytesIO, numpy.ndarray, or file opened with
            io.open()
        Raw audio data or a string with a URL pointing to the file to load.
        If passing the raw data, this must include headers and any other bytes
        required in the actual file.
    mimetype : str
        The mime type for the audio file. Defaults to "audio/wav".
        See https://tools.ietf.org/html/rfc4281 for more info.
    start_time : int
        The time from which this element should start playing. (default: 0)
    sample_rate: int or None
        Optional param to provide sample_rate in case of numpy array
    N)r   r<   r2   r	   rb   rK   )r(   r9   r   r:   r   r   r)   r)   r*   r%     s
    
r%   )r,   r   )r   r   N)4r>   rer   r   r   r   r   r   Ztyping_extensionsr   r   Z
validatorsr	   Z	streamlitr#   r
   r   Zstreamlit.errorsr   Zstreamlit.proto.Audio_pb2r   r   Zstreamlit.proto.Video_pb2r   r-   Zstreamlit.runtimer   Zstreamlit.runtime.metrics_utilr   r   rO   ZnptZstreamlit.delta_generatorr   r2   r=   r?   rB   rC   r   __annotations__r   compiler5   r8   rK   r3   r.   rZ   ra   rb   r%   r)   r)   r)   r*   <module>   sv     

:  +1    