typed-ffmpeg-compatible 2.6.3__py3-none-any.whl → 2.6.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- typed_ffmpeg/__init__.py +24 -0
- typed_ffmpeg/base.py +87 -29
- typed_ffmpeg/common/schema.py +281 -3
- typed_ffmpeg/common/serialize.py +118 -21
- typed_ffmpeg/dag/__init__.py +13 -0
- typed_ffmpeg/dag/compile.py +39 -4
- typed_ffmpeg/dag/context.py +137 -29
- typed_ffmpeg/dag/factory.py +27 -0
- typed_ffmpeg/dag/global_runnable/global_args.py +11 -0
- typed_ffmpeg/dag/global_runnable/runnable.py +143 -34
- typed_ffmpeg/dag/io/_input.py +2 -1
- typed_ffmpeg/dag/io/_output.py +2 -1
- typed_ffmpeg/dag/nodes.py +402 -67
- typed_ffmpeg/dag/schema.py +3 -1
- typed_ffmpeg/dag/utils.py +29 -8
- typed_ffmpeg/dag/validate.py +83 -20
- typed_ffmpeg/exceptions.py +42 -9
- typed_ffmpeg/info.py +137 -16
- typed_ffmpeg/probe.py +31 -6
- typed_ffmpeg/schema.py +32 -5
- typed_ffmpeg/streams/channel_layout.py +13 -0
- typed_ffmpeg/utils/escaping.py +47 -7
- typed_ffmpeg/utils/forzendict.py +108 -0
- typed_ffmpeg/utils/lazy_eval/operator.py +43 -1
- typed_ffmpeg/utils/lazy_eval/schema.py +122 -6
- typed_ffmpeg/utils/run.py +44 -7
- typed_ffmpeg/utils/snapshot.py +36 -1
- typed_ffmpeg/utils/typing.py +29 -4
- typed_ffmpeg/utils/view.py +46 -4
- {typed_ffmpeg_compatible-2.6.3.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/METADATA +1 -1
- typed_ffmpeg_compatible-2.6.4.dist-info/RECORD +48 -0
- typed_ffmpeg_compatible-2.6.3.dist-info/RECORD +0 -47
- {typed_ffmpeg_compatible-2.6.3.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/LICENSE +0 -0
- {typed_ffmpeg_compatible-2.6.3.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/WHEEL +0 -0
- {typed_ffmpeg_compatible-2.6.3.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/entry_points.txt +0 -0
@@ -1,3 +1,12 @@
|
|
1
|
+
"""
|
2
|
+
Execution capabilities for FFmpeg filter graphs.
|
3
|
+
|
4
|
+
This module provides the GlobalRunable class, which extends GlobalArgs with
|
5
|
+
methods for executing FFmpeg commands. It enables compiling filter graphs
|
6
|
+
into command-line arguments and running FFmpeg processes both synchronously
|
7
|
+
and asynchronously.
|
8
|
+
"""
|
9
|
+
|
1
10
|
from __future__ import annotations
|
2
11
|
|
3
12
|
import logging
|
@@ -15,24 +24,57 @@ logger = logging.getLogger(__name__)
|
|
15
24
|
|
16
25
|
|
17
26
|
class GlobalRunable(GlobalArgs):
|
27
|
+
"""
|
28
|
+
Base class that provides execution capabilities for FFmpeg filter graphs.
|
29
|
+
|
30
|
+
This class extends GlobalArgs with methods for compiling filter graphs into
|
31
|
+
FFmpeg command-line arguments and executing FFmpeg processes. It serves as
|
32
|
+
a mixin for stream classes that need to be executed as FFmpeg commands.
|
33
|
+
"""
|
34
|
+
|
18
35
|
def merge_outputs(self, *streams: OutputStream) -> GlobalStream:
|
19
36
|
"""
|
20
|
-
Merge multiple output streams into
|
37
|
+
Merge multiple output streams into a single command.
|
38
|
+
|
39
|
+
This method allows combining multiple output files into a single FFmpeg
|
40
|
+
command, which is more efficient than running separate commands for each
|
41
|
+
output. It creates a GlobalNode that includes all the specified output
|
42
|
+
streams.
|
21
43
|
|
22
44
|
Args:
|
23
|
-
*streams:
|
45
|
+
*streams: Additional output streams to include in the same command
|
24
46
|
|
25
47
|
Returns:
|
26
|
-
|
48
|
+
A GlobalStream that represents the combined outputs
|
49
|
+
|
50
|
+
Example:
|
51
|
+
```python
|
52
|
+
# Create two output files with one command
|
53
|
+
video = ffmpeg.input("input.mp4").video
|
54
|
+
output1 = video.output("output1.mp4")
|
55
|
+
output2 = video.output("output2.webm")
|
56
|
+
merged = output1.merge_outputs(output2)
|
57
|
+
merged.run() # Creates both output files with one FFmpeg command
|
58
|
+
```
|
27
59
|
"""
|
28
60
|
return self._global_node(*streams).stream()
|
29
61
|
|
30
62
|
def overwrite_output(self) -> GlobalStream:
|
31
63
|
"""
|
32
|
-
|
64
|
+
Set the FFmpeg command to overwrite output files without asking.
|
65
|
+
|
66
|
+
This method adds the `-y` option to the FFmpeg command, which causes
|
67
|
+
FFmpeg to overwrite output files without prompting for confirmation.
|
68
|
+
It's equivalent to calling `global_args(y=True)`.
|
33
69
|
|
34
70
|
Returns:
|
35
|
-
the
|
71
|
+
A GlobalStream with the overwrite option enabled
|
72
|
+
|
73
|
+
Example:
|
74
|
+
```python
|
75
|
+
# Overwrite output file if it already exists
|
76
|
+
ffmpeg.input("input.mp4").output("output.mp4").overwrite_output().run()
|
77
|
+
```
|
36
78
|
"""
|
37
79
|
return self._global_node(y=True).stream()
|
38
80
|
|
@@ -43,15 +85,31 @@ class GlobalRunable(GlobalArgs):
|
|
43
85
|
auto_fix: bool = True,
|
44
86
|
) -> list[str]:
|
45
87
|
"""
|
46
|
-
Build command-line for invoking
|
88
|
+
Build command-line arguments for invoking FFmpeg.
|
89
|
+
|
90
|
+
This method converts the filter graph into a list of command-line
|
91
|
+
arguments that can be passed to subprocess functions or executed
|
92
|
+
directly. It handles the FFmpeg executable name, overwrite options,
|
93
|
+
and automatic fixing of the filter graph.
|
47
94
|
|
48
95
|
Args:
|
49
|
-
cmd:
|
50
|
-
|
51
|
-
|
96
|
+
cmd: The FFmpeg executable name or path, or a list containing
|
97
|
+
the executable and initial arguments
|
98
|
+
overwrite_output: If True, add the -y option to overwrite output files
|
99
|
+
If False, add the -n option to never overwrite
|
100
|
+
If None (default), use the current settings
|
101
|
+
auto_fix: Whether to automatically fix issues in the filter graph,
|
102
|
+
such as adding split filters for reused streams
|
52
103
|
|
53
104
|
Returns:
|
54
|
-
the command
|
105
|
+
A list of strings representing the complete FFmpeg command
|
106
|
+
|
107
|
+
Example:
|
108
|
+
```python
|
109
|
+
# Get the command-line arguments for a filter graph
|
110
|
+
args = ffmpeg.input("input.mp4").output("output.mp4").compile()
|
111
|
+
# Result: ['ffmpeg', '-i', 'input.mp4', 'output.mp4']
|
112
|
+
```
|
55
113
|
"""
|
56
114
|
from ..compile import compile
|
57
115
|
|
@@ -72,15 +130,29 @@ class GlobalRunable(GlobalArgs):
|
|
72
130
|
auto_fix: bool = True,
|
73
131
|
) -> str:
|
74
132
|
"""
|
75
|
-
Build command-line for invoking
|
133
|
+
Build a command-line string for invoking FFmpeg.
|
134
|
+
|
135
|
+
This method is similar to compile(), but returns a single string with
|
136
|
+
proper escaping instead of a list of arguments. This is useful for
|
137
|
+
logging or displaying the command to users.
|
76
138
|
|
77
139
|
Args:
|
78
|
-
cmd:
|
79
|
-
|
80
|
-
|
140
|
+
cmd: The FFmpeg executable name or path, or a list containing
|
141
|
+
the executable and initial arguments
|
142
|
+
overwrite_output: If True, add the -y option to overwrite output files
|
143
|
+
If False, add the -n option to never overwrite
|
144
|
+
If None (default), use the current settings
|
145
|
+
auto_fix: Whether to automatically fix issues in the filter graph
|
81
146
|
|
82
147
|
Returns:
|
83
|
-
the command
|
148
|
+
A string representing the complete FFmpeg command with proper escaping
|
149
|
+
|
150
|
+
Example:
|
151
|
+
```python
|
152
|
+
# Get a command-line string for a filter graph
|
153
|
+
cmd_str = ffmpeg.input("input.mp4").output("output.mp4").compile_line()
|
154
|
+
# Result: 'ffmpeg -i input.mp4 output.mp4'
|
155
|
+
```
|
84
156
|
"""
|
85
157
|
return command_line(
|
86
158
|
self.compile(cmd, overwrite_output=overwrite_output, auto_fix=auto_fix)
|
@@ -97,19 +169,34 @@ class GlobalRunable(GlobalArgs):
|
|
97
169
|
auto_fix: bool = True,
|
98
170
|
) -> subprocess.Popen[bytes]:
|
99
171
|
"""
|
100
|
-
Run
|
172
|
+
Run FFmpeg asynchronously as a subprocess.
|
173
|
+
|
174
|
+
This method executes the FFmpeg command in a separate process without
|
175
|
+
waiting for it to complete. This is useful for long-running operations
|
176
|
+
or when you need to interact with the process while it's running.
|
101
177
|
|
102
178
|
Args:
|
103
|
-
cmd:
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
179
|
+
cmd: The FFmpeg executable name or path, or a list containing
|
180
|
+
the executable and initial arguments
|
181
|
+
pipe_stdin: Whether to create a pipe for writing to the process's stdin
|
182
|
+
pipe_stdout: Whether to create a pipe for reading from the process's stdout
|
183
|
+
pipe_stderr: Whether to create a pipe for reading from the process's stderr
|
184
|
+
quiet: Whether to capture stderr (implies pipe_stderr=True)
|
185
|
+
overwrite_output: If True, add the -y option to overwrite output files
|
186
|
+
If False, add the -n option to never overwrite
|
187
|
+
If None (default), use the current settings
|
188
|
+
auto_fix: Whether to automatically fix issues in the filter graph
|
110
189
|
|
111
190
|
Returns:
|
112
|
-
the process
|
191
|
+
A subprocess.Popen object representing the running FFmpeg process
|
192
|
+
|
193
|
+
Example:
|
194
|
+
```python
|
195
|
+
# Start FFmpeg process and interact with it
|
196
|
+
process = ffmpeg.input("input.mp4").output("output.mp4").run_async()
|
197
|
+
# Do something while FFmpeg is running
|
198
|
+
process.wait() # Wait for completion
|
199
|
+
```
|
113
200
|
"""
|
114
201
|
|
115
202
|
args = self.compile(cmd, overwrite_output=overwrite_output, auto_fix=auto_fix)
|
@@ -139,20 +226,42 @@ class GlobalRunable(GlobalArgs):
|
|
139
226
|
auto_fix: bool = True,
|
140
227
|
) -> tuple[bytes, bytes]:
|
141
228
|
"""
|
142
|
-
Run
|
229
|
+
Run FFmpeg synchronously and wait for completion.
|
230
|
+
|
231
|
+
This method executes the FFmpeg command in a separate process and waits
|
232
|
+
for it to complete before returning. It's the most common way to run
|
233
|
+
FFmpeg commands when you just want to process media files.
|
143
234
|
|
144
235
|
Args:
|
145
|
-
cmd:
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
236
|
+
cmd: The FFmpeg executable name or path, or a list containing
|
237
|
+
the executable and initial arguments
|
238
|
+
capture_stdout: Whether to capture and return the process's stdout
|
239
|
+
capture_stderr: Whether to capture and return the process's stderr
|
240
|
+
input: Optional bytes to write to the process's stdin
|
241
|
+
quiet: Whether to suppress output to the console
|
242
|
+
overwrite_output: If True, add the -y option to overwrite output files
|
243
|
+
If False, add the -n option to never overwrite
|
244
|
+
If None (default), use the current settings
|
245
|
+
auto_fix: Whether to automatically fix issues in the filter graph
|
152
246
|
|
153
247
|
Returns:
|
154
|
-
|
155
|
-
|
248
|
+
A tuple of (stdout_bytes, stderr_bytes), which will be empty bytes
|
249
|
+
objects if the respective capture_* parameter is False
|
250
|
+
|
251
|
+
Raises:
|
252
|
+
FFMpegExecuteError: If the FFmpeg process returns a non-zero exit code
|
253
|
+
|
254
|
+
Example:
|
255
|
+
```python
|
256
|
+
# Process a video file
|
257
|
+
stdout, stderr = ffmpeg.input("input.mp4").output("output.mp4").run()
|
258
|
+
|
259
|
+
# Capture FFmpeg's output
|
260
|
+
stdout, stderr = (
|
261
|
+
ffmpeg.input("input.mp4").output("output.mp4").run(capture_stderr=True)
|
262
|
+
)
|
263
|
+
print(stderr.decode()) # Print FFmpeg's progress information
|
264
|
+
```
|
156
265
|
"""
|
157
266
|
|
158
267
|
process = self.run_async(
|
typed_ffmpeg/dag/io/_input.py
CHANGED
@@ -6,6 +6,7 @@ from typing import Any
|
|
6
6
|
|
7
7
|
from ...streams.av import AVStream
|
8
8
|
from ...types import Boolean, Double, Float, Int, String, Time
|
9
|
+
from ...utils.forzendict import FrozenDict
|
9
10
|
from ..nodes import InputNode
|
10
11
|
|
11
12
|
|
@@ -195,5 +196,5 @@ def input(
|
|
195
196
|
}
|
196
197
|
|
197
198
|
return InputNode(
|
198
|
-
filename=str(filename), kwargs=
|
199
|
+
filename=str(filename), kwargs=FrozenDict(options | (extra_options or {}))
|
199
200
|
).stream()
|
typed_ffmpeg/dag/io/_output.py
CHANGED
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
5
5
|
from typing import Any
|
6
6
|
|
7
7
|
from ...types import Boolean, Float, Func, Int, Int64, String, Time
|
8
|
+
from ...utils.forzendict import FrozenDict
|
8
9
|
from ..nodes import FilterableStream, OutputNode, OutputStream
|
9
10
|
|
10
11
|
|
@@ -318,5 +319,5 @@ def output(
|
|
318
319
|
return OutputNode(
|
319
320
|
inputs=streams,
|
320
321
|
filename=str(filename),
|
321
|
-
kwargs=
|
322
|
+
kwargs=FrozenDict(options | (extra_options or {})),
|
322
323
|
).stream()
|