1
1
from __future__ import unicode_literals
2
2
3
- from .nodes import FilterNode , operator
3
+ from .nodes import FilterNode , filter_operator
4
4
from ._utils import escape_chars
5
5
6
6
7
- @operator ()
8
- def filter_ ( parent_node , filter_name , * args , ** kwargs ):
9
- """Apply custom single-source filter.
7
+ @filter_operator ()
8
+ def filter_multi_output ( stream_spec , filter_name , * args , ** kwargs ):
9
+ """Apply custom filter with one or more outputs .
10
10
11
- ``filter_`` is normally used by higher-level filter functions such as ``hflip``, but if a filter implementation
12
- is missing from ``fmpeg-python``, you can call ``filter_`` directly to have ``fmpeg-python`` pass the filter name
13
- and arguments to ffmpeg verbatim.
14
-
15
- Args:
16
- parent_node: Source stream to apply filter to.
17
- filter_name: ffmpeg filter name, e.g. `colorchannelmixer`
18
- *args: list of args to pass to ffmpeg verbatim
19
- **kwargs: list of keyword-args to pass to ffmpeg verbatim
11
+ This is the same as ``filter_`` except that the filter can produce more than one output.
20
12
21
- This function is used internally by all of the other single-source filters (e.g. ``hflip``, ``crop``, etc.).
22
- For custom multi-source filters, see ``filter_multi`` instead.
23
-
24
- The function name is suffixed with ``_`` in order avoid confusion with the standard python ``filter`` function.
13
+ To reference an output stream, use either the ``.stream`` operator or bracket shorthand:
25
14
26
15
Example:
27
16
28
- ``ffmpeg.input('in.mp4').filter_('hflip').output('out.mp4').run()``
17
+ ```
18
+ split = ffmpeg.input('in.mp4').filter_multi_output('split')
19
+ split0 = split.stream(0)
20
+ split1 = split[1]
21
+ ffmpeg.concat(split0, split1).output('out.mp4').run()
22
+ ```
29
23
"""
30
- return FilterNode ([parent_node ], filter_name , * args , ** kwargs )
31
-
24
+ return FilterNode (stream_spec , filter_name , args = args , kwargs = kwargs , max_inputs = None )
32
25
33
- def filter_multi (parent_nodes , filter_name , * args , ** kwargs ):
34
- """Apply custom multi-source filter.
35
26
36
- This is nearly identical to the ``filter`` function except that it allows filters to be applied to multiple
37
- streams. It's normally used by higher-level filter functions such as ``concat``, but if a filter implementation
38
- is missing from ``fmpeg-python``, you can call ``filter_multi`` directly .
27
+ @ filter_operator ()
28
+ def filter_ ( stream_spec , filter_name , * args , ** kwargs ):
29
+ """Apply custom filter .
39
30
40
- Note that because it applies to multiple streams, it can't be used as an operator, unlike the ``filter`` function
41
- (e.g. ``ffmpeg.input('in.mp4').filter_('hflip')``)
31
+ ``filter_`` is normally used by higher-level filter functions such as ``hflip``, but if a filter implementation
32
+ is missing from ``fmpeg-python``, you can call ``filter_`` directly to have ``fmpeg-python`` pass the filter name
33
+ and arguments to ffmpeg verbatim.
42
34
43
35
Args:
44
- parent_nodes: List of source streams to apply filter to.
45
- filter_name: ffmpeg filter name, e.g. `concat `
36
+ stream_spec: a Stream, list of Streams, or label-to-Stream dictionary mapping
37
+ filter_name: ffmpeg filter name, e.g. `colorchannelmixer `
46
38
*args: list of args to pass to ffmpeg verbatim
47
39
**kwargs: list of keyword-args to pass to ffmpeg verbatim
48
40
49
- For custom single-source filters, see ``filter_multi `` instead .
41
+ The function name is suffixed with ``_ `` in order avoid confusion with the standard python ``filter`` function .
50
42
51
43
Example:
52
44
53
- ``ffmpeg.filter_multi(ffmpeg. input('in1 .mp4'), ffmpeg.input('in2.mp4'), 'concat', n=2 ).output('out.mp4').run()``
45
+ ``ffmpeg.input('in .mp4').filter_('hflip' ).output('out.mp4').run()``
54
46
"""
55
- return FilterNode (parent_nodes , filter_name , * args , ** kwargs )
47
+ return filter_multi_output (stream_spec , filter_name , * args , ** kwargs ).stream ()
48
+
56
49
50
+ @filter_operator ()
51
+ def split (stream ):
52
+ return FilterNode (stream , split .__name__ )
57
53
58
54
59
- @operator ()
60
- def setpts (parent_node , expr ):
55
+ @filter_operator ()
56
+ def setpts (stream , expr ):
61
57
"""Change the PTS (presentation timestamp) of the input frames.
62
58
63
59
Args:
64
60
expr: The expression which is evaluated for each frame to construct its timestamp.
65
61
66
62
Official documentation: `setpts, asetpts <https://ffmpeg.org/ffmpeg-filters.html#setpts_002c-asetpts>`__
67
63
"""
68
- return filter_ ( parent_node , setpts .__name__ , expr )
64
+ return FilterNode ( stream , setpts .__name__ , args = [ expr ]). stream ( )
69
65
70
66
71
- @operator ()
72
- def trim (parent_node , ** kwargs ):
67
+ @filter_operator ()
68
+ def trim (stream , ** kwargs ):
73
69
"""Trim the input so that the output contains one continuous subpart of the input.
74
70
75
71
Args:
@@ -87,10 +83,10 @@ def trim(parent_node, **kwargs):
87
83
88
84
Official documentation: `trim <https://ffmpeg.org/ffmpeg-filters.html#trim>`__
89
85
"""
90
- return filter_ ( parent_node , trim .__name__ , ** kwargs )
86
+ return FilterNode ( stream , trim .__name__ , kwargs = kwargs ). stream ( )
91
87
92
88
93
- @operator ()
89
+ @filter_operator ()
94
90
def overlay (main_parent_node , overlay_parent_node , eof_action = 'repeat' , ** kwargs ):
95
91
"""Overlay one video on top of another.
96
92
@@ -135,29 +131,29 @@ def overlay(main_parent_node, overlay_parent_node, eof_action='repeat', **kwargs
135
131
Official documentation: `overlay <https://ffmpeg.org/ffmpeg-filters.html#overlay-1>`__
136
132
"""
137
133
kwargs ['eof_action' ] = eof_action
138
- return filter_multi ([main_parent_node , overlay_parent_node ], overlay .__name__ , ** kwargs )
134
+ return FilterNode ([main_parent_node , overlay_parent_node ], overlay .__name__ , kwargs = kwargs , max_inputs = 2 ). stream ( )
139
135
140
136
141
- @operator ()
142
- def hflip (parent_node ):
137
+ @filter_operator ()
138
+ def hflip (stream ):
143
139
"""Flip the input video horizontally.
144
140
145
141
Official documentation: `hflip <https://ffmpeg.org/ffmpeg-filters.html#hflip>`__
146
142
"""
147
- return filter_ ( parent_node , hflip .__name__ )
143
+ return FilterNode ( stream , hflip .__name__ ). stream ( )
148
144
149
145
150
- @operator ()
151
- def vflip (parent_node ):
146
+ @filter_operator ()
147
+ def vflip (stream ):
152
148
"""Flip the input video vertically.
153
149
154
150
Official documentation: `vflip <https://ffmpeg.org/ffmpeg-filters.html#vflip>`__
155
151
"""
156
- return filter_ ( parent_node , vflip .__name__ )
152
+ return FilterNode ( stream , vflip .__name__ ). stream ( )
157
153
158
154
159
- @operator ()
160
- def drawbox (parent_node , x , y , width , height , color , thickness = None , ** kwargs ):
155
+ @filter_operator ()
156
+ def drawbox (stream , x , y , width , height , color , thickness = None , ** kwargs ):
161
157
"""Draw a colored box on the input image.
162
158
163
159
Args:
@@ -178,11 +174,11 @@ def drawbox(parent_node, x, y, width, height, color, thickness=None, **kwargs):
178
174
"""
179
175
if thickness :
180
176
kwargs ['t' ] = thickness
181
- return filter_ ( parent_node , drawbox .__name__ , x , y , width , height , color , ** kwargs )
177
+ return FilterNode ( stream , drawbox .__name__ , args = [ x , y , width , height , color ], kwargs = kwargs ). stream ( )
182
178
183
179
184
- @operator ()
185
- def drawtext (parent_node , text = None , x = 0 , y = 0 , escape_text = True , ** kwargs ):
180
+ @filter_operator ()
181
+ def drawtext (stream , text = None , x = 0 , y = 0 , escape_text = True , ** kwargs ):
186
182
"""Draw a text string or text from a specified file on top of a video, using the libfreetype library.
187
183
188
184
To enable compilation of this filter, you need to configure FFmpeg with ``--enable-libfreetype``. To enable default
@@ -320,11 +316,11 @@ def drawtext(parent_node, text=None, x=0, y=0, escape_text=True, **kwargs):
320
316
kwargs ['x' ] = x
321
317
if y != 0 :
322
318
kwargs ['y' ] = y
323
- return filter_ (parent_node , drawtext .__name__ , ** kwargs )
319
+ return filter_ (stream , drawtext .__name__ , ** kwargs )
324
320
325
321
326
- @operator ()
327
- def concat (* parent_nodes , ** kwargs ):
322
+ @filter_operator ()
323
+ def concat (* streams , ** kwargs ):
328
324
"""Concatenate audio and video streams, joining them together one after the other.
329
325
330
326
The filter works on segments of synchronized video and audio streams. All segments must have the same number of
@@ -349,12 +345,12 @@ def concat(*parent_nodes, **kwargs):
349
345
350
346
Official documentation: `concat <https://ffmpeg.org/ffmpeg-filters.html#concat>`__
351
347
"""
352
- kwargs ['n' ] = len (parent_nodes )
353
- return filter_multi ( parent_nodes , concat .__name__ , ** kwargs )
348
+ kwargs ['n' ] = len (streams )
349
+ return FilterNode ( streams , concat .__name__ , kwargs = kwargs , max_inputs = None ). stream ( )
354
350
355
351
356
- @operator ()
357
- def zoompan (parent_node , ** kwargs ):
352
+ @filter_operator ()
353
+ def zoompan (stream , ** kwargs ):
358
354
"""Apply Zoom & Pan effect.
359
355
360
356
Args:
@@ -369,11 +365,11 @@ def zoompan(parent_node, **kwargs):
369
365
370
366
Official documentation: `zoompan <https://ffmpeg.org/ffmpeg-filters.html#zoompan>`__
371
367
"""
372
- return filter_ ( parent_node , zoompan .__name__ , ** kwargs )
368
+ return FilterNode ( stream , zoompan .__name__ , kwargs = kwargs ). stream ( )
373
369
374
370
375
- @operator ()
376
- def hue (parent_node , ** kwargs ):
371
+ @filter_operator ()
372
+ def hue (stream , ** kwargs ):
377
373
"""Modify the hue and/or the saturation of the input.
378
374
379
375
Args:
@@ -384,24 +380,23 @@ def hue(parent_node, **kwargs):
384
380
385
381
Official documentation: `hue <https://ffmpeg.org/ffmpeg-filters.html#hue>`__
386
382
""
C15E
"
387
- return filter_ ( parent_node , hue .__name__ , ** kwargs )
383
+ return FilterNode ( stream , hue .__name__ , kwargs = kwargs ). stream ( )
388
384
389
385
390
- @operator ()
391
- def colorchannelmixer (parent_node , * args , ** kwargs ):
386
+ @filter_operator ()
387
+ def colorchannelmixer (stream , * args , ** kwargs ):
392
388
"""Adjust video input frames by re-mixing color channels.
393
389
394
390
Official documentation: `colorchannelmixer <https://ffmpeg.org/ffmpeg-filters.html#colorchannelmixer>`__
395
391
"""
396
- return filter_ ( parent_node , colorchannelmixer .__name__ , ** kwargs )
392
+ return FilterNode ( stream , colorchannelmixer .__name__ , kwargs = kwargs ). stream ( )
397
393
398
394
399
395
__all__ = [
400
396
'colorchannelmixer' ,
401
397
'concat' ,
402
398
'drawbox' ,
403
399
'filter_' ,
404
- 'filter_multi' ,
405
400
'hflip' ,
406
401
'hue' ,
407
402
'overlay' ,
0 commit comments