8000 Merge pull request #14 from kkroening/io-flags · Powercoder64/ffmpeg-python@36c4a97 · GitHub
[go: up one dir, main page]

Skip to content

Commit 36c4a97

Browse files
authored
Merge pull request kkroening#14 from kkroening/io-flags
Support input/output parameters
2 parents 45f1494 + 525b1bf commit 36c4a97

File tree

4 files changed

+85
-8
lines changed

4 files changed

+85
-8
lines changed

ffmpeg/_ffmpeg.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88
)
99

1010

11-
def input(filename):
11+
def input(filename, **kwargs):
1212
"""Input file URL (ffmpeg ``-i`` option)
1313
1414
Official documentation: `Main options <https://ffmpeg.org/ffmpeg.html#Main-options>`__
1515
"""
16-
return InputNode(input.__name__, filename=filename)
16+
kwargs['filename'] = filename
17+
fmt = kwargs.pop('f', None)
18+
if fmt:
19+
assert 'format' not in kwargs, "Can't specify both `format` and `f` kwargs"
20+
kwargs['format'] = fmt
21+
return InputNode(input.__name__, **kwargs)
1722

1823

1924
@operator(node_classes={OutputNode, GlobalNode})
@@ -31,12 +36,17 @@ def merge_outputs(*parent_nodes):
3136

3237

3338
@operator(node_classes={InputNode, FilterNode})
34-
def output(parent_node, filename):
39+
def output(parent_node, filename, **kwargs):
3540
"""Output file URL
3641
3742
Official documentation: `Synopsis <https://ffmpeg.org/ffmpeg.html#Synopsis>`__
3843
"""
39-
return OutputNode([parent_node], output.__name__, filename=filename)
44+
kwargs['filename'] = filename
45+
fmt = kwargs.pop('f', None)
46+
if fmt:
47+
assert 'format' not in kwargs, "Can't specify both `format` and `f` kwargs"
48+
kwargs['format'] = fmt
49+
return OutputNode([parent_node], output.__name__, **kwargs)
4050

4151

4252

ffmpeg/_run.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import unicode_literals
22

3+
from functools import reduce
34
from past.builtins import basestring
5+
import copy
46
import operator as _operator
57
import subprocess as _subprocess
68

@@ -16,15 +18,34 @@
1618
operator,
1719
OutputNode,
1820
)
19-
from functools import reduce
2021

2122
def _get_stream_name(name):
2223
return '[{}]'.format(name)
2324

2425

26+
def _convert_kwargs_to_cmd_line_args(kwargs):
27+
args = []
28+
for k in sorted(kwargs.keys()):
29+
v = kwargs[k]
30+
args.append('-{}'.format(k))
31+
if v:
32+
args.append('{}'.format(v))
33+
return args
34+
35+
2536
def _get_input_args(input_node):
2637
if input_node._name == input.__name__:
27-
args = ['-i', input_node._kwargs['filename']]
38+
kwargs = copy.copy(input_node._kwargs)
39+
filename = kwargs.pop('filename')
40+
fmt = kwargs.pop('format', None)
41+
video_size = kwargs.pop('video_size', None)
42+
args = []
43+
if fmt:
44+
args += ['-f', fmt]
45+
if video_size:
46+
args += ['-video_size', '{}x{}'.format(video_size[0], video_size[1])]
47+
args += _convert_kwargs_to_cmd_line_args(kwargs)
48+
args += ['-i', filename]
2849
else:
2950
assert False, 'Unsupported input node: {}'.format(input_node)
3051
return args
@@ -78,7 +99,13 @@ def _get_output_args(node, stream_name_map):
7899
if stream_name != '[0]':
79100
args += ['-map', stream_name]
80101
if node._name == output.__name__:
81-
args += [node._kwargs['filename']]
102+
kwargs = copy.copy(node._kwargs)
103+
filename = kwargs.pop('filename')
104+
fmt = kwargs.pop('format', None)
105+
if fmt:
106+
args += ['-f', fmt]
107+
args += _convert_kwargs_to_cmd_line_args(kwargs)
108+
args += [filename]
82109
else:
83110
assert False, 'Unsupported output node: {}'.format(node)
84111
return args

ffmpeg/tests/test_ffmpeg.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import pytest
55
import subprocess
6+
import random
67

78

89
TEST_DIR = os.path.dirname(__file__)
@@ -167,3 +168,42 @@ def test_custom_filter_fluent():
167168
'-map', '[v0]',
168169
'dummy2.mp4'
169170
]
171+
172+
173+
def test_pipe():
174+
width = 32
175+
height = 32
176+
frame_size = width * height * 3 # 3 bytes for rgb24
177+
frame_count = 10
178+
start_frame = 2
179+
180+
out = (ffmpeg
181+
.input('pipe:0', format='rawvideo', pixel_format='rgb24', video_size=(width, height), framerate=10)
182+
.trim(start_frame=start_frame)
183+
.output('pipe:1', format='rawvideo')
184+
)
185+
186+
args = out.get_args()
187+
assert args == [
188+
'-f', 'rawvideo',
189+
'-video_size', '{}x{}'.format(width, height),
190+
'-framerate', '10',
191+
'-pixel_format', 'rgb24',
192+
'-i', 'pipe:0',
193+
'-filter_complex',
194+
'[0]trim=start_frame=2[v0]',
195+
'-map', '[v0]',
196+
'-f', 'rawvideo',
197+
'pipe:1'
198+
]
199+
200+
cmd = ['ffmpeg'] + args
201+
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
202+
203+
in_data = bytes(bytearray([random.randint(0,255) for _ in range(frame_size * frame_count)]))
204+
p.stdin.write(in_data) # note: this could block, in which case need to use threads
205+
p.stdin.close()
206+
207+
out_data = p.stdout.read()
208+
assert len(out_data) == frame_size * (frame_count - start_frame)
209+
assert out_data == in_data[start_frame*frame_size:]

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
envlist = py27, py33, py34, py35, py36, pypy
88

99
[testenv]
10-
commands = py.test
10+
commands = py.test -vv
1111
deps =
1212
future
1313
pytest

0 commit comments

Comments
 (0)
0