1
1
from __future__ import unicode_literals
2
2
from .nodes import (
3
3
FilterNode ,
4
- operator ,
4
+ filter_operator ,
5
5
)
6
6
7
7
8
- @operator ()
9
- def filter_ ( parent_node , filter_name , * args , ** kwargs ):
10
- """Apply custom single-source filter.
8
+ @filter_operator ()
9
+ def filter_multi_output ( stream_spec , filter_name , * args , ** kwargs ):
10
+ """Apply custom filter with one or more outputs .
11
11
12
- ``filter_`` is normally used by higher-level filter functions such as ``hflip``, but if a filter implementation
13
- is missing from ``fmpeg-python``, you can call ``filter_`` directly to have ``fmpeg-python`` pass the filter name
14
- and arguments to ffmpeg verbatim.
15
-
16
- Args:
17
- parent_node: Source stream to apply filter to.
18
- filter_name: ffmpeg filter name, e.g. `colorchannelmixer`
19
- *args: list of args to pass to ffmpeg verbatim
20
- **kwargs: list of keyword-args to pass to ffmpeg verbatim
12
+ This is the same as ``filter_`` except that the filter can produce more than one output.
21
13
22
- This function is used internally by all of the other single-source filters (e.g. ``hflip``, ``crop``, etc.).
23
- For custom multi-source filters, see ``filter_multi`` instead.
24
-
25
- The function name is suffixed with ``_`` in order avoid confusion with the standard python ``filter`` function.
14
+ To reference an output stream, use either the ``.stream`` operator or bracket shorthand:
26
15
27
16
Example:
28
17
29
- ``ffmpeg.input('in.mp4').filter_('hflip').output('out.mp4').run()``
18
+ ```
19
+ split = ffmpeg.input('in.mp4').filter_multi_output('split')
20
+ split0 = split.stream(0)
21
+ split1 = split[1]
22
+ ffmpeg.concat(split0, split1).output('out.mp4').run()
23
+ ```
30
24
"""
31
- return FilterNode ([parent_node ], filter_name , * args , ** kwargs )
32
-
25
+ return FilterNode (stream_spec , filter_name , args = args , kwargs = kwargs , max_inputs = None )
33
26
34
- def filter_multi (parent_nodes , filter_name , * args , ** kwargs ):
35
- """Apply custom multi-source filter.
36
27
37
- This is nearly identical to the ``filter`` function except that it allows filters to be applied to multiple
38
- streams. It's normally used by higher-level filter functions such as ``concat``, but if a filter implementation
39
- is missing from ``fmpeg-python``, you can call ``filter_multi`` directly .
28
+ @ filter_operator ()
29
+ def filter_ ( stream_spec , filter_name , * args , ** kwargs ):
30
+ """Apply custom filter .
40
31
41
- Note that because it applies to multiple streams, it can't be used as an operator, unlike the ``filter`` function
42
- (e.g. ``ffmpeg.input('in.mp4').filter_('hflip')``)
32
+ ``filter_`` is normally used by higher-level filter functions such as ``hflip``, but if a filter implementation
33
+ is missing from ``fmpeg-python``, you can call ``filter_`` directly to have ``fmpeg-python`` pass the filter name
34
+ and arguments to ffmpeg verbatim.
43
35
44
36
Args:
45
- parent_nodes: List of source streams to apply filter to.
46
- filter_name: ffmpeg filter name, e.g. `concat `
37
+ stream_spec: a Stream, list of Streams, or label-to-Stream dictionary mapping
38
+ filter_name: ffmpeg filter name, e.g. `colorchannelmixer `
47
39
*args: list of args to pass to ffmpeg verbatim
48
40
**kwargs: list of keyword-args to pass to ffmpeg verbatim
49
41
50
- For custom single-source filters, see ``filter_multi `` instead .
42
+ The function name is suffixed with ``_ `` in order avoid confusion with the standard python ``filter`` function .
51
43
52
44
Example:
53
45
54
- ``ffmpeg.filter_multi(ffmpeg. input('in1 .mp4'), ffmpeg.input('in2.mp4'), 'concat', n=2 ).output('out.mp4').run()``
46
+ ``ffmpeg.input('in .mp4').filter_('hflip' ).output('out.mp4').run()``
55
47
"""
56
- return FilterNode (parent_nodes , filter_name , * args , ** kwargs )
57
-
48
+ return filter_multi_output (stream_spec , filter_name , * args , ** kwargs ).stream ()
58
49
59
50
60
- @operator ()
61
- def setpts (parent_node , expr ):
51
+ @filter_operator ()
52
+ def setpts (stream , expr ):
62
53
"""Change the PTS (presentation timestamp) of the input frames.
63
54
64
55
Args:
65
56
expr: The expression which is evaluated for each frame to construct its timestamp.
66
57
67
58
Official documentation: `setpts, asetpts <https://ffmpeg.org/ffmpeg-filters.html#setpts_002c-asetpts>`__
68
59
"""
69
- return filter_ ( parent_node , setpts .__name__ , expr )
60
+ return FilterNode ( stream , setpts .__name__ , args = [ expr ]). stream ( )
70
61
71
62
72
- @operator ()
73
- def trim (parent_node , ** kwargs ):
63
+ @filter_operator ()
64
+ def trim (stream , ** kwargs ):
74
65
"""Trim the input so that the output contains one continuous subpart of the input.
75
66
76
67
Args:
@@ -88,10 +79,10 @@ def trim(parent_node, **kwargs):
88
79
89
80
Official documentation: `trim <https://ffmpeg.org/ffmpeg-filters.html#trim>`__
90
81
"""
91
- return filter_ ( parent_node , trim .__name__ , ** kwargs )
82
+ return FilterNode ( stream , trim .__name__ , kwargs = kwargs ). stream ( )
92
83
93
84
94
- @operator ()
85
+ @filter_operator ()
95
86
def overlay (main_parent_node , overlay_parent_node , eof_action = 'repeat' , ** kwargs ):
96
87
"""Overlay one video on top of another.
97
88
@@ -136,29 +127,29 @@ def overlay(main_parent_node, overlay_parent_node, eof_action='repeat', **kwargs
136
127
Official documentation: `overlay <https://ffmpeg.org/ffmpeg-filters.html#overlay-1>`__
137
128
"""
138
129
kwargs ['eof_action' ] = eof_action
139
- return filter_multi ([main_parent_node , overlay_parent_node ], overlay .__name__ , ** kwargs )
130
+ return FilterNode ([main_parent_node , overlay_parent_node ], overlay .__name__ , kwargs = kwargs , max_inputs = 2 ). stream ( )
140
131
141
132
142
- @operator ()
143
- def hflip (parent_node ):
133
+ @filter_operator ()
134
+ def hflip (stream ):
144
135
"""Flip the input video horizontally.
145
136
146
137
Official documentation: `hflip <https://ffmpeg.org/ffmpeg-filters.html#hflip>`__
147
138
"""
148
- return filter_ ( parent_node , hflip .__name__ )
139
+ return FilterNode ( stream , hflip .__name__ ). stream ( )
149
140
150
141
151
- @operator ()
152
- def vflip (parent_node ):
142
+ @filter_operator ()
143
+ def vflip (stream ):
153
144
"""Flip the input video vertically.
154
145
155
146
Official documentation: `vflip <https://ffmpeg.org/ffmpeg-filters.html#vflip>`__
156
147
"""
157
- return filter_ ( parent_node , vflip .__name__ )
148
+ return FilterNode ( stream , vflip .__name__ ). stream ( )
158
149
159
150
160
- @operator ()
161
- def drawbox (parent_node , x , y , width , height , color , thickness = None , ** kwargs ):
151
+ @filter_operator ()
152
+ def drawbox (stream , x , y , width , height , color , thickness = None , ** kwargs ):
162
153
"""Draw a colored box on the input image.
163
154
164
155
Args:
@@ -179,11 +170,11 @@ def drawbox(parent_node, x, y, width, height, color, thickness=None, **kwargs):
179
170
"""
180
171
if thickness :
181
172
kwargs ['t' ] = thickness
182
- return filter_ ( parent_node , drawbox .__name__ , x , y , width , height , color , ** kwargs )
173
+ return FilterNode ( stream , drawbox .__name__ , args = [ x , y , width , height , color ], kwargs = kwargs ). stream ( )
183
174
184
175
185
- @operator ()
186
- def concat (* parent_nodes , ** kwargs ):
176
+ @filter_operator ()
177
+ def concat (* streams , ** kwargs ):
187
178
"""Concatenate audio and video streams, joining them together one after the other.
188
179
189
180
The filter works on segments of synchronized video and audio streams. All segments must have the same number of
@@ -208,12 +199,12 @@ def concat(*parent_nodes, **kwargs):
208
199
209
200
Official documentation: `concat <https://ffmpeg.org/ffmpeg-filters.html#concat>`__
210
201
"""
211
- kwargs ['n' ] = len (parent_nodes )
212
- return filter_multi ( parent_nodes , concat .__name__ , ** kwargs )
202
+ kwargs ['n' ] = len (streams )
203
+ return FilterNode ( streams , concat .__name__ , kwargs = kwargs , max_inputs = None ). stream ( )
213
204
214
205
215
- @operator ()
216
- def zoompan (parent_node , ** kwargs ):
206
+ @filter_operator ()
207
+ def zoompan (stream , ** kwargs ):
217
208
"""Apply Zoom & Pan effect.
218
209
219
210
Args:
@@ -228,11 +219,11 @@ def zoompan(parent_node, **kwargs):
228
219
229
220
Official documentation: `zoompan <https://ffmpeg.org/ffmpeg-filters.html#zoompan>`__
230
221
"""
231
- return filter_ ( parent_node , zoompan .__name__ , ** kwargs )
222
+ return FilterNode ( stream , zoompan .__name__ , kwargs = kwargs ). stream ( )
232
223
233
224
234
- @operator ()
235
- def hue (parent_node , ** kwargs ):
225
+ @filter_operator ()
226
+ def hue (stream , ** kwargs ):
236
227
"""Modify the hue and/or the saturation of the input.
237
228
238
229
Args:
@@ -243,24 +234,23 @@ def hue(parent_node, **kwargs):
243
234
244
235
Official documentation: `hue <https://ffmpeg.org/ffmpeg-filters.html#hue>`__
245
236
"""
246
- return filter_ ( parent_node , hue .__name__ , ** kwargs )
237
+ return FilterNode ( stream , hue .__name__ , kwargs = kwargs ). stream ( )
247
238
248
239
249
- @operator ()
250
- def colorchannelmixer (parent_node , * args , ** kwargs ):
240
+ @filter_operator ()
241
+ def colorchannelmixer (stream , * args , ** kwargs ):
251
242
"""Adjust video input frames by re-mixing color channels.
252
243
253
244
Official documentation: `colorchannelmixer <https://ffmpeg.org/ffmpeg-filters.html#colorchannelmixer>`__
254
245
"""
255
- return filter_ ( parent_node , colorchannelmixer .__name__ , ** kwargs )
246
+ return FilterNode ( stream , colorchannelmixer .__name__ , kwargs = kwargs ). stream ( )
256
247
257
248
258
249
__all__ = [
259
250
'colorchannelmixer' ,
260
251
'concat' ,
261
252
'drawbox' ,
262
253
'filter_' ,
263
- 'filter_multi' ,
264
254
'hflip' ,
265
255
'hue' ,
266
256
'overlay' ,
0 commit comments