mirror of
https://github.com/kkroening/ffmpeg-python.git
synced 2025-04-06 04:15:44 +08:00
#34: run non-interactively by default
This commit is contained in:
parent
7a44e54955
commit
d1a9ff882a
@ -2,7 +2,6 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from .nodes import (
|
from .nodes import (
|
||||||
filter_operator,
|
filter_operator,
|
||||||
GlobalNode,
|
|
||||||
InputNode,
|
InputNode,
|
||||||
MergeOutputsNode,
|
MergeOutputsNode,
|
||||||
OutputNode,
|
OutputNode,
|
||||||
@ -24,15 +23,6 @@ def input(filename, **kwargs):
|
|||||||
return InputNode(input.__name__, kwargs=kwargs).stream()
|
return InputNode(input.__name__, kwargs=kwargs).stream()
|
||||||
|
|
||||||
|
|
||||||
@output_operator()
|
|
||||||
def overwrite_output(stream):
|
|
||||||
"""Overwrite output files without asking (ffmpeg ``-y`` option)
|
|
||||||
|
|
||||||
Official documentation: `Main options <https://ffmpeg.org/ffmpeg.html#Main-options>`__
|
|
||||||
"""
|
|
||||||
return GlobalNode(stream, overwrite_output.__name__).stream()
|
|
||||||
|
|
||||||
|
|
||||||
@output_operator()
|
@output_operator()
|
||||||
def merge_outputs(*streams):
|
def merge_outputs(*streams):
|
||||||
"""Include all given outputs in one ffmpeg command line
|
"""Include all given outputs in one ffmpeg command line
|
||||||
@ -60,5 +50,4 @@ __all__ = [
|
|||||||
'input',
|
'input',
|
||||||
'merge_outputs',
|
'merge_outputs',
|
||||||
'output',
|
'output',
|
||||||
'overwrite_output',
|
|
||||||
]
|
]
|
||||||
|
@ -10,7 +10,6 @@ import subprocess as _subprocess
|
|||||||
from ._ffmpeg import (
|
from ._ffmpeg import (
|
||||||
input,
|
input,
|
||||||
output,
|
output,
|
||||||
overwrite_output,
|
|
||||||
)
|
)
|
||||||
from .nodes import (
|
from .nodes import (
|
||||||
get_stream_spec_nodes,
|
get_stream_spec_nodes,
|
||||||
@ -83,10 +82,7 @@ def _get_filter_arg(filter_nodes, outgoing_edge_maps, stream_name_map):
|
|||||||
|
|
||||||
|
|
||||||
def _get_global_args(node):
|
def _get_global_args(node):
|
||||||
if node.name == overwrite_output.__name__:
|
raise ValueError('Unsupported global node: {}'.format(node))
|
||||||
return ['-y']
|
|
||||||
else:
|
|
||||||
raise ValueError('Unsupported global node: {}'.format(node))
|
|
||||||
|
|
||||||
|
|
||||||
def _get_output_args(node, stream_name_map):
|
def _get_output_args(node, stream_name_map):
|
||||||
@ -109,7 +105,7 @@ def _get_output_args(node, stream_name_map):
|
|||||||
|
|
||||||
|
|
||||||
@output_operator()
|
@output_operator()
|
||||||
def get_args(stream_spec, overwrite_output=False):
|
def get_args(stream_spec, overwrite_output=True):
|
||||||
"""Get command-line arguments for ffmpeg."""
|
"""Get command-line arguments for ffmpeg."""
|
||||||
nodes = get_stream_spec_nodes(stream_spec)
|
nodes = get_stream_spec_nodes(stream_spec)
|
||||||
args = []
|
args = []
|
||||||
@ -126,7 +122,9 @@ def get_args(stream_spec, overwrite_output=False):
|
|||||||
args += ['-filter_complex', filter_arg]
|
args += ['-filter_complex', filter_arg]
|
||||||
args += reduce(operator.add, [_get_output_args(node, stream_name_map) for node in output_nodes])
|
args += reduce(operator.add, [_get_output_args(node, stream_name_map) for node in output_nodes])
|
||||||
args += reduce(operator.add, [_get_global_args(node) for node in global_nodes], [])
|
args += reduce(operator.add, [_get_global_args(node) for node in global_nodes], [])
|
||||||
if overwrite_output:
|
if overwrite_output is False:
|
||||||
|
args += ['-n']
|
||||||
|
elif overwrite_output is not None:
|
||||||
args += ['-y']
|
args += ['-y']
|
||||||
return args
|
return args
|
||||||
|
|
||||||
@ -136,7 +134,7 @@ def run(stream_spec, cmd='ffmpeg', **kwargs):
|
|||||||
"""Run ffmpeg on node graph.
|
"""Run ffmpeg on node graph.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
**kwargs: keyword-arguments passed to ``get_args()`` (e.g. ``overwrite_output=True``).
|
**kwargs: keyword-arguments passed to ``get_args()`` (e.g. ``overwrite_output=False``).
|
||||||
"""
|
"""
|
||||||
if isinstance(cmd, basestring):
|
if isinstance(cmd, basestring):
|
||||||
cmd = [cmd]
|
cmd = [cmd]
|
||||||
|
@ -101,7 +101,7 @@ def test_stream_repr():
|
|||||||
|
|
||||||
def test_get_args_simple():
|
def test_get_args_simple():
|
||||||
out_file = ffmpeg.input('dummy.mp4').output('dummy2.mp4')
|
out_file = ffmpeg.input('dummy.mp4').output('dummy2.mp4')
|
||||||
assert out_file.get_args() == ['-i', 'dummy.mp4', 'dummy2.mp4']
|
assert out_file.get_args() == ['-i', 'dummy.mp4', 'dummy2.mp4', '-y']
|
||||||
|
|
||||||
|
|
||||||
def _get_complex_filter_example():
|
def _get_complex_filter_example():
|
||||||
@ -122,7 +122,6 @@ def _get_complex_filter_example():
|
|||||||
.overlay(overlay_file.hflip())
|
.overlay(overlay_file.hflip())
|
||||||
.drawbox(50, 50, 120, 120, color='red', thickness=5)
|
.drawbox(50, 50, 120, 120, color='red', thickness=5)
|
||||||
.output(TEST_OUTPUT_FILE1)
|
.output(TEST_OUTPUT_FILE1)
|
||||||
.overwrite_output()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -156,7 +155,7 @@ def test_filter_normal_arg_escape():
|
|||||||
.get_args()
|
.get_args()
|
||||||
)
|
)
|
||||||
assert args[:3] == ['-i', 'in', '-filter_complex']
|
assert args[:3] == ['-i', 'in', '-filter_complex']
|
||||||
assert args[4:] == ['-map', '[s0]', 'out']
|
assert args[4:] == ['-map', '[s0]', 'out', '-y']
|
||||||
match = re.match(r'\[0\]drawtext=font=a((.|\n)*)b:text=test\[s0\]', args[3], re.MULTILINE)
|
match = re.match(r'\[0\]drawtext=font=a((.|\n)*)b:text=test\[s0\]', args[3], re.MULTILINE)
|
||||||
assert match is not None, 'Invalid -filter_complex arg: {!r}'.format(args[3])
|
assert match is not None, 'Invalid -filter_complex arg: {!r}'.format(args[3])
|
||||||
return match.group(1)
|
return match.group(1)
|
||||||
@ -190,7 +189,7 @@ def test_filter_text_arg_str_escape():
|
|||||||
.get_args()
|
.get_args()
|
||||||
)
|
)
|
||||||
assert args[:3] == ['-i', 'in', '-filter_complex']
|
assert args[:3] == ['-i', 'in', '-filter_complex']
|
||||||
assert args[4:] == ['-map', '[s0]', 'out']
|
assert args[4:] == ['-map', '[s0]', 'out', '-y']
|
||||||
match = re.match(r'\[0\]drawtext=text=a((.|\n)*)b\[s0\]', args[3], re.MULTILINE)
|
match = re.match(r'\[0\]drawtext=text=a((.|\n)*)b\[s0\]', args[3], re.MULTILINE)
|
||||||
assert match is not None, 'Invalid -filter_complex arg: {!r}'.format(args[3])
|
assert match is not None, 'Invalid -filter_complex arg: {!r}'.format(args[3])
|
||||||
return match.group(1)
|
return match.group(1)
|
||||||
@ -226,7 +225,7 @@ def test_run_multi_output():
|
|||||||
in_ = ffmpeg.input(TEST_INPUT_FILE1)
|
in_ = ffmpeg.input(TEST_INPUT_FILE1)
|
||||||
out1 = in_.output(TEST_OUTPUT_FILE1)
|
out1 = in_.output(TEST_OUTPUT_FILE1)
|
||||||
out2 = in_.output(TEST_OUTPUT_FILE2)
|
out2 = in_.output(TEST_OUTPUT_FILE2)
|
||||||
ffmpeg.run([out1, out2], overwrite_output=True)
|
ffmpeg.run([out1, out2])
|
||||||
|
|
||||||
|
|
||||||
def test_run_dummy_cmd():
|
def test_run_dummy_cmd():
|
||||||
@ -253,7 +252,8 @@ def test_custom_filter():
|
|||||||
'-i', 'dummy.mp4',
|
'-i', 'dummy.mp4',
|
||||||
'-filter_complex', '[0]custom_filter=a:b:kwarg1=c[s0]',
|
'-filter_complex', '[0]custom_filter=a:b:kwarg1=c[s0]',
|
||||||
'-map', '[s0]',
|
'-map', '[s0]',
|
||||||
'dummy2.mp4'
|
'dummy2.mp4',
|
||||||
|
'-y',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -267,7 +267,8 @@ def test_custom_filter_fluent():
|
|||||||
'-i', 'dummy.mp4',
|
'-i', 'dummy.mp4',
|
||||||
'-filter_complex', '[0]custom_filter=a:b:kwarg1=c[s0]',
|
'-filter_complex', '[0]custom_filter=a:b:kwarg1=c[s0]',
|
||||||
'-map', '[s0]',
|
'-map', '[s0]',
|
||||||
'dummy2.mp4'
|
'dummy2.mp4',
|
||||||
|
'-y',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -276,10 +277,10 @@ def test_merge_outputs():
|
|||||||
out1 = in_.output('out1.mp4')
|
out1 = in_.output('out1.mp4')
|
||||||
out2 = in_.output('out2.mp4')
|
out2 = in_.output('out2.mp4')
|
||||||
assert ffmpeg.merge_outputs(out1, out2).get_args() == [
|
assert ffmpeg.merge_outputs(out1, out2).get_args() == [
|
||||||
'-i', 'in.mp4', 'out1.mp4', 'out2.mp4'
|
'-i', 'in.mp4', 'out1.mp4', 'out2.mp4', '-y'
|
||||||
]
|
]
|
||||||
assert ffmpeg.get_args([out1, out2]) == [
|
assert ffmpeg.get_args([out1, out2]) == [
|
||||||
'-i', 'in.mp4', 'out2.mp4', 'out1.mp4'
|
'-i', 'in.mp4', 'out2.mp4', 'out1.mp4', '-y'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -292,14 +293,16 @@ def test_multi_passthrough():
|
|||||||
'-i', 'in2.mp4',
|
'-i', 'in2.mp4',
|
||||||
'out1.mp4',
|
'out1.mp4',
|
||||||
'-map', '[1]', # FIXME: this should not be here (see #23)
|
'-map', '[1]', # FIXME: this should not be here (see #23)
|
||||||
'out2.mp4'
|
'out2.mp4',
|
||||||
|
'-y',
|
||||||
]
|
]
|
||||||
assert ffmpeg.get_args([out1, out2]) == [
|
assert ffmpeg.get_args([out1, out2]) == [
|
||||||
'-i', 'in2.mp4',
|
'-i', 'in2.mp4',
|
||||||
'-i', 'in1.mp4',
|
'-i', 'in1.mp4',
|
||||||
'out2.mp4',
|
'out2.mp4',
|
||||||
'-map', '[1]', # FIXME: this should not be here (see #23)
|
'-map', '[1]', # FIXME: this should not be here (see #23)
|
||||||
'out1.mp4'
|
'out1.mp4',
|
||||||
|
'-y',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -327,7 +330,8 @@ def test_pipe():
|
|||||||
'[0]trim=start_frame=2[s0]',
|
'[0]trim=start_frame=2[s0]',
|
||||||
'-map', '[s0]',
|
'-map', '[s0]',
|
||||||
'-f', 'rawvideo',
|
'-f', 'rawvideo',
|
||||||
'pipe:1'
|
'pipe:1',
|
||||||
|
'-y',
|
||||||
]
|
]
|
||||||
|
|
||||||
cmd = ['ffmpeg'] + args
|
cmd = ['ffmpeg'] + args
|
||||||
|
Loading…
x
Reference in New Issue
Block a user