auto-editor 27.0.0__py3-none-any.whl → 27.1.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.
@@ -2,13 +2,12 @@ from __future__ import annotations
2
2
 
3
3
  import xml.etree.ElementTree as ET
4
4
  from fractions import Fraction
5
- from io import StringIO
6
5
  from math import ceil
7
6
  from typing import TYPE_CHECKING
8
7
  from xml.etree.ElementTree import Element
9
8
 
10
- from auto_editor.ffwrapper import FileInfo, initFileInfo
11
- from auto_editor.timeline import ASpace, TlAudio, TlVideo, VSpace, v3
9
+ from auto_editor.ffwrapper import FileInfo
10
+ from auto_editor.timeline import ASpace, Template, TlAudio, TlVideo, VSpace, v3
12
11
 
13
12
  from .utils import Validator, show
14
13
 
@@ -29,59 +28,20 @@ DEPTH = "16"
29
28
 
30
29
 
31
30
  def uri_to_path(uri: str) -> str:
32
- def de_norm(s: str) -> str:
33
- uri_escape = {
34
- "3C": "<",
35
- "3E": ">",
36
- "23": "#",
37
- "25": "%",
38
- "2B": "+",
39
- "7B": "{",
40
- "7D": "}",
41
- "7C": "|",
42
- "5C": "\\",
43
- "5E": "^",
44
- "7E": "~",
45
- "5B": "[",
46
- "5D": "]",
47
- "60": "`",
48
- "3F": "?",
49
- "3A": ":",
50
- "40": "@",
51
- "3D": "=",
52
- "2A": "*",
53
- "29": ")",
54
- "28": "(",
55
- "27": "'",
56
- "26": "&",
57
- "24": "$",
58
- "22": '"',
59
- "21": "!",
60
- "20": " ",
61
- }
62
- buf = StringIO()
63
- i = 0
64
- while i < len(s):
65
- if s[i] == "%" and len(s) > i + 3:
66
- tag = s[i + 1 : i + 3]
67
- if tag in uri_escape:
68
- buf.write(uri_escape[tag])
69
- i += 3
70
- else:
71
- buf.write(s[i])
72
- i += 1
73
- else:
74
- buf.write(s[i])
75
- i += 1
76
- return buf.getvalue()
31
+ urllib = __import__("urllib.parse", fromlist=["parse"])
77
32
 
78
33
  if uri.startswith("file://localhost/"):
79
- return de_norm(uri[16:])
80
- if uri.startswith("file://"):
81
- if uri[9] == ":": # Handle Windows-style paths
82
- return de_norm(uri[8:])
83
- return de_norm(uri[7:])
84
- return uri
34
+ uri = uri[16:]
35
+ elif uri.startswith("file://"):
36
+ # Windows-style paths
37
+ if len(uri) > 8 and uri[9] == ":":
38
+ uri = uri[8:]
39
+ else:
40
+ uri = uri[7:]
41
+ else:
42
+ return uri
43
+
44
+ return urllib.parse.unquote(uri)
85
45
 
86
46
  # /Users/wyattblue/projects/auto-editor/example.mp4
87
47
  # file:///Users/wyattblue/projects/auto-editor/example.mp4
@@ -282,7 +242,7 @@ def fcp7_read_xml(path: str, log: Log) -> v3:
282
242
  fileobj = valid.parse(clipitem["file"], {"pathurl": str})
283
243
 
284
244
  if "pathurl" in fileobj:
285
- sources[file_id] = initFileInfo(
245
+ sources[file_id] = FileInfo.init(
286
246
  uri_to_path(fileobj["pathurl"]),
287
247
  log,
288
248
  )
@@ -317,7 +277,7 @@ def fcp7_read_xml(path: str, log: Log) -> v3:
317
277
  file_id = clipitem["file"].attrib["id"]
318
278
  if file_id not in sources:
319
279
  fileobj = valid.parse(clipitem["file"], {"pathurl": str})
320
- sources[file_id] = initFileInfo(
280
+ sources[file_id] = FileInfo.init(
321
281
  uri_to_path(fileobj["pathurl"]), log
322
282
  )
323
283
 
@@ -336,10 +296,8 @@ def fcp7_read_xml(path: str, log: Log) -> v3:
336
296
  )
337
297
  )
338
298
 
339
- primary_src = sources[next(iter(sources))]
340
- assert type(primary_src) is FileInfo
341
-
342
- return v3(primary_src, tb, sr, res, "#000", vobjs, aobjs, v1=None)
299
+ T = Template.init(sources[next(iter(sources))], sr, res=res)
300
+ return v3(tb, "#000", T, vobjs, aobjs, v1=None)
343
301
 
344
302
 
345
303
  def media_def(
@@ -424,13 +382,14 @@ def resolve_write_audio(audio: Element, make_filedef, tl: v3) -> None:
424
382
  clipitem.append(speedup(aclip.speed * 100))
425
383
 
426
384
 
427
- def premiere_write_audio(audio: Element, make_filedef, src: FileInfo, tl: v3) -> None:
385
+ def premiere_write_audio(audio: Element, make_filedef, tl: v3) -> None:
428
386
  ET.SubElement(audio, "numOutputChannels").text = "2"
429
387
  aformat = ET.SubElement(audio, "format")
430
388
  aschar = ET.SubElement(aformat, "samplecharacteristics")
431
389
  ET.SubElement(aschar, "depth").text = DEPTH
432
390
  ET.SubElement(aschar, "samplerate").text = f"{tl.sr}"
433
391
 
392
+ has_video = tl.v and tl.v[0]
434
393
  t = 0
435
394
  for aclips in tl.a:
436
395
  for channelcount in range(0, 2): # Because "stereo" is hardcoded.
@@ -442,7 +401,7 @@ def premiere_write_audio(audio: Element, make_filedef, src: FileInfo, tl: v3) ->
442
401
  premiereTrackType="Stereo",
443
402
  )
444
403
 
445
- if src.videos:
404
+ if has_video:
446
405
  ET.SubElement(track, "outputchannelindex").text = f"{channelcount + 1}"
447
406
 
448
407
  for j, aclip in enumerate(aclips):
@@ -453,7 +412,7 @@ def premiere_write_audio(audio: Element, make_filedef, src: FileInfo, tl: v3) ->
453
412
  _in = f"{aclip.offset}"
454
413
  _out = f"{aclip.offset + aclip.dur}"
455
414
 
456
- if not src.videos:
415
+ if not has_video:
457
416
  clip_item_num = j + 1
458
417
  else:
459
418
  clip_item_num = len(aclips) + 1 + j + (t * len(aclips))
@@ -579,7 +538,7 @@ def fcp7_write_xml(name: str, output: str, resolve: bool, tl: v3) -> None:
579
538
  if resolve:
580
539
  resolve_write_audio(audio, make_filedef, tl)
581
540
  else:
582
- premiere_write_audio(audio, make_filedef, src, tl)
541
+ premiere_write_audio(audio, make_filedef, tl)
583
542
 
584
543
  tree = ET.ElementTree(xmeml)
585
544
  ET.indent(tree, space=" ", level=0)
@@ -6,11 +6,12 @@ from difflib import get_close_matches
6
6
  from fractions import Fraction
7
7
  from typing import Any
8
8
 
9
- from auto_editor.ffwrapper import FileInfo, initFileInfo
9
+ from auto_editor.ffwrapper import FileInfo
10
10
  from auto_editor.json import dump, load
11
11
  from auto_editor.lib.err import MyError
12
12
  from auto_editor.timeline import (
13
13
  ASpace,
14
+ Template,
14
15
  TlAudio,
15
16
  TlVideo,
16
17
  VSpace,
@@ -59,7 +60,7 @@ def read_v3(tl: Any, log: Log) -> v3:
59
60
  def make_src(v: str) -> FileInfo:
60
61
  if v in srcs:
61
62
  return srcs[v]
62
- temp = initFileInfo(v, log)
63
+ temp = FileInfo.init(v, log)
63
64
  srcs[v] = temp
64
65
  return temp
65
66
 
@@ -151,11 +152,11 @@ def read_v3(tl: Any, log: Log) -> v3:
151
152
  a.append(a_out)
152
153
 
153
154
  try:
154
- src = srcs[next(iter(srcs))]
155
+ T = Template.init(srcs[next(iter(srcs))])
155
156
  except StopIteration:
156
- src = None
157
+ T = Template(sr, "stereo", res, [], [])
157
158
 
158
- return v3(src, tb, sr, res, bg, v, a, v1=None)
159
+ return v3(tb, bg, T, v, a, v1=None)
159
160
 
160
161
 
161
162
  def read_v1(tl: Any, log: Log) -> v3:
@@ -168,7 +169,7 @@ def read_v1(tl: Any, log: Log) -> v3:
168
169
 
169
170
  check_file(path, log)
170
171
 
171
- src = initFileInfo(path, log)
172
+ src = FileInfo.init(path, log)
172
173
 
173
174
  vtl: VSpace = []
174
175
  atl: ASpace = [[] for _ in range(len(src.audios))]
@@ -207,11 +208,9 @@ def read_v1(tl: Any, log: Log) -> v3:
207
208
  atl[a].append(TlAudio(c.start, c.dur, c.src, c.offset, c.speed, 1, a))
208
209
 
209
210
  return v3(
210
- src,
211
211
  src.get_fps(),
212
- src.get_sr(),
213
- src.get_res(),
214
212
  "#000",
213
+ Template.init(src),
215
214
  vtl,
216
215
  atl,
217
216
  v1(src, chunks),
@@ -13,6 +13,7 @@ from .palet import Syntax, env, is_boolarr, is_iterable, my_eval, p_slice, raise
13
13
  if TYPE_CHECKING:
14
14
  from typing import Any, Literal
15
15
 
16
+ import numpy as np
16
17
  from numpy.typing import NDArray
17
18
 
18
19
  Number = int | float | complex | Fraction
@@ -11,7 +11,7 @@ from auto_editor.ffwrapper import FileInfo
11
11
  from auto_editor.lang.palet import Lexer, Parser, env, interpret, is_boolean_array
12
12
  from auto_editor.lib.data_structs import print_str
13
13
  from auto_editor.lib.err import MyError
14
- from auto_editor.timeline import ASpace, TlAudio, TlVideo, VSpace, v1, v3
14
+ from auto_editor.timeline import ASpace, Template, TlAudio, TlVideo, VSpace, v1, v3
15
15
  from auto_editor.utils.func import mut_margin
16
16
  from auto_editor.utils.types import CoerceError, time
17
17
 
@@ -99,16 +99,17 @@ def parse_time(val: str, arr: NDArray, tb: Fraction) -> int: # raises: `CoerceE
99
99
 
100
100
 
101
101
  def make_timeline(
102
- sources: list[FileInfo],
103
- args: Args,
104
- sr: int,
105
- bar: Bar,
106
- log: Log,
102
+ sources: list[FileInfo], args: Args, sr: int, bar: Bar, log: Log
107
103
  ) -> v3:
108
104
  inp = None if not sources else sources[0]
109
105
 
110
106
  if inp is None:
111
- tb, res = Fraction(30), (1920, 1080)
107
+ tb = (
108
+ Fraction(30)
109
+ if args.frame_rate is None
110
+ else make_sane_timebase(args.frame_rate)
111
+ )
112
+ res = (1920, 1080) if args.resolution is None else args.resolution
112
113
  else:
113
114
  tb = make_sane_timebase(
114
115
  inp.get_fps() if args.frame_rate is None else args.frame_rate
@@ -302,4 +303,13 @@ def make_timeline(
302
303
  else:
303
304
  v1_compatiable = None
304
305
 
305
- return v3(inp, tb, sr, res, args.background, vtl, atl, v1_compatiable)
306
+ if len(vtl) == 0 and len(atl) == 0:
307
+ log.error("Timeline is empty, nothing to do.")
308
+
309
+ if inp is None:
310
+ layout = "stereo" if args.audio_layout is None else args.audio_layout
311
+ template = Template(sr, layout, res, [], [])
312
+ else:
313
+ template = Template.init(inp, sr, args.audio_layout, res)
314
+
315
+ return v3(tb, args.background, template, vtl, atl, v1_compatiable)