diff --git a/ffmpeg/_run.py b/ffmpeg/_run.py index 38dab26..f66b19a 100644 --- a/ffmpeg/_run.py +++ b/ffmpeg/_run.py @@ -7,7 +7,6 @@ import collections import copy import operator import subprocess -import asyncio from ._ffmpeg import input, output from .nodes import ( @@ -327,43 +326,12 @@ def run( return out, err -@output_operator() -async def run_asyncio( - stream_spec, - cmd='ffmpeg', - pipe_stdin=False, - pipe_stdout=False, - pipe_stderr=False, - quiet=False, - overwrite_output=False, -): - """Asynchronously invoke ffmpeg in asyncio sync/await style and return coroutine. - Have the same possibilities as `run_async` call. +__all__ = ['compile', 'Error', 'get_args', 'run', 'run_async'] - 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``. - - Returns: - A Process instance as a coroutine - """ - - args = compile(stream_spec, cmd, overwrite_output=overwrite_output) - stdin_stream = asyncio.subprocess.PIPE if pipe_stdin else None - stdout_stream = asyncio.subprocess.PIPE if pipe_stdout or quiet else None - stderr_stream = asyncio.subprocess.PIPE if pipe_stderr or quiet else None - - return await asyncio.create_subprocess_exec( - *args, - stdin=stdin_stream, - stdout=stdout_stream, - stderr=stderr_stream - ) - - -__all__ = ['compile', 'Error', 'get_args', 'run', 'run_async', 'run_asyncio'] +try: + from ._run_asyncio import * +except (SyntaxError, ImportError): + pass +else: + from . import _run_asyncio + __all__ += _run_asyncio.__all__ diff --git a/ffmpeg/_run_asyncio.py b/ffmpeg/_run_asyncio.py new file mode 100644 index 0000000..7ae7335 --- /dev/null +++ b/ffmpeg/_run_asyncio.py @@ -0,0 +1,47 @@ +import asyncio + +from ._run import output_operator +from ._run import * + + +@output_operator() +@asyncio.coroutine +def run_asyncio( + stream_spec, + cmd='ffmpeg', + pipe_stdin=False, + pipe_stdout=False, + pipe_stderr=False, + quiet=False, + overwrite_output=False, +): + """Asynchronously invoke ffmpeg in asyncio sync/await style and return coroutine. + Have the same possibilities as `run_async` call. + + 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``. + + Returns: + A Process instance as a coroutine + """ + + args = compile(stream_spec, cmd, overwrite_output=overwrite_output) + stdin_stream = asyncio.subprocess.PIPE if pipe_stdin else None + stdout_stream = asyncio.subprocess.PIPE if pipe_stdout or quiet else None + stderr_stream = asyncio.subprocess.PIPE if pipe_stderr or quiet else None + + result = yield from asyncio.create_subprocess_exec( + *args, + stdin=stdin_stream, + stdout=stdout_stream, + stderr=stderr_stream + ) + return result + +__all__ = ['run_asyncio'] diff --git a/ffmpeg/tests/_test_asyncio.py b/ffmpeg/tests/_test_asyncio.py new file mode 100644 index 0000000..623c620 --- /dev/null +++ b/ffmpeg/tests/_test_asyncio.py @@ -0,0 +1,33 @@ +import ffmpeg +import asyncio + +from .test_ffmpeg import TEST_INPUT_FILE1 + + +def test_run_asyncio(): + @asyncio.coroutine + def test_async(): + process = yield from ( + ffmpeg + .input(TEST_INPUT_FILE1) + .output('pipe:', format='rawvideo', pix_fmt='rgb24')['v'] + .run_asyncio(pipe_stdout=True, quiet=False) + ) + + video_frame_size = 320 * 240 * 3 # Note: RGB24 == 3 bytes per pixel. 320x240 - video size + + total_bytes = 0 + + while True: + frame_bytes = yield from process.stdout.read(video_frame_size) + if len(frame_bytes) == 0: + break + else: + total_bytes += len(frame_bytes) + + yield from process.wait() + + assert total_bytes == 48153600, 'Incorrect size of the output frames' + + loop = asyncio.get_event_loop() + loop.run_until_complete(test_async()) diff --git a/ffmpeg/tests/test_ffmpeg.py b/ffmpeg/tests/test_ffmpeg.py index 3aefcbc..9663819 100644 --- a/ffmpeg/tests/test_ffmpeg.py +++ b/ffmpeg/tests/test_ffmpeg.py @@ -10,7 +10,6 @@ import random import re import subprocess import sys -import asyncio try: @@ -786,29 +785,5 @@ def test__multi_output_edge_label_order(): assert out2 == get_filter_complex_input(flt_cmpl, 'hflip') -def test_run_asyncio(): - async def test_async(): - process = await ( - ffmpeg - .input(TEST_INPUT_FILE1) - .output('pipe:', format='rawvideo', pix_fmt='rgb24')['v'] - .run_asyncio(pipe_stdout=True, quiet=False) - ) - - video_frame_size = 320 * 240 * 3 # Note: RGB24 == 3 bytes per pixel. 320x240 - video size - - total_bytes = 0 - - while True: - frame_bytes = await process.stdout.read(video_frame_size) - if len(frame_bytes) == 0: - break - else: - total_bytes += len(frame_bytes) - - await process.wait() - - assert total_bytes == 48153600, 'Incorrect size of the output frames' - - loop = asyncio.get_event_loop() - loop.run_until_complete(test_async()) +if sys.version_info >= (3, 4): + from ._test_asyncio import test_run_asyncio