auto-editor 26.2.0__py3-none-any.whl → 26.3.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.
auto_editor/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "26.2.0"
1
+ __version__ = "26.3.0"
auto_editor/cmds/test.py CHANGED
@@ -549,6 +549,15 @@ def main(sys_args: list[str] | None = None):
549
549
  def yuv442p():
550
550
  return run.main(["resources/test_yuv422p.mp4"], [])
551
551
 
552
+ def prores():
553
+ run.main(["resources/testsrc.mp4", "-c:v", "prores", "-o", "out.mkv"], [])
554
+ assert fileinfo("out.mkv").videos[0].pix_fmt == "yuv422p10le"
555
+
556
+ run.main(["out.mkv", "-c:v", "prores", "-o", "out2.mkv"], [])
557
+ assert fileinfo("out2.mkv").videos[0].pix_fmt == "yuv422p10le"
558
+
559
+ return "out.mkv", "out2.mkv"
560
+
552
561
  # Issue 280
553
562
  def SAR():
554
563
  out = run.main(["resources/SAR-2by3.mp4"], [])
@@ -735,6 +744,7 @@ def main(sys_args: list[str] | None = None):
735
744
  premiere,
736
745
  SAR,
737
746
  yuv442p,
747
+ prores,
738
748
  edit_negative_tests,
739
749
  edit_positive_tests,
740
750
  audio_norm_f,
auto_editor/edit.py CHANGED
@@ -365,17 +365,35 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
365
365
 
366
366
  # Setup video
367
367
  if ctr.default_vid != "none" and tl.v:
368
- vframes = render_av(output, tl, args, bar, log)
368
+ vframes = render_av(output, tl, args, log)
369
369
  output_stream = next(vframes)
370
370
  else:
371
371
  output_stream, vframes = None, iter([])
372
372
 
373
+ no_color = log.no_color or log.machine
374
+ encoder_titles = []
375
+ if output_stream is not None:
376
+ name = output_stream.codec.canonical_name
377
+ encoder_titles.append(name if no_color else f"\033[95m{name}")
378
+ if audio_streams:
379
+ name = audio_streams[0].name
380
+ encoder_titles.append(name if no_color else f"\033[96m{name}")
381
+ if subtitle_streams:
382
+ name = subtitle_streams[0].name
383
+ encoder_titles.append(name if no_color else f"\033[32m{name}")
384
+
385
+ title = f"({os.path.splitext(output_path)[1][1:]}) "
386
+ if no_color:
387
+ title += "+".join(encoder_titles)
388
+ else:
389
+ title += "\033[0m+".join(encoder_titles) + "\033[0m"
390
+ bar.start(tl.end, title)
391
+
373
392
  # Process frames
374
393
  while True:
375
394
  audio_frames = [next(frames, None) for frames in audio_gen_frames]
376
- video_frame = next(vframes, None)
395
+ index, video_frame = next(vframes, (0, None))
377
396
  subtitle_frames = [next(packet, None) for packet in sub_gen_frames]
378
-
379
397
  if (
380
398
  all(frame is None for frame in audio_frames)
381
399
  and video_frame is None
@@ -405,12 +423,16 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
405
423
  except av.FFmpegError as e:
406
424
  log.error(e)
407
425
 
426
+ bar.tick(index)
427
+
408
428
  # Flush streams
409
429
  if output_stream is not None:
410
430
  output.mux(output_stream.encode(None))
411
431
  for audio_stream in audio_streams:
412
432
  output.mux(audio_stream.encode(None))
413
433
 
434
+ bar.end()
435
+
414
436
  # Close resources
415
437
  for audio_input in audio_inputs:
416
438
  audio_input.close()
auto_editor/ffwrapper.py CHANGED
@@ -147,10 +147,9 @@ 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"
151
150
  audios += (
152
151
  AudioStream(
153
- name,
152
+ a_cc.codec.canonical_name,
154
153
  0 if a_cc.sample_rate is None else a_cc.sample_rate,
155
154
  a.layout.name,
156
155
  a_cc.channels,
@@ -1045,7 +1045,7 @@ def make_standard_env() -> dict[str, Any]:
1045
1045
  # reals
1046
1046
  "pow": Proc("pow", pow, (2, 2), is_real),
1047
1047
  "abs": Proc("abs", abs, (1, 1), is_real),
1048
- "round": Proc("round", round, (1, 1), is_real),
1048
+ "round": Proc("round", round, (1, 2), is_real, is_int),
1049
1049
  "max": Proc("max", lambda *v: max(v), (1, None), is_real),
1050
1050
  "min": Proc("min", lambda *v: min(v), (1, None), is_real),
1051
1051
  "max-seq": Proc("max-seq", max, (1, 1), is_sequence),
@@ -15,7 +15,6 @@ if TYPE_CHECKING:
15
15
 
16
16
  from auto_editor.ffwrapper import FileInfo
17
17
  from auto_editor.timeline import v3
18
- from auto_editor.utils.bar import Bar
19
18
  from auto_editor.utils.log import Log
20
19
  from auto_editor.utils.types import Args
21
20
 
@@ -26,35 +25,12 @@ class VideoFrame:
26
25
  src: FileInfo
27
26
 
28
27
 
29
- # From: github.com/PyAV-Org/PyAV/blob/main/av/video/frame.pyx
30
- allowed_pix_fmt = {
31
- "yuv420p",
32
- "yuvj420p",
33
- "yuv444p",
34
- "yuvj444p",
35
- "rgb48be",
36
- "rgb48le",
37
- "rgb64be",
38
- "rgb64le",
39
- "rgb24",
40
- "bgr24",
41
- "argb",
42
- "rgba",
43
- "abgr",
44
- "bgra",
45
- "gray",
46
- "gray8",
47
- "gray16be",
48
- "gray16le",
49
- "rgb8",
50
- "bgr8",
51
- "pal8",
52
- }
28
+ allowed_pix_fmt = av.video.frame.supported_np_pix_fmts
53
29
 
54
30
 
55
31
  def make_solid(width: int, height: int, pix_fmt: str, bg: str) -> av.VideoFrame:
56
32
  hex_color = bg.lstrip("#").upper()
57
- rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in {0, 2, 4})
33
+ rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
58
34
 
59
35
  rgb_array = np.full((height, width, 3), rgb_color, dtype=np.uint8)
60
36
  rgb_frame = av.VideoFrame.from_ndarray(rgb_array, format="rgb24")
@@ -65,7 +41,7 @@ def make_image_cache(tl: v3) -> dict[tuple[FileInfo, int], np.ndarray]:
65
41
  img_cache = {}
66
42
  for clip in tl.v:
67
43
  for obj in clip:
68
- if isinstance(obj, TlImage) and obj.src not in img_cache:
44
+ if isinstance(obj, TlImage) and (obj.src, obj.width) not in img_cache:
69
45
  with av.open(obj.src.path) as cn:
70
46
  my_stream = cn.streams.video[0]
71
47
  for frame in cn.decode(my_stream):
@@ -85,7 +61,7 @@ def make_image_cache(tl: v3) -> dict[tuple[FileInfo, int], np.ndarray]:
85
61
 
86
62
 
87
63
  def render_av(
88
- output: av.container.OutputContainer, tl: v3, args: Args, bar: Bar, log: Log
64
+ output: av.container.OutputContainer, tl: v3, args: Args, log: Log
89
65
  ) -> Any:
90
66
  from_ndarray = av.VideoFrame.from_ndarray
91
67
 
@@ -132,13 +108,15 @@ def render_av(
132
108
 
133
109
  codec = av.Codec(args.video_codec, "w")
134
110
 
135
- if args.video_codec == "gif":
111
+ if codec.canonical_name == "gif":
136
112
  if codec.video_formats is not None and target_pix_fmt in (
137
113
  f.name for f in codec.video_formats
138
114
  ):
139
115
  target_pix_fmt = target_pix_fmt
140
116
  else:
141
117
  target_pix_fmt = "rgb8"
118
+ elif codec.canonical_name == "prores":
119
+ target_pix_fmt = "yuv422p10le"
142
120
  else:
143
121
  target_pix_fmt = (
144
122
  target_pix_fmt if target_pix_fmt in allowed_pix_fmt else "yuv420p"
@@ -212,8 +190,6 @@ def render_av(
212
190
  seek_frame = None
213
191
  frames_saved = 0
214
192
 
215
- bar.start(tl.end, "Creating new video")
216
-
217
193
  bg = args.background
218
194
  null_frame = make_solid(target_width, target_height, target_pix_fmt, bg)
219
195
  frame_index = -1
@@ -334,11 +310,7 @@ def render_av(
334
310
 
335
311
  if frame.format.name != target_pix_fmt:
336
312
  frame = frame.reformat(format=target_pix_fmt)
337
- bar.tick(index)
338
- elif index % 3 == 0:
339
- bar.tick(index)
340
313
 
341
- yield from_ndarray(frame.to_ndarray(), format=frame.format.name)
314
+ yield (index, from_ndarray(frame.to_ndarray(), format=frame.format.name))
342
315
 
343
- bar.end()
344
316
  log.debug(f"Total frames saved seeking: {frames_saved}")
auto_editor/utils/bar.py CHANGED
@@ -89,7 +89,7 @@ class Bar:
89
89
  percent = round(progress * 100, 1)
90
90
  p_pad = " " * (4 - len(str(percent)))
91
91
  columns = get_terminal_size().columns
92
- bar_len = max(1, columns - (len_title + 32))
92
+ bar_len = max(1, columns - len_title - 32)
93
93
  bar_str = self._bar_str(progress, bar_len)
94
94
 
95
95
  bar = f" {self.icon}{title} {bar_str} {p_pad}{percent}% ETA {new_time}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: auto-editor
3
- Version: 26.2.0
3
+ Version: 26.3.0
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Author-email: WyattBlue <wyattblue@auto-editor.com>
6
6
  License: Unlicense
@@ -12,7 +12,7 @@ Requires-Python: <3.14,>=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: numpy<3.0,>=1.24
15
- Requires-Dist: pyav==14.*
15
+ Requires-Dist: pyav==14.2.0
16
16
 
17
17
  <p align="center"><img src="https://auto-editor.com/img/auto-editor-banner.webp" title="Auto-Editor" width="700"></p>
18
18
 
@@ -1,8 +1,8 @@
1
- auto_editor/__init__.py,sha256=1-JJ1Kd-PXkwShJyQvOWjlyj_pGZI56jaozFas4DX70,23
1
+ auto_editor/__init__.py,sha256=foFMRrw-Br8Dq0ZIes1siNTsxZj5nQywX_cfWHfB380,23
2
2
  auto_editor/__main__.py,sha256=g-9q3i6oFeNPeFMeNJEwZua6ZloOPLcaLN-B0FlxWXo,11371
3
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
4
+ auto_editor/edit.py,sha256=gz2MocM5s1uz-hLrFWmiNl1TwOm4S_1EkYn-ZBuu_sE,17401
5
+ auto_editor/ffwrapper.py,sha256=1lYYfq8gVgMVkYWeAEYDPAHCwFCYbKQwy0FxYBxMzk8,4765
6
6
  auto_editor/help.py,sha256=CzfDTsL4GuGu596ySHKj_wKnxGR9h8B0KUdkZpo33oE,8044
7
7
  auto_editor/make_layers.py,sha256=vEeJt0PnE1vc9-cQZ_AlXVDjvWhObRCWJSCQGraoMvU,9016
8
8
  auto_editor/output.py,sha256=ho8Lpqz4Sv_Gw0Vj2OvG39s83xHpyZlvtRNryTPbXqc,2563
@@ -18,7 +18,7 @@ auto_editor/cmds/levels.py,sha256=qMxTOlj4ezna0K2jYWDFyZ0Srn4pT6nIdR-479IOEvw,57
18
18
  auto_editor/cmds/palet.py,sha256=ONzTqemaQq9YEfIOsDRNnwzfqnEMUMSXIQrETxyroRU,749
19
19
  auto_editor/cmds/repl.py,sha256=TF_I7zsFY7-KdgidrqjafTz7o_eluVbLvgTcOBG-UWQ,3449
20
20
  auto_editor/cmds/subdump.py,sha256=af_XBf7kaevqHn1A71z8C-7x8pS5WKD9FE_ugkCw6rk,665
21
- auto_editor/cmds/test.py,sha256=hX7g8tNa8DNk3vqx15DOtFj82zWKUImP_UHPCYPPdMQ,25787
21
+ auto_editor/cmds/test.py,sha256=Wih-KQnv5Ld1CgbOUdtrp_fMnINsr_khzONvlrJ-bhw,26163
22
22
  auto_editor/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  auto_editor/formats/fcp11.py,sha256=sqjC36jI47ICPLjZJYiqGwY7foOnWOiNjkPFLdgSnI4,5208
24
24
  auto_editor/formats/fcp7.py,sha256=x5cagTzGCAW3i3M6m7TZC1h8gLfSmX1UK-iiDuCpdfs,20289
@@ -30,7 +30,7 @@ auto_editor/lang/json.py,sha256=D84vwyLtX5t5xl8S4r4jFXGVkbIg1L4IcexlS_a_k6w,9231
30
30
  auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
31
31
  auto_editor/lang/libmath.py,sha256=z33A161Oe6vYYK7R6pgYjdZZe63dQkN38Qf36TL3prg,847
32
32
  auto_editor/lang/palet.py,sha256=ZOzNxLfzY8FTCYlF_mZtU2XoNzdg-eseUVkMtnWkVaI,24139
33
- auto_editor/lang/stdenv.py,sha256=CIlQ9tTKscVNjajtDJeCG24Rk2J9sYqKJK4moI67Kag,43754
33
+ auto_editor/lang/stdenv.py,sha256=sQyOD3bttjcieWMtTMNpE6blEZriAfHtSZHbuvC09R8,43762
34
34
  auto_editor/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  auto_editor/lib/contracts.py,sha256=lExGQymcQUmwG5lC1lO4qm4GY8W0q_yzK_miTaAoPA4,7586
36
36
  auto_editor/lib/data_structs.py,sha256=Hnzl5gWvo-geTU0g-lGejj6HQW3VvPv0NBEj2XoGskY,7089
@@ -38,9 +38,9 @@ auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
38
38
  auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  auto_editor/render/audio.py,sha256=_GuX0WNY1YeumgBN3bWqgwVXiuhpvx7sijABxqyO2ag,12580
40
40
  auto_editor/render/subtitle.py,sha256=jtNRKvgo1fpHTrAfGZqdkNeNgGgasw-K-4PwIKiWwfM,6231
41
- auto_editor/render/video.py,sha256=svyHUZRV3sAXjEcfrnKPW7gJkqd-724lYGrZnwKEnSA,12591
41
+ auto_editor/render/video.py,sha256=JBVl8w-hQ6zrs97iA527LPsBZ9s601SVSJs2bSMCq88,12185
42
42
  auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- auto_editor/utils/bar.py,sha256=miij9BW6mqn85gARh-bf2jP9dEHSwOyI3d4JIxQo36s,3998
43
+ auto_editor/utils/bar.py,sha256=0ZSfuWdBA1zySwodkb4mw5uahC6UwCk2umaGnB8A7n0,3996
44
44
  auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
45
45
  auto_editor/utils/cmdkw.py,sha256=aUGBvBel2Ko1o6Rwmr4rEL-BMc5hEnzYLbyZ1GeJdcY,5729
46
46
  auto_editor/utils/container.py,sha256=C_Ahh7nlMEX4DNQ2M_cITPPbYcIL68r4I_AgFy0OD6o,2487
@@ -48,9 +48,9 @@ auto_editor/utils/func.py,sha256=C8ucgsSEzPyBc-8obhsCXd_uQW0cnCdBn1KVxB7FHjU,274
48
48
  auto_editor/utils/log.py,sha256=8fOdyTG3vjKhA1tJTMKRjXVqhrY2q3tFnXU8tKm_twA,3937
49
49
  auto_editor/utils/types.py,sha256=r5f6QB81xH7NRwGntITIOCVx-fupOl8l3X3LSFkt3nE,10756
50
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,,
51
+ auto_editor-26.3.0.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
52
+ auto_editor-26.3.0.dist-info/METADATA,sha256=YOFNFBSIMQveLah-PSIrBtlfY-xwEveHxKNAneUAs_0,6111
53
+ auto_editor-26.3.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
54
+ auto_editor-26.3.0.dist-info/entry_points.txt,sha256=UAsTc7qJQbnAzHd7KWg-ALo_X9Hj2yDs3M9I2DV3eyI,212
55
+ auto_editor-26.3.0.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
+ auto_editor-26.3.0.dist-info/RECORD,,