Skip to content

Commit 3a211bc

Browse files
committed
Merge branch 'main' into update-docs
2 parents c3503fb + 4fd16e1 commit 3a211bc

2 files changed

Lines changed: 53 additions & 23 deletions

File tree

src/ffmpegio/filtergraph.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
from contextlib import contextmanager
100100
from functools import partial, reduce
101101
from copy import deepcopy
102+
import os
102103
import re
103104
from subprocess import PIPE
104105
from tempfile import NamedTemporaryFile
@@ -2340,43 +2341,71 @@ def rattach(self, left, right_on=None, left_on=None):
23402341

23412342
@contextmanager
23422343
def as_script_file(self):
2343-
"""return file-like object with filtergraph description
2344+
"""return script file containing the filtergraph description
23442345
2345-
:yield: temporary file with written filtergraph description
2346-
:rtype: file-like object
2346+
:yield: path of a temporary text file with filtergraph description
2347+
:rtype: str
23472348
2348-
The created file-like object can be used just like a normal file within
2349-
a `with` statement. Use this function to pipe in a long filtergraph
2350-
description with `filter_complex_script` or `filter_script` FFmpeg options.
2351-
The option value shall be set to `'pipe:x'` where x is the pipe's descriptor.
2352-
(`'pipe:0'` if using standard input).
2349+
This method is intended to work with the `filter_script` and
2350+
`filter_complex_script` FFmpeg options, by creating a temporary text file
2351+
containing the filtergraph description.
23532352
23542353
..note::
23552354
Only use this function when the filtergraph description is too long for
2356-
OS to handle it as an command argument. Presenting the filtergraph with
2357-
a `filter_complex` or `filter` option is a faster solution.
2355+
OS to handle it. Presenting the filtergraph with a `filter_complex` or
2356+
`filter` option to FFmpeg is always a faster solution.
2357+
2358+
Moreover, if `stdin` is available, i.e., not for a write or filter
2359+
operation, it is more performant to pass the long filtergraph object
2360+
to the subprocess' `input` argument instead of using this method.
2361+
2362+
Use this method with a `with` statement. How to incorporate its output
2363+
with `ffmpegprocess` depends on the `as_file_obj` argument.
23582364
23592365
..example::
2360-
2361-
..codeblock::python
23622366
2363-
fg = ffmpegio.FilterGraph(...) # a very long filtergraph
2367+
The following example illustrates a usecase for a video SISO filtergraph:
2368+
2369+
..codeblock::python
2370+
2371+
# assume `fg` is a SISO video filter Graph object
2372+
2373+
with fg.as_script_file() as script_path:
2374+
ffmpegio.ffmpegprocess.run(
2375+
{
2376+
'inputs': [('input.mp4', None)]
2377+
'outputs': [('output.mp4', {'filter_script:v': script_path})]
2378+
})
2379+
2380+
As noted above, a performant alternative is to use an input pipe and
2381+
feed the filtergraph description directly:
2382+
2383+
..codeblock::python
23642384
2365-
with fg.as_script_file(self) as f:
23662385
ffmpegio.ffmpegprocess.run(
23672386
{
23682387
'inputs': [('input.mp4', None)]
2369-
'outputs': [('output.mp4', {'filter_script:v': f})]
2370-
}, stdin=f)
2388+
'outputs': [('output.mp4', {'filter_script:v': 'pipe:0'})]
2389+
},
2390+
input=str(fg))
2391+
2392+
Note that `pipe:0` must be used and not the shorthand `'-'` unlike
2393+
the input url.
2394+
23712395
"""
23722396

23732397
# populate the file with filtergraph expression
2374-
temp_file = NamedTemporaryFile("w+t", delete=False)
2398+
temp_file = NamedTemporaryFile("wt", delete=False)
23752399
temp_file.write(str(self))
2376-
temp_file.seek(0)
2400+
temp_file.close()
2401+
2402+
try:
2403+
# present the file to the caller in the context
2404+
yield temp_file.name
23772405

2378-
# present the file to the caller in the context
2379-
yield temp_file
2406+
finally:
2407+
if temp_file:
2408+
os.remove(temp_file.name)
23802409

23812410

23822411
# dict: stores filter construction functions

tests/test_filtergraph.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,14 @@ def test_filter_empty_handling():
290290

291291
def test_script():
292292
fg = fgb.Graph("trim=duration=1")
293-
with fg.as_script_file() as f, TemporaryDirectory() as dir:
293+
with fg.as_script_file() as script, TemporaryDirectory() as dir:
294294
out = ffmpegprocess.run(
295295
{
296296
"inputs": [(path.join("tests", "assets", "sample.mp4"), None)],
297-
"outputs": [(path.join(dir, "output.mp4"), {"filter_script:v": "pipe:0"})],
297+
"outputs": [
298+
(path.join(dir, "output.mp4"), {"filter_script:v": script})
299+
],
298300
},
299-
stdin=f,
300301
)
301302
assert not out.returncode
302303

0 commit comments

Comments
 (0)