Skip to content

Commit e5f65d3

Browse files
committed
mpeg: add -loglevel
1 parent eeb87af commit e5f65d3

File tree

1 file changed

+106
-25
lines changed

1 file changed

+106
-25
lines changed

auto_editor/subcommands/mpeg.py

Lines changed: 106 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
11
import os
22
import sys
3+
from dataclasses import dataclass
34

45
import av
56
import av._core
7+
from av.container import InputContainer, OutputContainer
68

7-
av.logging.set_level(av.logging.VERBOSE)
89

10+
@dataclass(slots=True)
11+
class AvLog:
12+
level_set: int
913

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)
14+
def level(self, val: int, msg: str) -> None:
15+
if self.level_set < val:
16+
return
1817

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)
18+
if val == 24:
19+
sys.stderr.write(f"\033[38;5;226;40m{msg}\033[0m\n")
20+
elif val == 16:
21+
sys.stderr.write(f"\033[38;5;208;40m{msg}\033[0m\n")
22+
elif val == 8:
23+
sys.stderr.write(f"\033[31;40m{msg}\033[0m\n")
24+
else:
25+
sys.stderr.write(f"{msg}\n")
2426

25-
output_container = av.open(output_file, "w")
2627

28+
def transcode(
29+
log: AvLog,
30+
vn: bool,
31+
an: bool,
32+
sn: bool,
33+
input_container: InputContainer,
34+
output_container: OutputContainer,
35+
) -> None:
2736
stream_mapping: dict[int, av.stream.Stream] = {}
2837
for stream in input_container.streams:
2938
if (
@@ -48,13 +57,50 @@ def remux(
4857
output_container.close()
4958

5059

51-
def parse_args(args: list[str]) -> None:
60+
def parse_loglevel(args: list[str]) -> tuple[int, bool]:
61+
log_level = 32
62+
hide_banner = False
63+
64+
def parse_level(v: str) -> int:
65+
if v in ("quiet", "-8"):
66+
return -8
67+
if v in ("panic", "0"):
68+
return 0
69+
if v in ("fatal", "8"):
70+
return 8
71+
if v in ("error", "16"):
72+
return 16
73+
if v in ("warning", "24"):
74+
return 24
75+
if v in ("info", "32"):
76+
return 32
77+
if v in ("verbose", "40"):
78+
return 40
79+
if v in ("debug", "48"):
80+
return 48
81+
if v in ("trace", "56"):
82+
return 56
83+
return 0
84+
85+
i = 0
86+
while i < len(args):
87+
arg = args[i]
88+
if arg == "-hide_banner":
89+
hide_banner = True
90+
elif arg == "-loglevel":
91+
i += 1
92+
log_level = parse_level(args[i])
93+
i += 1
94+
95+
return log_level, hide_banner
96+
97+
98+
def parse_args(log: AvLog, hide_banner: bool, args: list[str]) -> None:
5299
inputs = []
53100
outputs = []
54101

55102
print_bf = False
56-
print_banner = True
57-
prompt = True
103+
overwrite = None
58104
vn = False
59105
an = False
60106
sn = False
@@ -64,9 +110,14 @@ def parse_args(args: list[str]) -> None:
64110
arg = args[i]
65111

66112
if arg == "-y":
67-
prompt = False
113+
overwrite = True
114+
elif arg == "-n":
115+
overwrite = False
68116
elif arg == "-hide_banner":
69-
print_banner = False
117+
pass
118+
elif arg == "-log_level":
119+
i += 1
120+
pass
70121
elif arg == "-vn":
71122
vn = True
72123
elif arg == "-an":
@@ -83,7 +134,7 @@ def parse_args(args: list[str]) -> None:
83134
outputs.append(arg)
84135
i += 1
85136

86-
if print_banner:
137+
if not hide_banner:
87138
by_config = {}
88139
for libname, config in sorted(av._core.library_meta.items()):
89140
version = config["version"]
@@ -106,20 +157,50 @@ def parse_args(args: list[str]) -> None:
106157
print("Bitstream filters:")
107158
return
108159

160+
if not outputs and not inputs:
161+
sys.stderr.write(
162+
"Universal media converter\nusage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...\n\n"
163+
)
164+
log.level(24, "Use -h to get full help or, even better, run 'man ffmpeg'")
165+
109166
if not outputs:
110167
if args:
111-
sys.stderr.write("At least one output file must be specified\n")
168+
log.level(16, "At least one output file must be specified")
112169
sys.exit(1)
113170

114171
if not inputs:
115-
sys.stderr.write("Output file does not contain any stream\n")
172+
log.level(8, "Output file does not contain any stream")
116173
sys.exit(1)
117174

118-
remux(prompt, vn, an, sn, inputs[0], outputs[0])
175+
input_containers = []
176+
for input_file in inputs:
177+
try:
178+
input_containers.append(av.open(input_file, "r"))
179+
except av.error.FileNotFoundError:
180+
log.level(8, f"Error opening input file {input_file}.")
181+
sys.exit(1)
182+
183+
output_containers = []
184+
for output_file in outputs:
185+
if os.path.exists(output_file):
186+
if overwrite is None:
187+
res = input(f"File '{output_file}' already exists. Overwrite? [y/N] ")
188+
if res.lower() != "y":
189+
log.level(16, "Not overwriting - exiting")
190+
sys.exit(1)
191+
elif not overwrite:
192+
log.level(16, f"File '{output_file}' already exists. Exiting.")
193+
log.level(8, f"Error opening output file {output_file}.")
194+
sys.exit(1)
195+
196+
output_containers.append(av.open(output_file, "w"))
197+
198+
transcode(log, vn, an, sn, input_containers[0], output_containers[0])
119199

120200

121201
def main(sys_args: list[str] = sys.argv[1:]) -> None:
122-
parse_args(sys_args)
202+
log_level, hide_banner = parse_loglevel(sys_args)
203+
parse_args(AvLog(log_level), hide_banner, sys_args)
123204

124205

125206
if __name__ == "__main__":

0 commit comments

Comments
 (0)