auto-editor 25.2.0__py3-none-any.whl → 25.3.1__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/wavfile.py CHANGED
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import io
4
4
  import struct
5
5
  import sys
6
- from typing import Literal
6
+ from typing import TYPE_CHECKING, Literal
7
7
 
8
8
  import numpy as np
9
9
 
@@ -15,13 +15,17 @@ AudioData = np.memmap | np.ndarray
15
15
  Endian = Literal[">", "<"] # Big Endian, Little Endian
16
16
  ByteOrd = Literal["big", "little"]
17
17
 
18
+ if TYPE_CHECKING:
19
+ Reader = io.BufferedReader | io.BytesIO
20
+ Writer = io.BufferedWriter | io.BytesIO
21
+
18
22
 
19
23
  class WavError(Exception):
20
24
  pass
21
25
 
22
26
 
23
27
  def _read_fmt_chunk(
24
- fid: io.BufferedReader, bytes_order: ByteOrd
28
+ fid: Reader, bytes_order: ByteOrd
25
29
  ) -> tuple[int, int, int, int, int]:
26
30
  size = int.from_bytes(fid.read(4), bytes_order)
27
31
 
@@ -69,7 +73,7 @@ def _read_fmt_chunk(
69
73
 
70
74
 
71
75
  def _read_data_chunk(
72
- fid: io.BufferedReader,
76
+ fid: Reader,
73
77
  format_tag: int,
74
78
  channels: int,
75
79
  bit_depth: int,
@@ -114,16 +118,22 @@ def _read_data_chunk(
114
118
  else:
115
119
  n_samples = (size - 1) // block_align
116
120
 
117
- data = np.memmap(
118
- fid, dtype=dtype, mode="c", offset=fid.tell(), shape=(n_samples, channels)
119
- )
120
- fid.seek(size, 1)
121
+ if isinstance(fid, io.BufferedReader):
122
+ data: AudioData = np.memmap(
123
+ fid, dtype=dtype, mode="c", offset=fid.tell(), shape=(n_samples, channels)
124
+ )
125
+ fid.seek(size, 1)
126
+ else:
127
+ bytes_per_sample = np.dtype(dtype).itemsize
128
+ buffer = fid.read(n_samples * channels * bytes_per_sample)
129
+ data = np.frombuffer(buffer, dtype=dtype).reshape((n_samples, channels))
130
+
121
131
  _handle_pad_byte(fid, size)
122
132
 
123
133
  return data
124
134
 
125
135
 
126
- def _skip_unknown_chunk(fid: io.BufferedReader, en: Endian) -> None:
136
+ def _skip_unknown_chunk(fid: Reader, en: Endian) -> None:
127
137
  data = fid.read(4)
128
138
 
129
139
  if len(data) == 4:
@@ -140,7 +150,7 @@ def _skip_unknown_chunk(fid: io.BufferedReader, en: Endian) -> None:
140
150
  )
141
151
 
142
152
 
143
- def _read_rf64_chunk(fid: io.BufferedReader) -> tuple[int, int, Endian]:
153
+ def _read_rf64_chunk(fid: Reader) -> tuple[int, int, Endian]:
144
154
  # https://tech.ebu.ch/docs/tech/tech3306v1_0.pdf
145
155
  # https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.2088-1-201910-I!!PDF-E.pdf
146
156
 
@@ -171,7 +181,7 @@ def _read_rf64_chunk(fid: io.BufferedReader) -> tuple[int, int, Endian]:
171
181
  return data_size, file_size, en
172
182
 
173
183
 
174
- def _read_riff_chunk(sig: bytes, fid: io.BufferedReader) -> tuple[None, int, Endian]:
184
+ def _read_riff_chunk(sig: bytes, fid: Reader) -> tuple[None, int, Endian]:
175
185
  en: Endian = "<" if sig == b"RIFF" else ">"
176
186
  bytes_order: ByteOrd = "big" if en == ">" else "little"
177
187
 
@@ -184,14 +194,12 @@ def _read_riff_chunk(sig: bytes, fid: io.BufferedReader) -> tuple[None, int, End
184
194
  return None, file_size, en
185
195
 
186
196
 
187
- def _handle_pad_byte(fid: io.BufferedReader, size: int) -> None:
197
+ def _handle_pad_byte(fid: Reader, size: int) -> None:
188
198
  if size % 2 == 1:
189
199
  fid.seek(1, 1)
190
200
 
191
201
 
192
- def read(filename: str) -> tuple[int, AudioData]:
193
- fid = open(filename, "rb")
194
-
202
+ def read(fid: Reader) -> tuple[int, AudioData]:
195
203
  file_sig = fid.read(4)
196
204
  if file_sig in (b"RIFF", b"RIFX"):
197
205
  data_size, file_size, en = _read_riff_chunk(file_sig, fid)
@@ -241,7 +249,7 @@ def read(filename: str) -> tuple[int, AudioData]:
241
249
  raise WavError("Found no data")
242
250
 
243
251
 
244
- def write(fid: io.BufferedWriter, sr: int, arr: np.ndarray) -> None:
252
+ def write(fid: Writer, sr: int, arr: np.ndarray) -> None:
245
253
  channels = 1 if arr.ndim == 1 else arr.shape[1]
246
254
  bit_depth = arr.dtype.itemsize * 8
247
255
  block_align = channels * (bit_depth // 8)
@@ -290,7 +298,8 @@ def main() -> None:
290
298
  with open("test.wav", "wb") as file:
291
299
  write(file, 48_000, data)
292
300
 
293
- read_sr, read_data = read("test.wav")
301
+ with open("test.wav", "rb") as file:
302
+ read_sr, read_data = read(file)
294
303
 
295
304
  assert read_sr == 48_000
296
305
  assert np.array_equal(data, read_data)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-editor
3
- Version: 25.2.0
3
+ Version: 25.3.1
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.23.0
15
- Requires-Dist: pyav ==13.0.*
15
+ Requires-Dist: pyav ==13.1.*
16
16
  Requires-Dist: ae-ffmpeg ==1.2.*
17
17
 
18
18
  <p align="center"><img src="https://auto-editor.com/img/auto-editor-banner.webp" title="Auto-Editor" width="700"></p>
@@ -1,22 +1,21 @@
1
- auto_editor/__init__.py,sha256=d15hyX45hKLmfvXLeIkyhpZzJZLdjD4LHXV2_hYYiiM,23
2
- auto_editor/__main__.py,sha256=OlPCTG3t8phhLnyXT8bQlqsA4O97mDhmJTanJCgb82Q,9964
3
- auto_editor/analyze.py,sha256=pHoSZ_-wyV1hLJyJpPg9Ha7oecjdGHGJ0a4hbKnb9NY,11779
4
- auto_editor/edit.py,sha256=-AtEOHTvBnLlvvYkDyDbh9weGOOui6vsbyJZbEoYljI,11447
5
- auto_editor/ffwrapper.py,sha256=NnhD4TvKyaap0Y2MQ7aIUQfeLJwfNbjTj5bLUpoMEI4,7888
1
+ auto_editor/__init__.py,sha256=2StKlE00iLSdWP1B73T1WJb76-2gk0h3rPFRqAk5ZXM,23
2
+ auto_editor/__main__.py,sha256=0t_yI-o11iwDm_LlUW_u84LsX89cv0GuHMfc0NKlp68,12228
3
+ auto_editor/analyze.py,sha256=uCi21659BB-lbPwZ6yxNLekS6Q3yoB2ypLNXPhmhTfg,11688
4
+ auto_editor/edit.py,sha256=9G2_g_8FEzQrvB3Ez9M5vtgrIS0feZeA4DdxT9cdObA,12319
5
+ auto_editor/ffwrapper.py,sha256=K-gs5mAdcwPaaZVdU1yOl7ckptO7eJ_zLQM8V7vwxaA,7491
6
6
  auto_editor/help.py,sha256=BFiP7vBz42TUzum4-zaQIrV1OY7kHeN0pe0MPE0T5xw,7997
7
7
  auto_editor/make_layers.py,sha256=8uFy5SvMArAP-5slYJrxa_iGAEwimQBFeM-T01VORVw,8995
8
- auto_editor/output.py,sha256=D8NCJwwmcjDf5rvoBnWKu5XY7QtxF3thxbnTxKAxGu8,8043
9
- auto_editor/preview.py,sha256=noWkgyzdE14zwG8ZDYxLDual5iVt6zYTt4HTe-QAgFY,3029
10
- auto_editor/timeline.py,sha256=gZHJT7Iugpz0LPH06cRPgcEWF4iXTltUwTXmS3ShtfQ,6921
11
- auto_editor/validate_input.py,sha256=_9vtbNxodhVPf4PzTAH67LSj2K-HS6kShJOARmUMJdY,2904
8
+ auto_editor/output.py,sha256=TbwiFL7CQnPv5_Pv0bSaE2faLvepxaIf5_xMvDAFXjQ,7997
9
+ auto_editor/preview.py,sha256=HUsjmV9Fx73rZ26BXrpz9z-z_e4oiui3u9e7qbbGoBY,3037
10
+ auto_editor/timeline.py,sha256=tIty8O8jD6TR2Sw2bivUtYtdnpplfuOXT7Dfc-gekr8,8174
12
11
  auto_editor/vanparse.py,sha256=f0vViZ-aYtDxEyVrFHJ5X2pPTQAfqtw3N2gZgzn51kU,10002
13
- auto_editor/wavfile.py,sha256=7N2LX_WfFVRnoXrKveLvuyTYpIz2htpGqfCD8tR4kJ8,9168
12
+ auto_editor/wavfile.py,sha256=1HbZ4L8IBD6Fbg3pd5MQG4ZXy48YZA05t8XllSplhWk,9499
14
13
  auto_editor/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- auto_editor/formats/fcp11.py,sha256=Sff8fLZw0s0G88EVeBsn9vwzzga_KHIt2pGMww3V5jA,5411
14
+ auto_editor/formats/fcp11.py,sha256=qzo-qpHYsiHjOPjGBWjBeJUAACDmo8ijJkjslHTQH6Q,5196
16
15
  auto_editor/formats/fcp7.py,sha256=vd7cW8vwoTvFlp4Tc5DYSn-A7i9ck3jJJdKNqWVtFVQ,20285
17
16
  auto_editor/formats/json.py,sha256=Br-xHVHj59C0OPP2FwfJeht_fImepRXsaw0iDFvK7-w,7693
18
17
  auto_editor/formats/shotcut.py,sha256=-ES854LLFCMCBe100JRJedDmuk8zPev17aQMTrzPv-g,4923
19
- auto_editor/formats/utils.py,sha256=GIZw28WHuCIaZ_zMI0v6Kxbq0QaIpbLsdSegdYwQxQ8,1990
18
+ auto_editor/formats/utils.py,sha256=LYXDiqOk9WwUorLGw2D0M7In9BNDkoKikNawuks7hqE,1648
20
19
  auto_editor/lang/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
20
  auto_editor/lang/json.py,sha256=OsNcYlfEj8ZLlzLK-gkLcrCCKI7mJz9rpe-6XLr4f9U,9231
22
21
  auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
@@ -28,31 +27,30 @@ auto_editor/lib/contracts.py,sha256=lExGQymcQUmwG5lC1lO4qm4GY8W0q_yzK_miTaAoPA4,
28
27
  auto_editor/lib/data_structs.py,sha256=dcsXgsLLzbmFDUZucoirzewPALsKzoxz7z5L22_QJM8,7091
29
28
  auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
30
29
  auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- auto_editor/render/audio.py,sha256=darKvlglNXkknSUaPnH-qEUyccM1Awnv03_Px4yY81I,8844
32
- auto_editor/render/subtitle.py,sha256=CNcU_hmLwfZ2yvmSllIK-pB7ge_YdXHR-fnnOVUO9m8,4425
33
- auto_editor/render/video.py,sha256=OWtziP6l9AuMdeb3I7CBv8SlgaXS5BcRilCX47BkadU,12492
30
+ auto_editor/render/audio.py,sha256=QF3nQMChIxL0GVy4AONvsnqrX_nqT31RrogLwxwWAO8,9650
31
+ auto_editor/render/subtitle.py,sha256=HCWL9HvFXZPeGUd0mI1K5okHnKf1f6hw-DgPFFPOKA0,4499
32
+ auto_editor/render/video.py,sha256=gQJx_zcqvL__WJNG8mfFWblSr8XFkuCeIW3nCXoIdKU,12487
34
33
  auto_editor/subcommands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
34
  auto_editor/subcommands/desc.py,sha256=GDrKJYiHMaeTrplZAceXl1JwoqD78XsV2_5lc0Xd7po,869
36
35
  auto_editor/subcommands/info.py,sha256=t5n43HLt9hpMFSIfGV777X4zIPBAFugOKlpCfRjiKxY,6921
37
- auto_editor/subcommands/levels.py,sha256=ZB8_9jbOA5s1AQUcUNZDiLAjyJOKl7Be2YeVWdkOr0Q,4071
36
+ auto_editor/subcommands/levels.py,sha256=ChJMDTd34-jgxewqHRmmd3VNhFdy964w0DcQG0ls-hY,4079
38
37
  auto_editor/subcommands/palet.py,sha256=ONzTqemaQq9YEfIOsDRNnwzfqnEMUMSXIQrETxyroRU,749
39
- auto_editor/subcommands/repl.py,sha256=hpdF-CrOzdkChmj7zhx8P-lNWLmFfVR_VAnSUt0aaNU,3176
38
+ auto_editor/subcommands/repl.py,sha256=DuMz5kImoZFSVMZh6sPQxqZXMbRXPCvXoW3G-MJfivc,3166
40
39
  auto_editor/subcommands/subdump.py,sha256=af_XBf7kaevqHn1A71z8C-7x8pS5WKD9FE_ugkCw6rk,665
41
- auto_editor/subcommands/test.py,sha256=PdJAIR6HRTL_FGVPYlQMq4uW-5U4Hz515O29nPbSZyg,25322
40
+ auto_editor/subcommands/test.py,sha256=ovYMX5_Fm1qSq8_ojnBj78W9vqkZImoNkbdCSIFFft0,25668
42
41
  auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- auto_editor/utils/bar.py,sha256=RJqkJ8gNr8op_Z-2hh48ExjSonmTPX-RshctK_itv14,3988
42
+ auto_editor/utils/bar.py,sha256=hG_NiYeuM90TdILzAJORft-UOS5grwWN3SbRuj6upsI,3998
44
43
  auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
45
44
  auto_editor/utils/cmdkw.py,sha256=uW_qDGQ6UzLPRbB20HTLrCmhMlWVXSfgyQMr4MyGErU,5734
46
45
  auto_editor/utils/container.py,sha256=RnpoMmMYmn7o69LmMbBFHW4TsP3K52jYDhG9qzWXmAs,2720
47
46
  auto_editor/utils/encoder.py,sha256=auNYo7HXbcU4iTUCc0LE5lpwFmSvdWvBm6-5KIaRK8w,2983
48
- auto_editor/utils/func.py,sha256=kcxCOqe-tg6k-kxutIran8LpffRiHDjKB6rm-ngFiSU,4460
47
+ auto_editor/utils/func.py,sha256=3p5f6BxC6wMjsolLSfrcx7OwVQnMRAprwBI7MQ8TjB0,3725
49
48
  auto_editor/utils/log.py,sha256=M2QKeQHMRNLm3HMVUKedZPRprT2u5dipOStiO4miPBk,3613
50
- auto_editor/utils/subtitle_tools.py,sha256=TjjVPiT8bWzZJcrZjF7ddpgfIsVkLE4LyxXzBswHAGU,693
51
- auto_editor/utils/types.py,sha256=49V5Fo6LlQIPWU7Gzsl8Y5_c0lsZOIJuEVWp__TWL5M,11450
52
- docs/build.py,sha256=8nJM_CgkSL5ilvzcJDGNjzoWpCphPJKZKguHazG6YK8,1641
53
- auto_editor-25.2.0.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
54
- auto_editor-25.2.0.dist-info/METADATA,sha256=EFLXuvw_VPO4Jhrku1AuiRpir3uQb8PUyC_cxBN0_f0,6148
55
- auto_editor-25.2.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
56
- auto_editor-25.2.0.dist-info/entry_points.txt,sha256=-H7zdTw4MqnAcwrN5xTNkGIhzZtJMxS9r6lTMeR9-aA,240
57
- auto_editor-25.2.0.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
58
- auto_editor-25.2.0.dist-info/RECORD,,
49
+ auto_editor/utils/types.py,sha256=BWj0YalUpWwXfEN7AEL5s_j22lscZOH-eb7x_dYuXfY,11471
50
+ docs/build.py,sha256=CM-ZWgQk8wSNjivx_-6wGIaG7cstrNKsX2d4TzFVivE,1642
51
+ auto_editor-25.3.1.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
52
+ auto_editor-25.3.1.dist-info/METADATA,sha256=0GOm0ktkMSsxqnTtALdMBcxK_IrYPMgFuSjUN-Xs9F0,6148
53
+ auto_editor-25.3.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
54
+ auto_editor-25.3.1.dist-info/entry_points.txt,sha256=-H7zdTw4MqnAcwrN5xTNkGIhzZtJMxS9r6lTMeR9-aA,240
55
+ auto_editor-25.3.1.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
+ auto_editor-25.3.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
docs/build.py CHANGED
@@ -49,5 +49,6 @@ def main():
49
49
  print(e)
50
50
  quit(1)
51
51
 
52
+
52
53
  if __name__ == "__main__":
53
54
  main()
@@ -1,29 +0,0 @@
1
- def convert_ass_to_text(ass_text: str) -> str:
2
- result = ""
3
- comma_count = i = 0
4
-
5
- while comma_count < 8 and i < len(ass_text):
6
- if ass_text[i] == ",":
7
- comma_count += 1
8
- i += 1
9
-
10
- state = False
11
- while i < len(ass_text):
12
- char = ass_text[i]
13
- next_char = "" if i + 1 >= len(ass_text) else ass_text[i + 1]
14
-
15
- if char == "\\" and next_char == "N":
16
- result += "\n"
17
- i += 2
18
- continue
19
-
20
- if not state:
21
- if char == "{":
22
- state = True
23
- else:
24
- result += ass_text[i]
25
- elif char == "}":
26
- state = False
27
- i += 1
28
-
29
- return result
@@ -1,88 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import re
4
- import subprocess
5
- import sys
6
- from os.path import exists, isdir, isfile, lexists, splitext
7
-
8
- from auto_editor.ffwrapper import FFmpeg
9
- from auto_editor.utils.func import get_stdout
10
- from auto_editor.utils.log import Log
11
- from auto_editor.utils.types import Args
12
-
13
-
14
- def get_domain(url: str) -> str:
15
- from urllib.parse import urlparse
16
-
17
- t = urlparse(url).netloc
18
- return ".".join(t.split(".")[-2:])
19
-
20
-
21
- def download_video(my_input: str, args: Args, ffmpeg: FFmpeg, log: Log) -> str:
22
- log.conwrite("Downloading video...")
23
-
24
- download_format = args.download_format
25
-
26
- if download_format is None and get_domain(my_input) == "youtube.com":
27
- download_format = "bestvideo[ext=mp4]+bestaudio[ext=m4a]"
28
-
29
- if args.output_format is None:
30
- output_format = re.sub(r"\W+", "-", splitext(my_input)[0]) + ".%(ext)s"
31
- else:
32
- output_format = args.output_format
33
-
34
- yt_dlp_path = args.yt_dlp_location
35
-
36
- cmd = ["--ffmpeg-location", ffmpeg.path]
37
-
38
- if download_format is not None:
39
- cmd.extend(["-f", download_format])
40
-
41
- cmd.extend(["-o", output_format, my_input])
42
-
43
- if args.yt_dlp_extras is not None:
44
- cmd.extend(args.yt_dlp_extras.split(" "))
45
-
46
- try:
47
- location = get_stdout(
48
- [yt_dlp_path, "--get-filename", "--no-warnings"] + cmd
49
- ).strip()
50
- except FileNotFoundError:
51
- msg = "Could not find program 'yt-dlp' when attempting to download a URL. Install yt-dlp with "
52
- if sys.platform == "win32":
53
- msg += "your favorite package manager (pip, choco, winget)."
54
- elif sys.platform == "darwin":
55
- msg += "brew or pip and make sure it's in PATH."
56
- else:
57
- msg += "pip or your favorite package manager and make sure it's in PATH."
58
- log.error(msg)
59
-
60
- if not isfile(location):
61
- subprocess.run([yt_dlp_path] + cmd)
62
-
63
- if not isfile(location):
64
- log.error(f"Download file wasn't created: {location}")
65
-
66
- return location
67
-
68
-
69
- def valid_input(inputs: list[str], ffmpeg: FFmpeg, args: Args, log: Log) -> list[str]:
70
- result = []
71
-
72
- for my_input in inputs:
73
- if my_input.startswith("http://") or my_input.startswith("https://"):
74
- result.append(download_video(my_input, args, ffmpeg, log))
75
- else:
76
- _, ext = splitext(my_input)
77
- if ext == "":
78
- if isdir(my_input):
79
- log.error("Input must be a file or a URL, not a directory.")
80
- if exists(my_input):
81
- log.error(f"Input file must have an extension: {my_input}")
82
- if lexists(my_input):
83
- log.error(f"Input file is a broken symbolic link: {my_input}")
84
- if my_input.startswith("-"):
85
- log.error(f"Option/Input file doesn't exist: {my_input}")
86
- result.append(my_input)
87
-
88
- return result