3
‡ŒðiV,  ã               @   s8  d dl mZ ddlmZmZ ddlmZmZ d dlm	Z	 d dl
mZ d dlZd dlZd dlZd dlZddlmZmZ dd	lmZmZmZmZmZmZ G d
d„ deƒZdd„ Zd&dd„Zdd„ Zdd„ Zdd„ Z dd„ Z!dd„ Z"dd„ Z#eƒ d'dd„ƒZ$eƒ d(d d!„ƒZ%eƒ d)d"d#„ƒZ&eƒ d*d$d%„ƒZ'd!ddd%d#gZ(dS )+é    )Úunicode_literalsé   )Úget_outgoing_edgesÚ	topo_sort)Ú
basestringÚconvert_kwargs_to_cmd_line_args)Ústr)ÚreduceN)ÚinputÚoutput)Úget_stream_spec_nodesÚ
FilterNodeÚ
GlobalNodeÚ	InputNodeÚ
OutputNodeÚoutput_operatorc                   s   e Zd Z‡ fdd„Z‡  ZS )ÚErrorc                s&   t t| ƒjdj|ƒƒ || _|| _d S )Nz'{} error (see stderr output for detail))Úsuperr   Ú__init__ÚformatÚstdoutÚstderr)ÚselfÚcmdr   r   )Ú	__class__© ú4/tmp/pip-build-6m2fasei/ffmpeg-python/ffmpeg/_run.pyr      s    
zError.__init__)Ú__name__Ú
__module__Ú__qualname__r   Ú__classcell__r   r   )r   r   r      s   r   c             C   sš   | j tjkrˆtj| jƒ}|jdƒ}|jdd ƒ}|jdd ƒ}g }|rN|d|g7 }|rn|ddj|d |d ƒg7 }|t|ƒ7 }|d	|g7 }ntd
j| ƒƒ‚|S )NÚfilenamer   Ú
video_sizez-fz-video_sizez{}x{}r   r   z-izUnsupported input node: {})	Únamer
   r   ÚcopyÚkwargsÚpopr   r   Ú
ValueError)Z
input_noder%   r!   Úfmtr"   Úargsr   r   r   Ú_get_input_args   s    
r*   Fc             C   sN   | |j |jf }|jsd}ndj|jƒ}|r>t|j tƒr>d}nd}|j||ƒS )NÚ z:{}z{}{}z[{}{}])Úupstream_nodeÚupstream_labelZupstream_selectorr   Ú
isinstancer   )Ústream_name_mapÚedgeÚis_final_argÚprefixÚsuffixr(   r   r   r   Ú_format_input_stream_name1   s    r4   c             C   s   dj | |j|jf ƒS )Nz[{}])r   r,   r-   )r/   r0   r   r   r   Ú_format_output_stream_name@   s    r5   c                sX   | j }t| |ƒ}‡ fdd„|D ƒ}‡ fdd„|D ƒ}djdj|ƒ| j|ƒdj|ƒƒ}|S )Nc                s   g | ]}t ˆ |ƒ‘qS r   )r4   )Ú.0r0   )r/   r   r   ú
<listcomp>H   s    z$_get_filter_spec.<locals>.<listcomp>c                s   g | ]}t ˆ |ƒ‘qS r   )r5   )r6   r0   )r/   r   r   r7   K   s    z{}{}{}r+   )Úincoming_edgesr   r   ÚjoinZ_get_filter)ÚnodeÚoutgoing_edge_mapr/   r8   Zoutgoing_edgesÚinputsÚoutputsZfilter_specr   )r/   r   Ú_get_filter_specD   s    
r>   c             C   sn   d}xd| D ]\}|| }xNt |jƒ ƒD ]>\}}t|ƒdkrHtdj||ƒƒ‚dj|ƒ|||f< |d7 }q$W q
W d S )Nr   r   zpEncountered {} with multiple outgoing edges with same upstream label {!r}; a `split` filter is probably requiredzs{})ÚsortedÚitemsÚlenr'   r   )Úfilter_nodesÚoutgoing_edge_mapsr/   Zstream_countr,   r;   r-   Zdownstreamsr   r   r   Ú_allocate_filter_stream_namesS   s    

rD   c                s*   t | ˆ ˆƒ ‡ ‡fdd„| D ƒ}dj|ƒS )Nc                s   g | ]}t |ˆ | ˆƒ‘qS r   )r>   )r6   r:   )rC   r/   r   r   r7   g   s   z#_get_filter_arg.<locals>.<listcomp>ú;)rD   r9   )rB   rC   r/   Zfilter_specsr   )rC   r/   r   Ú_get_filter_argd   s    rF   c             C   s
   t | jƒS )N)Úlistr)   )r:   r   r   r   Ú_get_global_argsm   s    rH   c             C   sP  | j tjkrtdj| ƒƒ‚g }t| jƒdkr:tdj| ƒƒ‚x>| jD ]4}t||dd�}|dksjt| jƒdkrB|d|g7 }qBW tj| j	ƒ}|j
d	ƒ}d
|krª|d|j
d
ƒg7 }d|krÈ|dt|j
dƒƒg7 }d|kræ|dt|j
dƒƒg7 }d|k�r6|j
dƒ}t|tƒ �r*t|tjƒ�r*dj|d |d ƒ}|d|g7 }|t|ƒ7 }||g7 }|S )NzUnsupported output node: {}r   z$Output node {} has no mapped streamsT)r1   Ú0r   z-mapr!   r   z-fZvideo_bitratez-b:vZaudio_bitratez-b:ar"   z{}x{}z-video_size)r#   r   r   r'   r   rA   r8   r4   r$   r%   r&   r   r.   r   ÚcollectionsÚIterabler   )r:   r/   r)   r0   Ústream_namer%   r!   r"   r   r   r   Ú_get_output_argsq   s6    



rM   c                sä   t | ƒ}g }t|ƒ\}}dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}	dd„ t|ƒD ƒ‰ t|	|ˆ ƒ}
|ttjdd„ |D ƒƒ7 }|
r˜|d	|
g7 }|ttj‡ fd
d„|D ƒƒ7 }|ttjdd„ |D ƒg ƒ7 }|rà|dg7 }|S )z4Build command-line arguments to be passed to ffmpeg.c             S   s   g | ]}t |tƒr|‘qS r   )r.   r   )r6   r:   r   r   r   r7   œ   s    zget_args.<locals>.<listcomp>c             S   s   g | ]}t |tƒr|‘qS r   )r.   r   )r6   r:   r   r   r   r7   �   s    c             S   s   g | ]}t |tƒr|‘qS r   )r.   r   )r6   r:   r   r   r   r7   ž   s    c             S   s   g | ]}t |tƒr|‘qS r   )r.   r   )r6   r:   r   r   r   r7   Ÿ   s    c             S   s   i | ]\}}t |ƒ|d f“qS )N)r   )r6   Úir:   r   r   r   ú
<dictcomp>    s    zget_args.<locals>.<dictcomp>c             S   s   g | ]}t |ƒ‘qS r   )r*   )r6   r:   r   r   r   r7   ¢   s    z-filter_complexc                s   g | ]}t |ˆ ƒ‘qS r   )rM   )r6   r:   )r/   r   r   r7   ¦   s    c             S   s   g | ]}t |ƒ‘qS r   )rH   )r6   r:   r   r   r   r7   ¨   s    z-y)r   r   Ú	enumeraterF   r	   ÚoperatorÚadd)Ústream_specÚoverwrite_outputÚnodesr)   Zsorted_nodesrC   Zinput_nodesZoutput_nodesZglobal_nodesrB   Z
filter_argr   )r/   r   Úget_args•   s$    
rV   Úffmpegc             C   s6   t |tƒr|g}nt|ƒtkr&t|ƒ}|t| |d� S )a�  Build command-line for invoking ffmpeg.

    The :meth:`run` function uses this to build the commnad line
    arguments and should work in most cases, but calling this function
    directly is useful for debugging or if you need to invoke ffmpeg
    manually for whatever reason.

    This is the same as calling :meth:`get_args` except that it also
    includes the ``ffmpeg`` command as the first argument.
    )rT   )r.   r   ÚtyperG   rV   )rS   r   rT   r   r   r   Úcompile®   s
    
rY   c             C   sR   t | ||d�}|rtjnd}|s$|r*tjnd}	|s6|r<tjnd}
tj|||	|
d�S )aD
  Asynchronously invoke ffmpeg for the supplied node graph.

    Args:
        pipe_stdin: if True, connect pipe to subprocess stdin (to be
            used with ``pipe:`` ffmpeg inputs).
        pipe_stdout: if True, connect pipe to subprocess stdout (to be
            used with ``pipe:`` ffmpeg outputs).
        pipe_stderr: if True, connect pipe to subprocess stderr.
        quiet: shorthand for setting ``capture_stdout`` and
            ``capture_stderr``.
        **kwargs: keyword-arguments passed to ``get_args()`` (e.g.
            ``overwrite_output=True``).

    Returns:
        A `subprocess Popen`_ object representing the child process.

    Examples:
        Run and stream input::

            process = (
                ffmpeg
                .input('pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height))
                .output(out_filename, pix_fmt='yuv420p')
                .overwrite_output()
                .run_async(pipe_stdin=True)
            )
            process.communicate(input=input_data)

        Run and capture output::

            process = (
                ffmpeg
                .input(in_filename)
                .output('pipe':, format='rawvideo', pix_fmt='rgb24')
                .run_async(pipe_stdout=True, pipe_stderr=True)
            )
            out, err = process.communicate()

        Process video frame-by-frame using numpy::

            process1 = (
                ffmpeg
                .input(in_filename)
                .output('pipe:', format='rawvideo', pix_fmt='rgb24')
                .run_async(pipe_stdout=True)
            )

            process2 = (
                ffmpeg
                .input('pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height))
                .output(out_filename, pix_fmt='yuv420p')
                .overwrite_output()
                .run_async(pipe_stdin=True)
            )

            while True:
                in_bytes = process1.stdout.read(width * height * 3)
                if not in_bytes:
                    break
                in_frame = (
                    np
                    .frombuffer(in_bytes, np.uint8)
                    .reshape([height, width, 3])
                )
                out_frame = in_frame * 0.3
                process2.stdin.write(
                    frame
                    .astype(np.uint8)
                    .tobytes()
                )

            process2.stdin.close()
            process1.wait()
            process2.wait()

    .. _subprocess Popen: https://docs.python.org/3/library/subprocess.html#popen-objects
    )rT   N)Ústdinr   r   )rY   Ú
subprocessÚPIPEÚPopen)rS   r   Ú
pipe_stdinÚpipe_stdoutÚpipe_stderrÚquietrT   r)   Zstdin_streamZstdout_streamZstderr_streamr   r   r   Ú	run_asyncÁ   s    Wrb   c          	   C   sH   t | ||dk	||||d�}|j|ƒ\}}	|jƒ }
|
r@td||	ƒ‚||	fS )a7  Invoke ffmpeg for the supplied node graph.

    Args:
        capture_stdout: if True, capture stdout (to be used with
            ``pipe:`` ffmpeg outputs).
        capture_stderr: if True, capture stderr.
        quiet: shorthand for setting ``capture_stdout`` and ``capture_stderr``.
        input: text to be sent to stdin (to be used with ``pipe:``
            ffmpeg inputs)
        **kwargs: keyword-arguments passed to ``get_args()`` (e.g.
            ``overwrite_output=True``).

    Returns: (out, err) tuple containing captured stdout and stderr data.
    N)r^   r_   r`   ra   rT   rW   )rb   ÚcommunicateÚpollr   )rS   r   Zcapture_stdoutZcapture_stderrr
   ra   rT   ÚprocessÚoutÚerrÚretcoder   r   r   Úrun!  s    ri   )F)F)rW   F)rW   FFFFF)rW   FFNFF))Ú
__future__r   Zdagr   r   Ú_utilsr   r   Úbuiltinsr   Ú	functoolsr	   rJ   r$   rQ   r[   Z_ffmpegr
   r   rU   r   r   r   r   r   r   Ú	Exceptionr   r*   r4   r5   r>   rD   rF   rH   rM   rV   rY   rb   ri   Ú__all__r   r   r   r   Ú<module>   sL    
	
	$     X      