Skip to content

Commit eeb87af

Browse files
committed
Add mpeg: a ffmpeg facade
1 parent 81a0cf6 commit eeb87af

File tree

2 files changed

+127
-1
lines changed

2 files changed

+127
-1
lines changed

auto_editor/__main__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def main_options(parser: ArgumentParser) -> ArgumentParser:
272272

273273

274274
def main() -> None:
275-
subcommands = ("test", "info", "levels", "subdump", "desc", "repl", "palet")
275+
subcommands = ("test", "info", "levels", "subdump", "desc", "repl", "palet", "mpeg")
276276

277277
if len(sys.argv) > 1 and sys.argv[1] in subcommands:
278278
obj = __import__(

auto_editor/subcommands/mpeg.py

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import os
2+
import sys
3+
4+
import av
5+
import av._core
6+
7+
av.logging.set_level(av.logging.VERBOSE)
8+
9+
10+
def remux(
11+
prompt: bool, vn: bool, an: bool, sn: bool, input_file: str, output_file: str
12+
) -> None:
13+
try:
14+
input_container = av.open(input_file, "r")
15+
except av.error.FileNotFoundError:
16+
sys.stderr.write(f"Error opening input file {input_file}.\n")
17+
sys.exit(1)
18+
19+
if prompt and os.path.exists(output_file):
20+
result = input(f"File '{output_file}' already exists. Overwrite? [y/N] ")
21+
if result.lower() != "y":
22+
sys.stderr.write("Not overwriting - exiting\n")
23+
sys.exit(1)
24+
25+
output_container = av.open(output_file, "w")
26+
27+
stream_mapping: dict[int, av.stream.Stream] = {}
28+
for stream in input_container.streams:
29+
if (
30+
(stream.type == "video" and vn)
31+
or (stream.type == "audio" and an)
32+
or (stream.type == "subtitle" and sn)
33+
):
34+
continue
35+
36+
output_stream = output_container.add_stream(template=stream)
37+
stream_mapping[stream.index] = output_stream
38+
39+
for packet in input_container.demux():
40+
if packet.dts is None:
41+
continue
42+
43+
if packet.stream.index in stream_mapping:
44+
packet.stream = stream_mapping[packet.stream.index]
45+
output_container.mux(packet)
46+
47+
input_container.close()
48+
output_container.close()
49+
50+
51+
def parse_args(args: list[str]) -> None:
52+
inputs = []
53+
outputs = []
54+
55+
print_bf = False
56+
print_banner = True
57+
prompt = True
58+
vn = False
59+
an = False
60+
sn = False
61+
62+
i = 0
63+
while i < len(args):
64+
arg = args[i]
65+
66+
if arg == "-y":
67+
prompt = False
68+
elif arg == "-hide_banner":
69+
print_banner = False
70+
elif arg == "-vn":
71+
vn = True
72+
elif arg == "-an":
73+
an = True
74+
elif arg == "-sn":
75+
sn = True
76+
elif arg == "-bsfs":
77+
print_bf = True
78+
elif arg == "-i":
79+
i += 1
80+
if i < len(args):
81+
inputs.append(args[i])
82+
else:
83+
outputs.append(arg)
84+
i += 1
85+
86+
if print_banner:
87+
by_config = {}
88+
for libname, config in sorted(av._core.library_meta.items()):
89+
version = config["version"]
90+
if version[0] >= 0:
91+
by_config.setdefault(
92+
(config["configuration"], config["license"]), []
93+
).append((libname, config))
94+
95+
sys.stderr.write("ffmpeg version 6.1.1\n")
96+
sys.stderr.write(" built with\n")
97+
for (config, license), libs in by_config.items():
98+
sys.stderr.write(f" configuration: {config}\n")
99+
for libname, config in libs:
100+
version = config["version"]
101+
sys.stderr.write(
102+
f" {libname:<13} {version[0]:3d}.{version[1]:3d}.{version[2]:3d}\n"
103+
)
104+
105+
if print_bf:
106+
print("Bitstream filters:")
107+
return
108+
109+
if not outputs:
110+
if args:
111+
sys.stderr.write("At least one output file must be specified\n")
112+
sys.exit(1)
113+
114+
if not inputs:
115+
sys.stderr.write("Output file does not contain any stream\n")
116+
sys.exit(1)
117+
118+
remux(prompt, vn, an, sn, inputs[0], outputs[0])
119+
120+
121+
def main(sys_args: list[str] = sys.argv[1:]) -> None:
122+
parse_args(sys_args)
123+
124+
125+
if __name__ == "__main__":
126+
main()

0 commit comments

Comments
 (0)