auto-editor 26.1.1__py3-none-any.whl → 26.2.0__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.
Files changed (39) hide show
  1. auto_editor/__init__.py +1 -1
  2. auto_editor/__main__.py +10 -15
  3. auto_editor/analyze.py +1 -1
  4. auto_editor/{subcommands → cmds}/cache.py +2 -2
  5. auto_editor/{subcommands → cmds}/info.py +4 -4
  6. auto_editor/{subcommands → cmds}/levels.py +42 -11
  7. auto_editor/{subcommands → cmds}/test.py +3 -3
  8. auto_editor/edit.py +21 -10
  9. auto_editor/ffwrapper.py +3 -2
  10. auto_editor/formats/fcp11.py +4 -4
  11. auto_editor/formats/fcp7.py +6 -6
  12. auto_editor/formats/json.py +1 -1
  13. auto_editor/lang/json.py +2 -2
  14. auto_editor/lang/palet.py +5 -5
  15. auto_editor/lang/stdenv.py +1 -1
  16. auto_editor/lib/data_structs.py +0 -2
  17. auto_editor/render/audio.py +4 -4
  18. auto_editor/render/subtitle.py +2 -2
  19. auto_editor/render/video.py +20 -8
  20. auto_editor/utils/bar.py +1 -1
  21. auto_editor/utils/container.py +4 -10
  22. auto_editor/utils/func.py +1 -1
  23. auto_editor/utils/log.py +4 -0
  24. auto_editor/utils/types.py +4 -3
  25. auto_editor/vanparse.py +1 -1
  26. auto_editor/wavfile.py +3 -3
  27. {auto_editor-26.1.1.dist-info → auto_editor-26.2.0.dist-info}/METADATA +2 -2
  28. auto_editor-26.2.0.dist-info/RECORD +56 -0
  29. {auto_editor-26.1.1.dist-info → auto_editor-26.2.0.dist-info}/WHEEL +1 -1
  30. auto_editor-26.2.0.dist-info/entry_points.txt +6 -0
  31. auto_editor-26.1.1.dist-info/RECORD +0 -56
  32. auto_editor-26.1.1.dist-info/entry_points.txt +0 -6
  33. /auto_editor/{subcommands → cmds}/__init__.py +0 -0
  34. /auto_editor/{subcommands → cmds}/desc.py +0 -0
  35. /auto_editor/{subcommands → cmds}/palet.py +0 -0
  36. /auto_editor/{subcommands → cmds}/repl.py +0 -0
  37. /auto_editor/{subcommands → cmds}/subdump.py +0 -0
  38. {auto_editor-26.1.1.dist-info → auto_editor-26.2.0.dist-info}/LICENSE +0 -0
  39. {auto_editor-26.1.1.dist-info → auto_editor-26.2.0.dist-info}/top_level.txt +0 -0
auto_editor/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "26.1.1"
1
+ __version__ = "26.2.0"
auto_editor/__main__.py CHANGED
@@ -188,6 +188,12 @@ def main_options(parser: ArgumentParser) -> ArgumentParser:
188
188
  metavar="BITRATE",
189
189
  help="Set the number of bits per second for video",
190
190
  )
191
+ parser.add_argument(
192
+ "-vprofile",
193
+ "-profile:v",
194
+ metavar="PROFILE",
195
+ help="Set the video profile. For h264: high, main, or baseline",
196
+ )
191
197
  parser.add_argument(
192
198
  "--scale",
193
199
  type=number,
@@ -286,21 +292,10 @@ def download_video(my_input: str, args: Args, log: Log) -> str:
286
292
 
287
293
 
288
294
  def main() -> None:
289
- subcommands = (
290
- "test",
291
- "info",
292
- "levels",
293
- "subdump",
294
- "desc",
295
- "repl",
296
- "palet",
297
- "cache",
298
- )
299
-
300
- if len(sys.argv) > 1 and sys.argv[1] in subcommands:
301
- obj = __import__(
302
- f"auto_editor.subcommands.{sys.argv[1]}", fromlist=["subcommands"]
303
- )
295
+ commands = ("test", "info", "levels", "subdump", "desc", "repl", "palet", "cache")
296
+
297
+ if len(sys.argv) > 1 and sys.argv[1] in commands:
298
+ obj = __import__(f"auto_editor.cmds.{sys.argv[1]}", fromlist=["cmds"])
304
299
  obj.main(sys.argv[2:])
305
300
  return
306
301
 
auto_editor/analyze.py CHANGED
@@ -155,7 +155,7 @@ def iter_motion(
155
155
 
156
156
  def obj_tag(path: Path, kind: str, tb: Fraction, obj: Sequence[object]) -> str:
157
157
  mod_time = int(path.stat().st_mtime)
158
- key = f"{path}:{mod_time:x}:{tb}:" + ",".join(f"{v}" for v in obj)
158
+ key = f"{path.name}:{mod_time:x}:{tb}:" + ",".join(f"{v}" for v in obj)
159
159
  part1 = sha1(key.encode()).hexdigest()[:16]
160
160
 
161
161
  return f"{part1}{kind}"
@@ -12,7 +12,7 @@ from auto_editor import __version__
12
12
  def main(sys_args: list[str] = sys.argv[1:]) -> None:
13
13
  cache_dir = os.path.join(gettempdir(), f"ae-{__version__}")
14
14
 
15
- if sys_args and sys_args[0] in ("clean", "clear"):
15
+ if sys_args and sys_args[0] in {"clean", "clear"}:
16
16
  rmtree(cache_dir, ignore_errors=True)
17
17
  return
18
18
 
@@ -26,7 +26,7 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
26
26
  return
27
27
 
28
28
  def format_bytes(size: float) -> str:
29
- for unit in ("B", "KiB", "MiB", "GiB", "TiB"):
29
+ for unit in {"B", "KiB", "MiB", "GiB", "TiB"}:
30
30
  if size < 1024:
31
31
  return f"{size:.2f} {unit}"
32
32
  size /= 1024
@@ -98,7 +98,7 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
98
98
 
99
99
  continue
100
100
 
101
- if ext in (".xml", ".fcpxml", ".mlt"):
101
+ if ext in {".xml", ".fcpxml", ".mlt"}:
102
102
  file_info[file] = {"type": "timeline"}
103
103
  continue
104
104
 
@@ -169,7 +169,7 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
169
169
  return
170
170
 
171
171
  def is_null(key: str, val: object) -> bool:
172
- return val is None or (key in ("bitrate", "duration") and val == 0.0)
172
+ return val is None or (key in {"bitrate", "duration"} and val == 0.0)
173
173
 
174
174
  def stream_to_text(text: str, label: str, streams: list[dict[str, Any]]) -> str:
175
175
  if len(streams) > 0:
@@ -183,12 +183,12 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
183
183
  sep = "x" if key == "resolution" else ":"
184
184
  value = sep.join(f"{x}" for x in value)
185
185
 
186
- if key in (
186
+ if key in {
187
187
  "color_range",
188
188
  "color_space",
189
189
  "color_transfer",
190
190
  "color_primaries",
191
- ):
191
+ }:
192
192
  if key == "color_range":
193
193
  if value == 1:
194
194
  text += " - color range: 1 (tv)\n"
@@ -59,7 +59,7 @@ def levels_options(parser: ArgumentParser) -> ArgumentParser:
59
59
  def print_arr(arr: NDArray) -> None:
60
60
  print("")
61
61
  print("@start")
62
- if arr.dtype == np.float64:
62
+ if arr.dtype in {np.float64, np.float32, np.float16}:
63
63
  for a in arr:
64
64
  sys.stdout.write(f"{a:.20f}\n")
65
65
  elif arr.dtype == np.bool_:
@@ -131,18 +131,49 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
131
131
  levels = Levels(src, tb, bar, False, log, strict=True)
132
132
  try:
133
133
  if method == "audio":
134
- container = av.open(src.path, "r")
135
- audio_stream = container.streams.audio[obj["stream"]]
136
- log.experimental(audio_stream.codec)
137
- print_arr_gen(iter_audio(audio_stream, tb))
138
- container.close()
134
+ if (arr := levels.read_cache("audio", (obj["stream"],))) is not None:
135
+ print_arr(arr)
136
+ else:
137
+ container = av.open(src.path, "r")
138
+ audio_stream = container.streams.audio[obj["stream"]]
139
+ log.experimental(audio_stream.codec)
140
+
141
+ values = []
142
+
143
+ def value_storing_generator() -> Iterator[np.float32]:
144
+ for value in iter_audio(audio_stream, tb):
145
+ values.append(value)
146
+ yield value
147
+
148
+ print_arr_gen(value_storing_generator())
149
+ container.close()
150
+
151
+ cache_array = np.array(values, dtype=np.float32)
152
+ levels.cache(cache_array, "audio", (obj["stream"],))
139
153
 
140
154
  elif method == "motion":
141
- container = av.open(src.path, "r")
142
- video_stream = container.streams.video[obj["stream"]]
143
- log.experimental(video_stream.codec)
144
- print_arr_gen(iter_motion(video_stream, tb, obj["blur"], obj["width"]))
145
- container.close()
155
+ mobj = (obj["stream"], obj["width"], obj["blur"])
156
+ if (arr := levels.read_cache("motion", mobj)) is not None:
157
+ print_arr(arr)
158
+ else:
159
+ container = av.open(src.path, "r")
160
+ video_stream = container.streams.video[obj["stream"]]
161
+ log.experimental(video_stream.codec)
162
+
163
+ values = []
164
+
165
+ def value_storing_generator() -> Iterator[np.float32]:
166
+ for value in iter_motion(
167
+ video_stream, tb, obj["blur"], obj["width"]
168
+ ):
169
+ values.append(value)
170
+ yield value
171
+
172
+ print_arr_gen(value_storing_generator())
173
+ container.close()
174
+
175
+ cache_array = np.array(values, dtype=np.float32)
176
+ levels.cache(cache_array, "motion", mobj)
146
177
 
147
178
  elif method == "subtitle":
148
179
  print_arr(levels.subtitle(**obj))
@@ -723,13 +723,13 @@ def main(sys_args: list[str] | None = None):
723
723
 
724
724
  tests = []
725
725
 
726
- if args.category in ("palet", "all"):
726
+ if args.category in {"palet", "all"}:
727
727
  tests.extend([palet_python_bridge, palet_scripts])
728
728
 
729
- if args.category in ("sub", "all"):
729
+ if args.category in {"sub", "all"}:
730
730
  tests.extend([info, levels, subdump, desc])
731
731
 
732
- if args.category in ("cli", "all"):
732
+ if args.category in {"cli", "all"}:
733
733
  tests.extend(
734
734
  [
735
735
  premiere,
auto_editor/edit.py CHANGED
@@ -8,7 +8,7 @@ from subprocess import run
8
8
  from typing import Any
9
9
 
10
10
  import av
11
- from av import AudioResampler
11
+ from av import AudioResampler, Codec
12
12
 
13
13
  from auto_editor.ffwrapper import FileInfo, initFileInfo
14
14
  from auto_editor.lib.contracts import is_int, is_str
@@ -81,6 +81,7 @@ def set_video_codec(
81
81
  return codec
82
82
 
83
83
  if codec == "copy":
84
+ log.deprecated("The `copy` codec is deprecated. auto-editor always re-encodes")
84
85
  if src is None:
85
86
  log.error("No input to copy its codec from.")
86
87
  if not src.videos:
@@ -88,7 +89,13 @@ def set_video_codec(
88
89
  codec = src.videos[0].codec
89
90
 
90
91
  if ctr.vcodecs is not None and codec not in ctr.vcodecs:
91
- log.error(codec_error.format(codec, out_ext))
92
+ try:
93
+ cobj = Codec(codec, "w")
94
+ except av.codec.codec.UnknownCodecError:
95
+ log.error(f"Unknown encoder: {codec}")
96
+ # Normalize encoder names
97
+ if cobj.id not in (Codec(x, "w").id for x in ctr.vcodecs):
98
+ log.error(codec_error.format(codec, out_ext))
92
99
 
93
100
  return codec
94
101
 
@@ -101,18 +108,16 @@ def set_audio_codec(
101
108
  codec = "aac"
102
109
  else:
103
110
  codec = src.audios[0].codec
104
- ctx = av.Codec(codec)
105
- if ctx.audio_formats is None:
111
+ if av.Codec(codec, "w").audio_formats is None:
106
112
  codec = "aac"
107
113
  if codec not in ctr.acodecs and ctr.default_aud != "none":
108
114
  codec = ctr.default_aud
109
- if codec == "mp3float":
110
- codec = "mp3"
111
115
  if codec is None:
112
116
  codec = "aac"
113
117
  return codec
114
118
 
115
119
  if codec == "copy":
120
+ log.deprecated("The `copy` codec is deprecated. auto-editor always re-encodes")
116
121
  if src is None:
117
122
  log.error("No input to copy its codec from.")
118
123
  if not src.audios:
@@ -120,7 +125,13 @@ def set_audio_codec(
120
125
  codec = src.audios[0].codec
121
126
 
122
127
  if ctr.acodecs is None or codec not in ctr.acodecs:
123
- log.error(codec_error.format(codec, out_ext))
128
+ try:
129
+ cobj = Codec(codec, "w")
130
+ except av.codec.codec.UnknownCodecError:
131
+ log.error(f"Unknown encoder: {codec}")
132
+ # Normalize encoder names
133
+ if cobj.id not in (Codec(x, "w").id for x in ctr.acodecs):
134
+ log.error(codec_error.format(codec, out_ext))
124
135
 
125
136
  return codec
126
137
 
@@ -240,7 +251,7 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
240
251
  make_json_timeline(export_ops["api"], output, tl, log)
241
252
  return
242
253
 
243
- if export in ("premiere", "resolve-fcp7"):
254
+ if export in {"premiere", "resolve-fcp7"}:
244
255
  from auto_editor.formats.fcp7 import fcp7_write_xml
245
256
 
246
257
  is_resolve = export.startswith("resolve")
@@ -301,7 +312,7 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
301
312
  # Setup audio
302
313
  if audio_paths:
303
314
  try:
304
- audio_encoder = av.Codec(args.audio_codec)
315
+ audio_encoder = av.Codec(args.audio_codec, "w")
305
316
  except av.FFmpegError as e:
306
317
  log.error(e)
307
318
  if audio_encoder.audio_formats is None:
@@ -449,7 +460,7 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
449
460
 
450
461
  log.stop_timer()
451
462
 
452
- if not args.no_open and export in ("default", "audio"):
463
+ if not args.no_open and export in {"default", "audio"}:
453
464
  if args.player is None:
454
465
  if sys.platform == "win32":
455
466
  try:
auto_editor/ffwrapper.py CHANGED
@@ -111,7 +111,7 @@ def initFileInfo(path: str, log: Log) -> FileInfo:
111
111
  vdur = 0.0
112
112
 
113
113
  fps = v.average_rate
114
- if (fps is None or fps < 1) and v.name in ("png", "mjpeg", "webp"):
114
+ if (fps is None or fps < 1) and v.name in {"png", "mjpeg", "webp"}:
115
115
  fps = Fraction(25)
116
116
  if fps is None or fps == 0:
117
117
  fps = Fraction(30)
@@ -147,9 +147,10 @@ def initFileInfo(path: str, log: Log) -> FileInfo:
147
147
  adur = float(a.duration * a.time_base)
148
148
 
149
149
  a_cc = a.codec_context
150
+ name = a_cc.name if a_cc.name != "mp3float" else "mp3"
150
151
  audios += (
151
152
  AudioStream(
152
- a_cc.name,
153
+ name,
153
154
  0 if a_cc.sample_rate is None else a_cc.sample_rate,
154
155
  a.layout.name,
155
156
  a_cc.channels,
@@ -36,7 +36,7 @@ def get_colorspace(src: FileInfo) -> str:
36
36
  return "6-1-6 (Rec. 601 NTSC)"
37
37
  if s.color_primaries == 9: # "bt2020"
38
38
  # See: https://video.stackexchange.com/questions/22059/how-to-identify-hdr-video
39
- if s.color_transfer in (16, 18): # "smpte2084" "arib-std-b67"
39
+ if s.color_transfer in {16, 18}: # "smpte2084" "arib-std-b67"
40
40
  return "9-18-9 (Rec. 2020 HLG)"
41
41
  return "9-1-9 (Rec. 2020)"
42
42
 
@@ -80,7 +80,7 @@ def fcp11_write_xml(
80
80
  SubElement(
81
81
  resources,
82
82
  "format",
83
- id=f"r{i*2+1}",
83
+ id=f"r{i * 2 + 1}",
84
84
  name=make_name(one_src, tl.tb),
85
85
  frameDuration=fraction(1),
86
86
  width=f"{tl.res[0]}",
@@ -90,11 +90,11 @@ def fcp11_write_xml(
90
90
  r2 = SubElement(
91
91
  resources,
92
92
  "asset",
93
- id=f"r{i*2+2}",
93
+ id=f"r{i * 2 + 2}",
94
94
  name=one_src.path.stem,
95
95
  start="0s",
96
96
  hasVideo="1" if one_src.videos else "0",
97
- format=f"r{i*2+1}",
97
+ format=f"r{i * 2 + 1}",
98
98
  hasAudio="1" if one_src.audios else "0",
99
99
  audioSources="1",
100
100
  audioChannels=f"{2 if not one_src.audios else one_src.audios[0].channels}",
@@ -99,7 +99,7 @@ def set_tb_ntsc(tb: Fraction) -> tuple[int, str]:
99
99
  return 60, "TRUE"
100
100
 
101
101
  ctb = ceil(tb)
102
- if ctb not in (24, 30, 60) and ctb * Fraction(999, 1000) == tb:
102
+ if ctb not in {24, 30, 60} and ctb * Fraction(999, 1000) == tb:
103
103
  return ctb, "TRUE"
104
104
 
105
105
  return int(tb), "FALSE"
@@ -151,7 +151,7 @@ SUPPORTED_EFFECTS = ("timeremap",)
151
151
 
152
152
  def read_filters(clipitem: Element, log: Log) -> float:
153
153
  for effect_tag in clipitem:
154
- if effect_tag.tag in ("enabled", "start", "end"):
154
+ if effect_tag.tag in {"enabled", "start", "end"}:
155
155
  continue
156
156
  if len(effect_tag) < 3:
157
157
  log.error("<effect> requires: <effectid> <name> and one <parameter>")
@@ -495,7 +495,7 @@ def fcp7_write_xml(name: str, output: str, resolve: bool, tl: v3) -> None:
495
495
  file_defs: set[str] = set() # Contains urls
496
496
 
497
497
  for src in set(tl.sources):
498
- the_id = f"file-{len(src_to_id)+1}"
498
+ the_id = f"file-{len(src_to_id) + 1}"
499
499
  src_to_url[src] = f"{src.path.resolve()}"
500
500
  src_to_id[src] = the_id
501
501
 
@@ -541,7 +541,7 @@ def fcp7_write_xml(name: str, output: str, resolve: bool, tl: v3) -> None:
541
541
  _in = f"{clip.offset}"
542
542
  _out = f"{clip.offset + clip.dur}"
543
543
 
544
- this_clipid = f"clipitem-{j+1}"
544
+ this_clipid = f"clipitem-{j + 1}"
545
545
  clipitem = ET.SubElement(track, "clipitem", id=this_clipid)
546
546
  ET.SubElement(clipitem, "name").text = src.path.stem
547
547
  ET.SubElement(clipitem, "enabled").text = "TRUE"
@@ -562,14 +562,14 @@ def fcp7_write_xml(name: str, output: str, resolve: bool, tl: v3) -> None:
562
562
  link = ET.SubElement(clipitem, "link")
563
563
  ET.SubElement(
564
564
  link, "linkclipref"
565
- ).text = f"clipitem-{(len(tl.v[0]))+j+1}"
565
+ ).text = f"clipitem-{(len(tl.v[0])) + j + 1}"
566
566
  continue
567
567
 
568
568
  for i in range(1 + len(src.audios) * 2): # `2` because stereo.
569
569
  link = ET.SubElement(clipitem, "link")
570
570
  ET.SubElement(
571
571
  link, "linkclipref"
572
- ).text = f"clipitem-{(i*(len(tl.v[0])))+j+1}"
572
+ ).text = f"clipitem-{(i * (len(tl.v[0]))) + j + 1}"
573
573
  ET.SubElement(link, "mediatype").text = "video" if i == 0 else "audio"
574
574
  ET.SubElement(link, "trackindex").text = f"{max(i, 1)}"
575
575
  ET.SubElement(link, "clipindex").text = f"{j + 1}"
@@ -239,7 +239,7 @@ def read_json(path: str, log: Log) -> v3:
239
239
 
240
240
 
241
241
  def make_json_timeline(ver: int, out: str | int, tl: v3, log: Log) -> None:
242
- if ver not in (3, 1):
242
+ if ver not in {3, 1}:
243
243
  log.error(f"Version {ver} is not supported!")
244
244
 
245
245
  if isinstance(out, str):
auto_editor/lang/json.py CHANGED
@@ -204,7 +204,7 @@ class Parser:
204
204
  def expr(self) -> Any:
205
205
  self.current_token
206
206
 
207
- if self.current_token.type in (STR, VAL):
207
+ if self.current_token.type in {STR, VAL}:
208
208
  val = self.current_token.value
209
209
  self.eat()
210
210
  return val
@@ -215,7 +215,7 @@ class Parser:
215
215
  my_dic = {}
216
216
  while self.current_token.type != RCUR:
217
217
  if self.current_token.type != STR:
218
- if self.current_token.type in (LBRAC, VAL):
218
+ if self.current_token.type in {LBRAC, VAL}:
219
219
  self.lexer.error("JSON Objects only allow strings as keys")
220
220
  self.lexer.error("Expected closing `}`")
221
221
  key = self.current_token.value
auto_editor/lang/palet.py CHANGED
@@ -218,10 +218,10 @@ class Lexer:
218
218
  self.advance()
219
219
 
220
220
  result = buf.getvalue()
221
- if result in ("t", "T", "true"):
221
+ if result in {"t", "T", "true"}:
222
222
  return Token(VAL, True, self.lineno, self.column)
223
223
 
224
- if result in ("f", "F", "false"):
224
+ if result in {"f", "F", "false"}:
225
225
  return Token(VAL, False, self.lineno, self.column)
226
226
 
227
227
  self.error(f"Unknown hash literal `#{result}`")
@@ -451,7 +451,7 @@ class Parser:
451
451
 
452
452
  self.eat()
453
453
  childs = []
454
- while self.current_token.type not in (RPAREN, RBRAC, RCUR, EOF):
454
+ while self.current_token.type not in {RPAREN, RBRAC, RCUR, EOF}:
455
455
  childs.append(self.expr())
456
456
  return tuple(childs)
457
457
 
@@ -512,7 +512,7 @@ def p_slice(
512
512
 
513
513
  is_iterable = Contract(
514
514
  "iterable?",
515
- lambda v: type(v) in (str, range, list, tuple, dict, Quoted)
515
+ lambda v: type(v) in {str, range, list, tuple, dict, Quoted}
516
516
  or isinstance(v, np.ndarray),
517
517
  )
518
518
  is_boolarr = Contract(
@@ -689,7 +689,7 @@ def my_eval(env: Env, node: object) -> Any:
689
689
  length = len(node[1:])
690
690
  if length > 3:
691
691
  raise MyError(f"{print_str(node[0])}: slice expects 1 argument")
692
- if length in (2, 3):
692
+ if length in {2, 3}:
693
693
  return p_slice(oper, *(my_eval(env, c) for c in node[1:]))
694
694
  if length == 1:
695
695
  return ref(oper, my_eval(env, node[1]))
@@ -283,7 +283,7 @@ def make_standard_env() -> dict[str, Any]:
283
283
  type(node[2]) is tuple
284
284
  and node[2]
285
285
  and type(node[2][0]) is Sym
286
- and node[2][0].val in ("lambda", "λ")
286
+ and node[2][0].val in {"lambda", "λ"}
287
287
  ):
288
288
  terms = node[2][1]
289
289
  body = node[2][2:]
@@ -191,7 +191,6 @@ def display_str(val: object) -> str:
191
191
  return f"{float(val)}"
192
192
  if type(val) is Fraction:
193
193
  return f"{val.numerator}/{val.denominator}"
194
-
195
194
  if type(val) is Quoted or type(val) is tuple:
196
195
  if not val:
197
196
  return "()"
@@ -201,7 +200,6 @@ def display_str(val: object) -> str:
201
200
  result.write(f" {display_str(item)}")
202
201
  result.write(")")
203
202
  return result.getvalue()
204
-
205
203
  if type(val) is list:
206
204
  if not val:
207
205
  return "#()"
@@ -62,7 +62,7 @@ def parse_ebu_bytes(norm: dict, stat: bytes, log: Log) -> tuple[str, str]:
62
62
  except MyError:
63
63
  log.error(f"Invalid loudnorm stats.\n{stat!r}")
64
64
 
65
- for key in ("input_i", "input_tp", "input_lra", "input_thresh", "target_offset"):
65
+ for key in {"input_i", "input_tp", "input_lra", "input_thresh", "target_offset"}:
66
66
  val = float(parsed[key])
67
67
  if val == float("-inf"):
68
68
  parsed[key] = -99
@@ -91,7 +91,7 @@ def apply_audio_normalization(
91
91
  ) -> None:
92
92
  if norm["tag"] == "ebu":
93
93
  first_pass = (
94
- f"i={norm['i']}:lra={norm['lra']}:tp={norm['tp']}:" f"offset={norm['gain']}"
94
+ f"i={norm['i']}:lra={norm['lra']}:tp={norm['tp']}:offset={norm['gain']}"
95
95
  )
96
96
  log.debug(f"audio norm first pass: {first_pass}")
97
97
  with av.open(f"{pre_master}") as container:
@@ -167,10 +167,10 @@ def process_audio_clip(
167
167
  if clip.speed != 1:
168
168
  if clip.speed > 10_000:
169
169
  for _ in range(3):
170
- args.append(graph.add("atempo", f"{clip.speed ** (1/3)}"))
170
+ args.append(graph.add("atempo", f"{clip.speed ** (1 / 3)}"))
171
171
  elif clip.speed > 100:
172
172
  for _ in range(2):
173
- args.append(graph.add("atempo", f"{clip.speed ** 0.5}"))
173
+ args.append(graph.add("atempo", f"{clip.speed**0.5}"))
174
174
  elif clip.speed >= 0.5:
175
175
  args.append(graph.add("atempo", f"{clip.speed}"))
176
176
  else:
@@ -53,7 +53,7 @@ class SubtitleParser:
53
53
  self.codec = codec
54
54
  self.contents = []
55
55
 
56
- if codec == "ass" or codec == "ssa":
56
+ if codec in {"ass", "ssa"}:
57
57
  time_code = re.compile(r"(.*)(\d+:\d+:[\d.]+)(.*)(\d+:\d+:[\d.]+)(.*)")
58
58
  elif codec == "webvtt":
59
59
  time_code = re.compile(r"()(\d+:[\d.]+)( --> )(\d+:[\d.]+)(\n.*)")
@@ -189,7 +189,7 @@ def make_new_subtitles(tl: v3, log: Log) -> list[str]:
189
189
  parser = SubtitleParser(tl.tb)
190
190
  if sub.codec == "ssa":
191
191
  format = "ass"
192
- elif sub.codec in ("webvtt", "ass"):
192
+ elif sub.codec in {"webvtt", "ass"}:
193
193
  format = sub.codec
194
194
  else:
195
195
  log.error(f"Unknown subtitle codec: {sub.codec}")
@@ -54,7 +54,7 @@ allowed_pix_fmt = {
54
54
 
55
55
  def make_solid(width: int, height: int, pix_fmt: str, bg: str) -> av.VideoFrame:
56
56
  hex_color = bg.lstrip("#").upper()
57
- rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
57
+ rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in {0, 2, 4})
58
58
 
59
59
  rgb_array = np.full((height, width, 3), rgb_color, dtype=np.uint8)
60
60
  rgb_frame = av.VideoFrame.from_ndarray(rgb_array, format="rgb24")
@@ -130,22 +130,34 @@ def render_av(
130
130
  log.debug(f"Tous: {tous}")
131
131
  log.debug(f"Clips: {tl.v}")
132
132
 
133
+ codec = av.Codec(args.video_codec, "w")
134
+
133
135
  if args.video_codec == "gif":
134
- _c = av.Codec("gif", "w")
135
- if _c.video_formats is not None and target_pix_fmt in (
136
- f.name for f in _c.video_formats
136
+ if codec.video_formats is not None and target_pix_fmt in (
137
+ f.name for f in codec.video_formats
137
138
  ):
138
139
  target_pix_fmt = target_pix_fmt
139
140
  else:
140
141
  target_pix_fmt = "rgb8"
141
- del _c
142
142
  else:
143
143
  target_pix_fmt = (
144
144
  target_pix_fmt if target_pix_fmt in allowed_pix_fmt else "yuv420p"
145
145
  )
146
146
 
147
+ del codec
147
148
  ops = {"mov_flags": "faststart"}
148
149
  output_stream = output.add_stream(args.video_codec, rate=target_fps, options=ops)
150
+
151
+ cc = output_stream.codec_context
152
+ if args.vprofile is not None:
153
+ if args.vprofile.title() not in cc.profiles:
154
+ b = " ".join([f'"{x.lower()}"' for x in cc.profiles])
155
+ log.error(
156
+ f"`{args.vprofile}` is not a valid profile.\nprofiles supported: {b}"
157
+ )
158
+
159
+ cc.profile = args.vprofile.title()
160
+
149
161
  yield output_stream
150
162
  if not isinstance(output_stream, av.VideoStream):
151
163
  log.error(f"Not a known video codec: {args.video_codec}")
@@ -177,9 +189,9 @@ def render_av(
177
189
  color_prim = src.videos[0].color_primaries
178
190
  color_trc = src.videos[0].color_transfer
179
191
 
180
- if color_range == 1 or color_range == 2:
192
+ if color_range in {1, 2}:
181
193
  output_stream.color_range = color_range
182
- if colorspace in (0, 1) or (colorspace >= 3 and colorspace < 16):
194
+ if colorspace in {0, 1} or (colorspace >= 3 and colorspace < 16):
183
195
  output_stream.colorspace = colorspace
184
196
  if color_prim == 1 or (color_prim >= 4 and color_prim < 17):
185
197
  output_stream.color_primaries = color_prim
@@ -310,7 +322,7 @@ def render_av(
310
322
  roi = array[y_start:y_end, x_start:x_end]
311
323
 
312
324
  # Blend the overlay image with the ROI based on the opacity
313
- roi = (1 - obj.opacity) * roi + obj.opacity * clipped_overlay
325
+ roi = (1 - obj.opacity) * roi + obj.opacity * clipped_overlay # type: ignore
314
326
  array[y_start:y_end, x_start:x_end] = roi
315
327
  array = np.clip(array, 0, 255).astype(np.uint8)
316
328
 
auto_editor/utils/bar.py CHANGED
@@ -31,7 +31,7 @@ def initBar(bar_type: str) -> Bar:
31
31
  part_width = len(chars) - 1
32
32
 
33
33
  ampm = True
34
- if sys.platform == "darwin" and bar_type in ("modern", "classic", "ascii"):
34
+ if sys.platform == "darwin" and bar_type in {"modern", "classic", "ascii"}:
35
35
  try:
36
36
  date_format = get_stdout_bytes(
37
37
  ["defaults", "read", "com.apple.menuextra.clock", "Show24Hour"]
@@ -47,11 +47,11 @@ containers: dict[str, DictContainer] = {
47
47
 
48
48
 
49
49
  def codec_type(x: str) -> str:
50
- if x in ("vp9", "vp8", "h264", "hevc", "av1", "gif", "apng"):
50
+ if x in {"vp9", "vp8", "h264", "hevc", "av1", "gif", "apng"}:
51
51
  return "video"
52
- if x in ("aac", "flac", "mp3"):
52
+ if x in {"aac", "flac", "mp3"}:
53
53
  return "audio"
54
- if x in ("ass", "ssa", "srt"):
54
+ if x in {"ass", "ssa", "srt"}:
55
55
  return "subtitle"
56
56
 
57
57
  try:
@@ -82,18 +82,12 @@ def container_constructor(ext: str) -> Container:
82
82
  kind = codec_type(codec)
83
83
  if kind == "video":
84
84
  vcodecs.add(codec)
85
- if codec == "h264":
86
- vcodecs.add("libx264")
87
- if codec == "av1":
88
- vcodecs.add("libsvtav1")
89
- if codec == "hevc":
90
- vcodecs.add("hevc_nvenc")
91
85
  if kind == "audio":
92
86
  acodecs.add(codec)
93
87
  if kind == "subtitle":
94
88
  scodecs.add(codec)
95
89
 
96
- allow_image = ext in ("mp4", "mkv")
90
+ allow_image = ext in {"mp4", "mkv"}
97
91
  kwargs = containers[ext] if ext in containers else {}
98
92
 
99
93
  return Container(
auto_editor/utils/func.py CHANGED
@@ -41,7 +41,7 @@ def to_timecode(secs: float | Fraction, fmt: str) -> str:
41
41
  if h == 0:
42
42
  return f"{sign}{m:02d}:{s:06.3f}"
43
43
  return f"{sign}{h:02d}:{m:02d}:{s:06.3f}"
44
- if fmt == "srt" or fmt == "mov_text":
44
+ if fmt in {"srt", "mov_text"}:
45
45
  return f"{sign}{h:02d}:{m:02d}:" + f"{s:06.3f}".replace(".", ",", 1)
46
46
  if fmt == "standard":
47
47
  return f"{sign}{h:02d}:{m:02d}:{s:06.3f}"
auto_editor/utils/log.py CHANGED
@@ -104,6 +104,10 @@ class Log:
104
104
  if codec.experimental:
105
105
  self.error(f"`{codec.name}` is an experimental codec")
106
106
 
107
+ @staticmethod
108
+ def deprecated(message: str) -> None:
109
+ sys.stderr.write(f"\033[1m\033[33m{message}\033[0m\n")
110
+
107
111
  def error(self, message: str | Exception) -> NoReturn:
108
112
  if self.is_debug and isinstance(message, Exception):
109
113
  self.cleanup()
@@ -104,7 +104,7 @@ def frame_rate(val: str) -> Fraction:
104
104
 
105
105
  def sample_rate(val: str) -> int:
106
106
  num, unit = _split_num_str(val)
107
- if unit in ("kHz", "KHz"):
107
+ if unit in {"kHz", "KHz"}:
108
108
  return natural(num * 1000)
109
109
  _unit_check(unit, ("", "Hz"))
110
110
  return natural(num)
@@ -122,9 +122,9 @@ def time(val: str, tb: Fraction) -> int:
122
122
  raise CoerceError(f"'{val}': Invalid time format")
123
123
 
124
124
  num, unit = _split_num_str(val)
125
- if unit in ("s", "sec", "secs", "second", "seconds"):
125
+ if unit in {"s", "sec", "secs", "second", "seconds"}:
126
126
  return round(num * tb)
127
- if unit in ("min", "mins", "minute", "minutes"):
127
+ if unit in {"min", "mins", "minute", "minutes"}:
128
128
  return round(num * tb * 60)
129
129
  if unit == "hour":
130
130
  return round(num * tb * 3600)
@@ -198,6 +198,7 @@ class Args:
198
198
  video_codec: str = "auto"
199
199
  audio_codec: str = "auto"
200
200
  video_bitrate: str = "auto"
201
+ vprofile: str | None = None
201
202
  audio_bitrate: str = "auto"
202
203
  scale: float = 1.0
203
204
  sn: bool = False
auto_editor/vanparse.py CHANGED
@@ -289,7 +289,7 @@ class ArgumentParser:
289
289
  key = to_key(option)
290
290
 
291
291
  next_arg = None if i == len(sys_args) - 1 else sys_args[i + 1]
292
- if next_arg in ("-h", "--help"):
292
+ if next_arg in {"-h", "--help"}:
293
293
  print_option_help(program_name, ns_obj, option)
294
294
  sys.exit()
295
295
 
auto_editor/wavfile.py CHANGED
@@ -90,7 +90,7 @@ def _read_data_chunk(
90
90
 
91
91
  bytes_per_sample = block_align // channels
92
92
 
93
- if bytes_per_sample in (3, 5, 6, 7):
93
+ if bytes_per_sample in {3, 5, 6, 7}:
94
94
  raise WavError(f"Unsupported bytes per sample: {bytes_per_sample}")
95
95
 
96
96
  if format_tag == PCM:
@@ -103,7 +103,7 @@ def _read_data_chunk(
103
103
  f"Unsupported bit depth: the WAV file has {bit_depth}-bit integer data."
104
104
  )
105
105
  elif format_tag == IEEE_FLOAT:
106
- if bit_depth in (32, 64):
106
+ if bit_depth in {32, 64}:
107
107
  dtype = f"{en}f{bytes_per_sample}"
108
108
  else:
109
109
  raise WavError(
@@ -201,7 +201,7 @@ def _handle_pad_byte(fid: Reader, size: int) -> None:
201
201
 
202
202
  def read(fid: Reader) -> tuple[int, AudioData]:
203
203
  file_sig = fid.read(4)
204
- if file_sig in (b"RIFF", b"RIFX"):
204
+ if file_sig in {b"RIFF", b"RIFX"}:
205
205
  data_size, file_size, en = _read_riff_chunk(file_sig, fid)
206
206
  elif file_sig == b"RF64":
207
207
  data_size, file_size, en = _read_rf64_chunk(fid)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: auto-editor
3
- Version: 26.1.1
3
+ Version: 26.2.0
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Author-email: WyattBlue <wyattblue@auto-editor.com>
6
6
  License: Unlicense
@@ -0,0 +1,56 @@
1
+ auto_editor/__init__.py,sha256=1-JJ1Kd-PXkwShJyQvOWjlyj_pGZI56jaozFas4DX70,23
2
+ auto_editor/__main__.py,sha256=g-9q3i6oFeNPeFMeNJEwZua6ZloOPLcaLN-B0FlxWXo,11371
3
+ auto_editor/analyze.py,sha256=7p_SDRRKQzlc6wtoW6MXYvJkDV4NO4DSOtJPFAuYcwM,12721
4
+ auto_editor/edit.py,sha256=cZbt5a4AH2U8pwtBb_VNOhcvjE3JEaBwkXfvriEcHYY,16573
5
+ auto_editor/ffwrapper.py,sha256=1uUTPV61RWKbUrONLvQdu2piNziz44vZjzQgd-e9YCU,4807
6
+ auto_editor/help.py,sha256=CzfDTsL4GuGu596ySHKj_wKnxGR9h8B0KUdkZpo33oE,8044
7
+ auto_editor/make_layers.py,sha256=vEeJt0PnE1vc9-cQZ_AlXVDjvWhObRCWJSCQGraoMvU,9016
8
+ auto_editor/output.py,sha256=ho8Lpqz4Sv_Gw0Vj2OvG39s83xHpyZlvtRNryTPbXqc,2563
9
+ auto_editor/preview.py,sha256=HUsjmV9Fx73rZ26BXrpz9z-z_e4oiui3u9e7qbbGoBY,3037
10
+ auto_editor/timeline.py,sha256=XfaH9cH-RB-MObOpMr5IfLcqJcjmabO1XwkUkT3_FQM,8186
11
+ auto_editor/vanparse.py,sha256=Ug5A2QaRqGiw4l55Z_h9T2QU1x0WqRibR7yY5rQ0WTk,10002
12
+ auto_editor/wavfile.py,sha256=afFfje8cK9lFjIkYoBbQHfvQIpsEPxWvspCtFhUKlAw,9499
13
+ auto_editor/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ auto_editor/cmds/cache.py,sha256=bViYbtVXefTeEIUvSanDfA6cG35ep1N_Jvtz7ZjgIkY,1959
15
+ auto_editor/cmds/desc.py,sha256=GDrKJYiHMaeTrplZAceXl1JwoqD78XsV2_5lc0Xd7po,869
16
+ auto_editor/cmds/info.py,sha256=vYa1hYdE8kDTE8AS3kwXlnd59X6CrE2GtIEQ7UmlpRY,7010
17
+ auto_editor/cmds/levels.py,sha256=qMxTOlj4ezna0K2jYWDFyZ0Srn4pT6nIdR-479IOEvw,5758
18
+ auto_editor/cmds/palet.py,sha256=ONzTqemaQq9YEfIOsDRNnwzfqnEMUMSXIQrETxyroRU,749
19
+ auto_editor/cmds/repl.py,sha256=TF_I7zsFY7-KdgidrqjafTz7o_eluVbLvgTcOBG-UWQ,3449
20
+ auto_editor/cmds/subdump.py,sha256=af_XBf7kaevqHn1A71z8C-7x8pS5WKD9FE_ugkCw6rk,665
21
+ auto_editor/cmds/test.py,sha256=hX7g8tNa8DNk3vqx15DOtFj82zWKUImP_UHPCYPPdMQ,25787
22
+ auto_editor/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ auto_editor/formats/fcp11.py,sha256=sqjC36jI47ICPLjZJYiqGwY7foOnWOiNjkPFLdgSnI4,5208
24
+ auto_editor/formats/fcp7.py,sha256=x5cagTzGCAW3i3M6m7TZC1h8gLfSmX1UK-iiDuCpdfs,20289
25
+ auto_editor/formats/json.py,sha256=kpYioIgFaVvhmS4I2NKi4ax574sRATe0Xfs0Wht9GUY,7693
26
+ auto_editor/formats/shotcut.py,sha256=-ES854LLFCMCBe100JRJedDmuk8zPev17aQMTrzPv-g,4923
27
+ auto_editor/formats/utils.py,sha256=LYXDiqOk9WwUorLGw2D0M7In9BNDkoKikNawuks7hqE,1648
28
+ auto_editor/lang/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ auto_editor/lang/json.py,sha256=D84vwyLtX5t5xl8S4r4jFXGVkbIg1L4IcexlS_a_k6w,9231
30
+ auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
31
+ auto_editor/lang/libmath.py,sha256=z33A161Oe6vYYK7R6pgYjdZZe63dQkN38Qf36TL3prg,847
32
+ auto_editor/lang/palet.py,sha256=ZOzNxLfzY8FTCYlF_mZtU2XoNzdg-eseUVkMtnWkVaI,24139
33
+ auto_editor/lang/stdenv.py,sha256=CIlQ9tTKscVNjajtDJeCG24Rk2J9sYqKJK4moI67Kag,43754
34
+ auto_editor/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ auto_editor/lib/contracts.py,sha256=lExGQymcQUmwG5lC1lO4qm4GY8W0q_yzK_miTaAoPA4,7586
36
+ auto_editor/lib/data_structs.py,sha256=Hnzl5gWvo-geTU0g-lGejj6HQW3VvPv0NBEj2XoGskY,7089
37
+ auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
38
+ auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ auto_editor/render/audio.py,sha256=_GuX0WNY1YeumgBN3bWqgwVXiuhpvx7sijABxqyO2ag,12580
40
+ auto_editor/render/subtitle.py,sha256=jtNRKvgo1fpHTrAfGZqdkNeNgGgasw-K-4PwIKiWwfM,6231
41
+ auto_editor/render/video.py,sha256=svyHUZRV3sAXjEcfrnKPW7gJkqd-724lYGrZnwKEnSA,12591
42
+ auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ auto_editor/utils/bar.py,sha256=miij9BW6mqn85gARh-bf2jP9dEHSwOyI3d4JIxQo36s,3998
44
+ auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
45
+ auto_editor/utils/cmdkw.py,sha256=aUGBvBel2Ko1o6Rwmr4rEL-BMc5hEnzYLbyZ1GeJdcY,5729
46
+ auto_editor/utils/container.py,sha256=C_Ahh7nlMEX4DNQ2M_cITPPbYcIL68r4I_AgFy0OD6o,2487
47
+ auto_editor/utils/func.py,sha256=C8ucgsSEzPyBc-8obhsCXd_uQW0cnCdBn1KVxB7FHjU,2747
48
+ auto_editor/utils/log.py,sha256=8fOdyTG3vjKhA1tJTMKRjXVqhrY2q3tFnXU8tKm_twA,3937
49
+ auto_editor/utils/types.py,sha256=r5f6QB81xH7NRwGntITIOCVx-fupOl8l3X3LSFkt3nE,10756
50
+ docs/build.py,sha256=POy8X8QOBYe_8A8HI_yiVI_Qg9E5mLpn1z7AHQr0_vQ,1888
51
+ auto_editor-26.2.0.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
52
+ auto_editor-26.2.0.dist-info/METADATA,sha256=cy6NADq5iQR2-kkjagsaCvfz7ZuDW0kaM83TKMdqZTU,6109
53
+ auto_editor-26.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
54
+ auto_editor-26.2.0.dist-info/entry_points.txt,sha256=UAsTc7qJQbnAzHd7KWg-ALo_X9Hj2yDs3M9I2DV3eyI,212
55
+ auto_editor-26.2.0.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
+ auto_editor-26.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.7.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,6 @@
1
+ [console_scripts]
2
+ aedesc = auto_editor.cmds.desc:main
3
+ aeinfo = auto_editor.cmds.info:main
4
+ aelevels = auto_editor.cmds.levels:main
5
+ aesubdump = auto_editor.cmds.subdump:main
6
+ auto-editor = auto_editor.__main__:main
@@ -1,56 +0,0 @@
1
- auto_editor/__init__.py,sha256=2Ltcef2BVJgJx2W5ZkX7r21sdnzR3Zvtu1PYKRHEjLk,23
2
- auto_editor/__main__.py,sha256=tc0M1MIPYjU5wCEU3EqmleOzaUgksU60qVHO0vRuC10,11310
3
- auto_editor/analyze.py,sha256=Fv8NA99T1dZzrqlweJNlK7haKjgK13neR9CMw4t6rlY,12716
4
- auto_editor/edit.py,sha256=eEMRaQbn0jylfJ6D_egnUXjoMCbdQVsAu7MDrn-xlGo,15950
5
- auto_editor/ffwrapper.py,sha256=Tct_Q-uy5F51h8M7UFam50UzRFpgkBvUamJP1AoKVvc,4749
6
- auto_editor/help.py,sha256=CzfDTsL4GuGu596ySHKj_wKnxGR9h8B0KUdkZpo33oE,8044
7
- auto_editor/make_layers.py,sha256=vEeJt0PnE1vc9-cQZ_AlXVDjvWhObRCWJSCQGraoMvU,9016
8
- auto_editor/output.py,sha256=ho8Lpqz4Sv_Gw0Vj2OvG39s83xHpyZlvtRNryTPbXqc,2563
9
- auto_editor/preview.py,sha256=HUsjmV9Fx73rZ26BXrpz9z-z_e4oiui3u9e7qbbGoBY,3037
10
- auto_editor/timeline.py,sha256=XfaH9cH-RB-MObOpMr5IfLcqJcjmabO1XwkUkT3_FQM,8186
11
- auto_editor/vanparse.py,sha256=f0vViZ-aYtDxEyVrFHJ5X2pPTQAfqtw3N2gZgzn51kU,10002
12
- auto_editor/wavfile.py,sha256=1HbZ4L8IBD6Fbg3pd5MQG4ZXy48YZA05t8XllSplhWk,9499
13
- auto_editor/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- auto_editor/formats/fcp11.py,sha256=qzo-qpHYsiHjOPjGBWjBeJUAACDmo8ijJkjslHTQH6Q,5196
15
- auto_editor/formats/fcp7.py,sha256=LYkGtZC_dmbHQDg1wYP7XQYS74NEon6ws8c5MDdTd90,20275
16
- auto_editor/formats/json.py,sha256=Br-xHVHj59C0OPP2FwfJeht_fImepRXsaw0iDFvK7-w,7693
17
- auto_editor/formats/shotcut.py,sha256=-ES854LLFCMCBe100JRJedDmuk8zPev17aQMTrzPv-g,4923
18
- auto_editor/formats/utils.py,sha256=LYXDiqOk9WwUorLGw2D0M7In9BNDkoKikNawuks7hqE,1648
19
- auto_editor/lang/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- auto_editor/lang/json.py,sha256=OsNcYlfEj8ZLlzLK-gkLcrCCKI7mJz9rpe-6XLr4f9U,9231
21
- auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
22
- auto_editor/lang/libmath.py,sha256=z33A161Oe6vYYK7R6pgYjdZZe63dQkN38Qf36TL3prg,847
23
- auto_editor/lang/palet.py,sha256=jHSO8R4eAbMeiQaGwCLih6z0pPGoJEcmPgSvsTpF8EA,24139
24
- auto_editor/lang/stdenv.py,sha256=3UnVgLaTT7hQMhquDmv-mQx82jtr_YOYstwZAwvXfJY,43754
25
- auto_editor/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- auto_editor/lib/contracts.py,sha256=lExGQymcQUmwG5lC1lO4qm4GY8W0q_yzK_miTaAoPA4,7586
27
- auto_editor/lib/data_structs.py,sha256=dcsXgsLLzbmFDUZucoirzewPALsKzoxz7z5L22_QJM8,7091
28
- auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
29
- auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- auto_editor/render/audio.py,sha256=1iOQCeRXfRz28cqnHp2XeK-f3_UnPf80AKQAfifGvdE,12584
31
- auto_editor/render/subtitle.py,sha256=lf2l1QWJgFiqlpQWWBwSlKJnSgW8Lkfi59WrJMbIDqM,6240
32
- auto_editor/render/video.py,sha256=dje0RNW2dKILfTzt0VAF0WR6REfGOsc6l17pP1Z4ooA,12215
33
- auto_editor/subcommands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- auto_editor/subcommands/cache.py,sha256=YW_5qH0q5TVzmfOLEO117uqcY7dF6DS619ltVTPIzHQ,1959
35
- auto_editor/subcommands/desc.py,sha256=GDrKJYiHMaeTrplZAceXl1JwoqD78XsV2_5lc0Xd7po,869
36
- auto_editor/subcommands/info.py,sha256=UDdoxd6_fqSoRPwthkWXqnpxHp7dJQ0Dn96lYX_ubWc,7010
37
- auto_editor/subcommands/levels.py,sha256=psSSIsGfzr9j0HGKp2yvK6nMlrkLwxkwsyI0uF2xb_c,4496
38
- auto_editor/subcommands/palet.py,sha256=ONzTqemaQq9YEfIOsDRNnwzfqnEMUMSXIQrETxyroRU,749
39
- auto_editor/subcommands/repl.py,sha256=TF_I7zsFY7-KdgidrqjafTz7o_eluVbLvgTcOBG-UWQ,3449
40
- auto_editor/subcommands/subdump.py,sha256=af_XBf7kaevqHn1A71z8C-7x8pS5WKD9FE_ugkCw6rk,665
41
- auto_editor/subcommands/test.py,sha256=bR3MQvW1P_cKDwd1hRa2t-n3GqgRGGv5D3IBnfrH8-0,25787
42
- auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- auto_editor/utils/bar.py,sha256=hG_NiYeuM90TdILzAJORft-UOS5grwWN3SbRuj6upsI,3998
44
- auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
45
- auto_editor/utils/cmdkw.py,sha256=aUGBvBel2Ko1o6Rwmr4rEL-BMc5hEnzYLbyZ1GeJdcY,5729
46
- auto_editor/utils/container.py,sha256=Wf1ZL0tvXWl6m1B9mK_SkgVl89ilV_LpwlQq0TVroCc,2704
47
- auto_editor/utils/func.py,sha256=kB-pNDn20M6YT7sljyd_auve5teK-E2G4TgwVOAIuJw,2754
48
- auto_editor/utils/log.py,sha256=n5dlJ2CdK_54eiYE02SPgkBdBWABV7tE2p8ONj_F6TM,3813
49
- auto_editor/utils/types.py,sha256=7BF7R7DA5eKmtI6f5ia7bOYNL0u_2sviiPsE1VmP0lc,10724
50
- docs/build.py,sha256=POy8X8QOBYe_8A8HI_yiVI_Qg9E5mLpn1z7AHQr0_vQ,1888
51
- auto_editor-26.1.1.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
52
- auto_editor-26.1.1.dist-info/METADATA,sha256=Ovf6CjY_x-lyih-4c1xBZEkL_X0gvifVFthPcLSMOtk,6109
53
- auto_editor-26.1.1.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
54
- auto_editor-26.1.1.dist-info/entry_points.txt,sha256=-H7zdTw4MqnAcwrN5xTNkGIhzZtJMxS9r6lTMeR9-aA,240
55
- auto_editor-26.1.1.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
- auto_editor-26.1.1.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- [console_scripts]
2
- aedesc = auto_editor.subcommands.desc:main
3
- aeinfo = auto_editor.subcommands.info:main
4
- aelevels = auto_editor.subcommands.levels:main
5
- aesubdump = auto_editor.subcommands.subdump:main
6
- auto-editor = auto_editor.__main__:main
File without changes
File without changes
File without changes
File without changes
File without changes