auto-editor 23.20.1__tar.gz → 23.21.1__tar.gz

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 (61) hide show
  1. {auto-editor-23.20.1 → auto-editor-23.21.1}/PKG-INFO +1 -1
  2. auto-editor-23.21.1/auto_editor/__init__.py +2 -0
  3. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/formats/fcp7.py +58 -8
  4. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/formats/shotcut.py +1 -1
  5. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lang/json.py +1 -1
  6. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lang/palet.py +5 -3
  7. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lib/data_structs.py +5 -3
  8. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/render/audio.py +2 -2
  9. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/test.py +1 -1
  10. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/wavfile.py +70 -80
  11. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/PKG-INFO +1 -1
  12. auto-editor-23.20.1/auto_editor/__init__.py +0 -2
  13. {auto-editor-23.20.1 → auto-editor-23.21.1}/LICENSE +0 -0
  14. {auto-editor-23.20.1 → auto-editor-23.21.1}/README.md +0 -0
  15. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/__main__.py +0 -0
  16. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/analyze.py +0 -0
  17. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/edit.py +0 -0
  18. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/ffwrapper.py +0 -0
  19. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/formats/__init__.py +0 -0
  20. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/formats/final_cut_pro.py +0 -0
  21. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/formats/json.py +0 -0
  22. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/formats/utils.py +0 -0
  23. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/help.py +0 -0
  24. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lang/__init__.py +0 -0
  25. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lib/__init__.py +0 -0
  26. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lib/contracts.py +0 -0
  27. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/lib/err.py +0 -0
  28. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/make_layers.py +0 -0
  29. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/output.py +0 -0
  30. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/preview.py +0 -0
  31. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/render/__init__.py +0 -0
  32. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/render/image.py +0 -0
  33. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/render/subtitle.py +0 -0
  34. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/render/video.py +0 -0
  35. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/__init__.py +0 -0
  36. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/desc.py +0 -0
  37. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/info.py +0 -0
  38. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/levels.py +0 -0
  39. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/palet.py +0 -0
  40. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/repl.py +0 -0
  41. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/subcommands/subdump.py +0 -0
  42. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/timeline.py +0 -0
  43. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/__init__.py +0 -0
  44. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/bar.py +0 -0
  45. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/chunks.py +0 -0
  46. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/cmdkw.py +0 -0
  47. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/container.py +0 -0
  48. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/encoder.py +0 -0
  49. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/func.py +0 -0
  50. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/log.py +0 -0
  51. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/utils/types.py +0 -0
  52. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/validate_input.py +0 -0
  53. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor/vanparse.py +0 -0
  54. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/SOURCES.txt +0 -0
  55. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/dependency_links.txt +0 -0
  56. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/entry_points.txt +0 -0
  57. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/requires.txt +0 -0
  58. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/top_level.txt +0 -0
  59. {auto-editor-23.20.1 → auto-editor-23.21.1}/auto_editor.egg-info/zip-safe +0 -0
  60. {auto-editor-23.20.1 → auto-editor-23.21.1}/setup.cfg +0 -0
  61. {auto-editor-23.20.1 → auto-editor-23.21.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-editor
3
- Version: 23.20.1
3
+ Version: 23.21.1
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Home-page: https://auto-editor.com
6
6
  Author: WyattBlue
@@ -0,0 +1,2 @@
1
+ __version__ = "23.21.1"
2
+ version = "23w21a"
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os.path
4
3
  import xml.etree.ElementTree as ET
5
4
  from fractions import Fraction
5
+ from io import StringIO
6
6
  from math import ceil
7
7
  from typing import TYPE_CHECKING
8
8
  from xml.etree.ElementTree import Element
@@ -34,16 +34,63 @@ DEPTH = "16"
34
34
 
35
35
 
36
36
  def uri_to_path(uri: str) -> str:
37
- from urllib.parse import urlparse
38
- from urllib.request import url2pathname
39
-
40
- parsed = urlparse(uri)
41
- s = os.path.sep
42
- host = f"{s}{s}{parsed.netloc}{s}"
43
- return os.path.normpath(os.path.join(host, url2pathname(parsed.path)))
37
+ def de_norm(s: str) -> str:
38
+ uri_escape = {
39
+ "3C": "<",
40
+ "3E": ">",
41
+ "23": "#",
42
+ "25": "%",
43
+ "2B": "+",
44
+ "7B": "{",
45
+ "7D": "}",
46
+ "7C": "|",
47
+ "5C": "\\",
48
+ "5E": "^",
49
+ "7E": "~",
50
+ "5B": "[",
51
+ "5D": "]",
52
+ "60": "`",
53
+ "3F": "?",
54
+ "3A": ":",
55
+ "40": "@",
56
+ "3D": "=",
57
+ "2A": "*",
58
+ "29": ")",
59
+ "28": "(",
60
+ "27": "'",
61
+ "26": "&",
62
+ "24": "$",
63
+ "22": '"',
64
+ "21": "!",
65
+ "20": " ",
66
+ }
67
+ buf = StringIO()
68
+ i = 0
69
+ while i < len(s):
70
+ if s[i] == "%" and len(s) > i + 3:
71
+ tag = s[i + 1 : i + 3]
72
+ if tag in uri_escape:
73
+ buf.write(uri_escape[tag])
74
+ i += 3
75
+ else:
76
+ buf.write(s[i])
77
+ i += 1
78
+ else:
79
+ buf.write(s[i])
80
+ i += 1
81
+ return buf.getvalue()
82
+
83
+ if uri.startswith("file://localhost/"):
84
+ return de_norm(uri[16:])
85
+ if uri.startswith("file://"):
86
+ if uri[9] == ":": # Handle Windows-style paths
87
+ return de_norm(uri[8:])
88
+ return de_norm(uri[7:])
89
+ return uri
44
90
 
45
91
  # /Users/wyattblue/projects/auto-editor/example.mp4
46
92
  # file:///Users/wyattblue/projects/auto-editor/example.mp4
93
+ # file:///C:/Users/WyattBlue/projects/auto-editor/example.mp4
47
94
  # file://localhost/Users/wyattblue/projects/auto-editor/example.mp4
48
95
 
49
96
 
@@ -307,6 +354,9 @@ def media_def(
307
354
  ET.SubElement(rate, "timebase").text = f"{tb}"
308
355
  ET.SubElement(rate, "ntsc").text = ntsc
309
356
 
357
+ # DaVinci Resolve needs this tag even though it's blank
358
+ ET.SubElement(filedef, "duration").text = ""
359
+
310
360
  mediadef = ET.SubElement(filedef, "media")
311
361
 
312
362
  if len(src.videos) > 0:
@@ -38,7 +38,7 @@ def shotcut_write_mlt(output: str, tl: v3) -> None:
38
38
  tb = tl.tb
39
39
  src = tl.v1.source
40
40
 
41
- profile = ET.SubElement(
41
+ ET.SubElement(
42
42
  mlt,
43
43
  "profile",
44
44
  attrib={
@@ -121,7 +121,7 @@ class Lexer:
121
121
  self.advance()
122
122
 
123
123
  if self.char is None:
124
- self.error(f'Expected a closing `"`')
124
+ self.error('Expected a closing `"`')
125
125
 
126
126
  self.advance()
127
127
  return result.getvalue()
@@ -134,7 +134,7 @@ class Lexer:
134
134
  self.advance()
135
135
 
136
136
  if self.char is None:
137
- self.close_err(f'Expected a closing `"`')
137
+ self.close_err('Expected a closing `"`')
138
138
 
139
139
  self.advance()
140
140
  return result.getvalue()
@@ -214,7 +214,7 @@ class Lexer:
214
214
  if result == "hash":
215
215
  self.advance()
216
216
  if self.char is None or self.char not in "([{":
217
- self.error(f"Expected an opening bracket after #hash")
217
+ self.error("Expected an opening bracket after #hash")
218
218
 
219
219
  brac_type = self.char
220
220
  self.advance()
@@ -754,7 +754,9 @@ class Syntax:
754
754
  def __call__(self, env: Env, node: list) -> Any:
755
755
  return self.syn(env, node)
756
756
 
757
- __str__: Callable[[Syntax], str] = lambda self: "#<syntax>"
757
+ def __str__(self) -> str:
758
+ return "#<syntax>"
759
+
758
760
  __repr__ = __str__
759
761
 
760
762
 
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  from fractions import Fraction
4
4
  from io import StringIO
5
- from typing import Callable
6
5
 
7
6
  import numpy as np
8
7
 
@@ -14,7 +13,9 @@ class Sym:
14
13
  self.val = val
15
14
  self.hash = hash(val)
16
15
 
17
- __str__: Callable[[Sym], str] = lambda self: self.val
16
+ def __str__(self) -> str:
17
+ return self.val
18
+
18
19
  __repr__ = __str__
19
20
 
20
21
  def __hash__(self) -> int:
@@ -34,7 +35,8 @@ class Char:
34
35
  assert type(val) is str and len(val) == 1
35
36
  self.val = val
36
37
 
37
- __str__: Callable[[Char], str] = lambda self: self.val
38
+ def __str__(self) -> str:
39
+ return self.val
38
40
 
39
41
  def __repr__(self) -> str:
40
42
  names = {" ": "space", "\n": "newline", "\t": "tab"}
@@ -182,10 +182,10 @@ def make_new_audio(
182
182
  if not tl.a or not tl.a[0]:
183
183
  log.error("Trying to render empty audio timeline")
184
184
 
185
- for l, layer in enumerate(tl.a):
185
+ for i, layer in enumerate(tl.a):
186
186
  bar.start(len(layer), "Creating new audio")
187
187
 
188
- path = Path(temp, f"new{l}.wav")
188
+ path = Path(temp, f"new{i}.wav")
189
189
  output.append(f"{path}")
190
190
  arr: AudioData | None = None
191
191
 
@@ -610,7 +610,7 @@ def main(sys_args: list[str] | None = None):
610
610
 
611
611
  def audio_norm_ebu():
612
612
  return run.main(
613
- ["example.mp4"], ["--audio-normalize", f"ebu:i=-5,lra=20,gain=5,tp=-1"]
613
+ ["example.mp4"], ["--audio-normalize", "ebu:i=-5,lra=20,gain=5,tp=-1"]
614
614
  )
615
615
 
616
616
  def palet():
@@ -16,13 +16,17 @@ Endian = Literal[">", "<"] # Big Endian, Little Endian
16
16
  ByteOrd = Literal["big", "little"]
17
17
 
18
18
 
19
+ class WavError(Exception):
20
+ pass
21
+
22
+
19
23
  def _read_fmt_chunk(
20
24
  fid: io.BufferedReader, bytes_order: ByteOrd
21
25
  ) -> tuple[int, int, int, int, int]:
22
26
  size = int.from_bytes(fid.read(4), bytes_order)
23
27
 
24
28
  if size < 16:
25
- raise ValueError("Binary structure of wave file is not compliant")
29
+ raise WavError("Binary structure of wave file is not compliant")
26
30
 
27
31
  format_tag = int.from_bytes(fid.read(2), bytes_order)
28
32
  channels = int.from_bytes(fid.read(2), bytes_order)
@@ -47,10 +51,10 @@ def _read_fmt_chunk(
47
51
  if raw_guid.endswith(tail):
48
52
  format_tag = int.from_bytes(raw_guid[:4], bytes_order)
49
53
  else:
50
- raise ValueError("Binary structure of wave file is not compliant")
54
+ raise WavError("Binary structure of wave file is not compliant")
51
55
 
52
56
  if format_tag not in {PCM, IEEE_FLOAT}:
53
- raise ValueError(
57
+ raise WavError(
54
58
  f"Encountered unknown format tag: {format_tag:#06x}, while reading fmt chunk."
55
59
  )
56
60
 
@@ -83,7 +87,7 @@ def _read_data_chunk(
83
87
  bytes_per_sample = block_align // channels
84
88
 
85
89
  if bytes_per_sample in (3, 5, 6, 7):
86
- raise ValueError(f"Unsupported bytes per sample: {bytes_per_sample}")
90
+ raise WavError(f"Unsupported bytes per sample: {bytes_per_sample}")
87
91
 
88
92
  if format_tag == PCM:
89
93
  if 1 <= bit_depth <= 8:
@@ -91,21 +95,20 @@ def _read_data_chunk(
91
95
  elif bit_depth <= 64:
92
96
  dtype = f"{en}i{bytes_per_sample}"
93
97
  else:
94
- raise ValueError(
98
+ raise WavError(
95
99
  f"Unsupported bit depth: the WAV file has {bit_depth}-bit integer data."
96
100
  )
97
101
  elif format_tag == IEEE_FLOAT:
98
102
  if bit_depth in (32, 64):
99
103
  dtype = f"{en}f{bytes_per_sample}"
100
104
  else:
101
- raise ValueError(
105
+ raise WavError(
102
106
  f"Unsupported bit depth: the WAV file has {bit_depth}-bit floating-point data."
103
107
  )
104
108
  else:
105
- raise ValueError(
109
+ raise WavError(
106
110
  f"Unknown wave file format: {format_tag:#06x}. Supported formats: PCM, IEEE_FLOAT"
107
111
  )
108
-
109
112
  if size % 2 == 0:
110
113
  n_samples = size // block_align
111
114
  else:
@@ -121,10 +124,20 @@ def _read_data_chunk(
121
124
 
122
125
 
123
126
  def _skip_unknown_chunk(fid: io.BufferedReader, en: Endian) -> None:
124
- if data := fid.read(4):
127
+ data = fid.read(4)
128
+
129
+ if len(data) == 4:
125
130
  size = struct.unpack(f"{en}I", data)[0]
131
+ if size == 0:
132
+ raise WavError("Unknown chunk size is 0")
126
133
  fid.seek(size, 1)
127
134
  _handle_pad_byte(fid, size)
135
+ elif len(data) == 0:
136
+ pass # It's okay, we've hit EOF
137
+ else:
138
+ raise WavError(
139
+ f"Unknown chunk size has wrong length, expected 4, got {len(data)}"
140
+ )
128
141
 
129
142
 
130
143
  def _read_rf64_chunk(fid: io.BufferedReader) -> tuple[int, int, Endian]:
@@ -133,7 +146,7 @@ def _read_rf64_chunk(fid: io.BufferedReader) -> tuple[int, int, Endian]:
133
146
 
134
147
  heading = fid.read(12)
135
148
  if heading != b"\xff\xff\xff\xffWAVEds64":
136
- raise ValueError(f"Invalid heading for rf64 chunk: {heading!r}")
149
+ raise WavError(f"Invalid heading for rf64 chunk: {heading!r}")
137
150
 
138
151
  chunk_size = fid.read(4)
139
152
 
@@ -163,7 +176,7 @@ def _read_riff_chunk(sig: bytes, fid: io.BufferedReader) -> tuple[None, int, End
163
176
 
164
177
  form = fid.read(4)
165
178
  if form != b"WAVE":
166
- raise ValueError(f"Not a WAV file. RIFF form type is {form!r}.")
179
+ raise WavError(f"Not a WAV file. RIFF form type is {form!r}.")
167
180
 
168
181
  return None, file_size, en
169
182
 
@@ -176,78 +189,64 @@ def _handle_pad_byte(fid: io.BufferedReader, size: int) -> None:
176
189
  def read(filename: str) -> tuple[int, AudioData]:
177
190
  fid = open(filename, "rb")
178
191
 
179
- try:
180
- file_sig = fid.read(4)
181
- if file_sig in (b"RIFF", b"RIFX"):
182
- data_size, file_size, en = _read_riff_chunk(file_sig, fid)
183
- elif file_sig == b"RF64":
184
- data_size, file_size, en = _read_rf64_chunk(fid)
185
- else:
186
- raise ValueError(f"File format {file_sig!r} not supported.")
187
-
188
- fmt_chunk_received = False
189
- data_chunk_received = False
190
- while fid.tell() < file_size:
191
- chunk_id = fid.read(4)
192
-
193
- if not chunk_id:
194
- if data_chunk_received:
195
- break # EOF but data successfully read
196
- raise ValueError("Unexpected end of file.")
197
-
198
- elif len(chunk_id) < 4 and not (fmt_chunk_received and data_chunk_received):
199
- raise ValueError(f"Incomplete chunk ID: {chunk_id!r}")
200
-
201
- if chunk_id == b"fmt ":
202
- fmt_chunk_received = True
203
- bytes_order: ByteOrd = "big" if en == ">" else "little"
204
- format_tag, channels, sr, block_align, bit_depth = _read_fmt_chunk(
205
- fid, bytes_order
206
- )
207
- elif chunk_id == b"data":
208
- data_chunk_received = True
209
- if not fmt_chunk_received:
210
- raise ValueError("No fmt chunk before data")
211
-
212
- data = _read_data_chunk(
213
- fid,
214
- format_tag,
215
- channels,
216
- bit_depth,
217
- en,
218
- block_align,
219
- data_size,
220
- )
221
- else:
222
- _skip_unknown_chunk(fid, en)
192
+ file_sig = fid.read(4)
193
+ if file_sig in (b"RIFF", b"RIFX"):
194
+ data_size, file_size, en = _read_riff_chunk(file_sig, fid)
195
+ elif file_sig == b"RF64":
196
+ data_size, file_size, en = _read_rf64_chunk(fid)
197
+ else:
198
+ raise WavError(f"File format {file_sig!r} not supported.")
223
199
 
224
- finally:
225
- fid.seek(0)
200
+ bytes_order: ByteOrd = "big" if en == ">" else "little"
201
+ fmt_chunk_received = False
226
202
 
227
- return sr, data
203
+ while fid.tell() < file_size:
204
+ chunk_id = fid.read(4)
228
205
 
206
+ if not chunk_id:
207
+ raise WavError("Unexpected end of file.")
208
+ if len(chunk_id) < 4:
209
+ raise WavError(f"Incomplete chunk ID: {chunk_id!r}")
229
210
 
230
- def write(fid: io.BufferedWriter, sr: int, arr: AudioData) -> None:
231
- # Write RIFF WAV Header
232
- fid.write(b"RIFF\x00\x00\x00\x00WAVE")
211
+ if chunk_id == b"fmt ":
212
+ fmt_chunk_received = True
213
+ format_tag, channels, sr, block_align, bit_depth = _read_fmt_chunk(
214
+ fid, bytes_order
215
+ )
216
+ elif chunk_id == b"data":
217
+ if not fmt_chunk_received:
218
+ raise WavError("No fmt chunk before data")
219
+
220
+ data = _read_data_chunk(
221
+ fid,
222
+ format_tag,
223
+ channels,
224
+ bit_depth,
225
+ en,
226
+ block_align,
227
+ data_size,
228
+ )
233
229
 
234
- # Write RF64 WAV Header
235
- # fid.write(b"RF64\xff\xff\xff\xffWAVEds64")
230
+ fid.seek(0)
231
+ return sr, data
236
232
 
237
- # # - chunk_size
238
- # fid.write(b'\x1c\x00\x00\x00') # Value based on bit-depth + '# of samples'
233
+ elif chunk_id == b"\x00\x00\x00\x00":
234
+ raise WavError("Invalid chunk ID")
235
+ else:
236
+ _skip_unknown_chunk(fid, en)
239
237
 
240
- # # - bw_size, Declaring Little Endian
241
- # fid.write(b'j@|\x00')
242
- # fid.write(b'\x00\x00\x00\x00')
238
+ raise WavError("Found no data")
243
239
 
244
- # Write 'fmt' Header
245
- dkind = arr.dtype.kind
246
240
 
241
+ def write(fid: io.BufferedWriter, sr: int, arr: AudioData) -> None:
242
+ # Write RIFF WAV Header
243
+ fid.write(b"RIFF\x00\x00\x00\x00WAVE")
247
244
  header_data = b"fmt "
248
245
 
246
+ dkind = arr.dtype.kind
249
247
  format_tag = IEEE_FLOAT if dkind == "f" else PCM
250
248
  channels = 1 if arr.ndim == 1 else arr.shape[1]
249
+
251
250
  bit_depth = arr.dtype.itemsize * 8
252
251
  bit_rate = sr * (bit_depth // 8) * channels
253
252
  block_align = channels * (bit_depth // 8)
@@ -256,20 +255,11 @@ def write(fid: io.BufferedWriter, sr: int, arr: AudioData) -> None:
256
255
  "<HHIIHH", format_tag, channels, sr, bit_rate, block_align, bit_depth
257
256
  )
258
257
 
259
- if not (dkind == "i" or dkind == "u"):
260
- # add cbSize field for non-PCM files
261
- fmt_chunk_data += b"\x00\x00"
262
-
263
258
  header_data += struct.pack("<I", len(fmt_chunk_data))
264
259
  header_data += fmt_chunk_data
265
260
 
266
- # fact chunk (non-PCM files)
267
- if not (dkind == "i" or dkind == "u"):
268
- header_data += b"fact"
269
- header_data += struct.pack("<II", 4, arr.shape[0])
270
-
271
261
  if len(header_data) + arr.nbytes > 0xFFFFFFFF:
272
- raise ValueError("Data exceeds wave file size limit")
262
+ raise WavError("Data exceeds wave file size limit")
273
263
 
274
264
  fid.write(header_data)
275
265
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-editor
3
- Version: 23.20.1
3
+ Version: 23.21.1
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Home-page: https://auto-editor.com
6
6
  Author: WyattBlue
@@ -1,2 +0,0 @@
1
- __version__ = "23.20.1"
2
- version = "23w20a"
File without changes
File without changes
File without changes
File without changes