auto-editor 24.7.1__tar.gz → 24.13.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 (65) hide show
  1. {auto-editor-24.7.1/auto_editor.egg-info → auto-editor-24.13.1}/PKG-INFO +3 -3
  2. {auto-editor-24.7.1 → auto-editor-24.13.1}/ae-ffmpeg/ae_ffmpeg/__init__.py +1 -1
  3. auto-editor-24.13.1/auto_editor/__init__.py +2 -0
  4. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/analyze.py +0 -82
  5. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/edit.py +2 -2
  6. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/ffwrapper.py +23 -47
  7. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/formats/fcp11.py +6 -6
  8. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/formats/fcp7.py +11 -11
  9. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/formats/json.py +8 -8
  10. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/help.py +5 -6
  11. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lang/palet.py +143 -60
  12. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lib/contracts.py +57 -10
  13. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lib/data_structs.py +1 -0
  14. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/output.py +14 -7
  15. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/render/video.py +24 -23
  16. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/desc.py +2 -4
  17. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/info.py +24 -19
  18. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/levels.py +1 -1
  19. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/repl.py +1 -1
  20. auto-editor-24.13.1/auto_editor/subcommands/subdump.py +23 -0
  21. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/test.py +11 -7
  22. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/cmdkw.py +41 -0
  23. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/wavfile.py +3 -3
  24. {auto-editor-24.7.1 → auto-editor-24.13.1/auto_editor.egg-info}/PKG-INFO +3 -3
  25. auto-editor-24.13.1/auto_editor.egg-info/requires.txt +3 -0
  26. {auto-editor-24.7.1 → auto-editor-24.13.1}/pyproject.toml +2 -2
  27. auto-editor-24.7.1/auto_editor/__init__.py +0 -2
  28. auto-editor-24.7.1/auto_editor/subcommands/subdump.py +0 -58
  29. auto-editor-24.7.1/auto_editor.egg-info/requires.txt +0 -3
  30. {auto-editor-24.7.1 → auto-editor-24.13.1}/LICENSE +0 -0
  31. {auto-editor-24.7.1 → auto-editor-24.13.1}/README.md +0 -0
  32. {auto-editor-24.7.1 → auto-editor-24.13.1}/ae-ffmpeg/ae_ffmpeg/py.typed +0 -0
  33. {auto-editor-24.7.1 → auto-editor-24.13.1}/ae-ffmpeg/setup.py +0 -0
  34. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/__main__.py +0 -0
  35. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/formats/__init__.py +0 -0
  36. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/formats/shotcut.py +0 -0
  37. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/formats/utils.py +0 -0
  38. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lang/__init__.py +0 -0
  39. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lang/json.py +0 -0
  40. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lang/libmath.py +0 -0
  41. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lib/__init__.py +0 -0
  42. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/lib/err.py +0 -0
  43. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/make_layers.py +0 -0
  44. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/preview.py +0 -0
  45. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/render/__init__.py +0 -0
  46. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/render/audio.py +0 -0
  47. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/render/subtitle.py +0 -0
  48. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/__init__.py +0 -0
  49. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/subcommands/palet.py +0 -0
  50. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/timeline.py +0 -0
  51. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/__init__.py +0 -0
  52. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/bar.py +0 -0
  53. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/chunks.py +0 -0
  54. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/container.py +0 -0
  55. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/encoder.py +0 -0
  56. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/func.py +0 -0
  57. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/log.py +0 -0
  58. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/utils/types.py +0 -0
  59. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/validate_input.py +0 -0
  60. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor/vanparse.py +0 -0
  61. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor.egg-info/SOURCES.txt +0 -0
  62. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor.egg-info/dependency_links.txt +0 -0
  63. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor.egg-info/entry_points.txt +0 -0
  64. {auto-editor-24.7.1 → auto-editor-24.13.1}/auto_editor.egg-info/top_level.txt +0 -0
  65. {auto-editor-24.7.1 → auto-editor-24.13.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-editor
3
- Version: 24.7.1
3
+ Version: 24.13.1
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Author-email: WyattBlue <wyattblue@auto-editor.com>
6
6
  License: Unlicense
@@ -12,8 +12,8 @@ Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: numpy>=1.22.0
15
- Requires-Dist: pyav==12.0.2
16
- Requires-Dist: ae-ffmpeg==1.1.*
15
+ Requires-Dist: pyav==12.0.5
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>
19
19
 
@@ -1,4 +1,4 @@
1
- __version__ = "1.1.2"
1
+ __version__ = "1.2.0"
2
2
 
3
3
  import os.path
4
4
  from platform import machine, system
@@ -0,0 +1,2 @@
1
+ __version__ = "24.13.1"
2
+ version = "24w13a"
@@ -21,13 +21,10 @@ from auto_editor.lib.contracts import (
21
21
  from auto_editor.lib.data_structs import Sym
22
22
  from auto_editor.render.subtitle import SubtitleParser
23
23
  from auto_editor.utils.cmdkw import (
24
- ParserError,
25
24
  Required,
26
- parse_with_palet,
27
25
  pAttr,
28
26
  pAttrs,
29
27
  )
30
- from auto_editor.utils.func import boolop
31
28
  from auto_editor.wavfile import read
32
29
 
33
30
  if TYPE_CHECKING:
@@ -38,7 +35,6 @@ if TYPE_CHECKING:
38
35
  from numpy.typing import NDArray
39
36
 
40
37
  from auto_editor.ffwrapper import FileInfo
41
- from auto_editor.lib.data_structs import Env
42
38
  from auto_editor.output import Ensure
43
39
  from auto_editor.utils.bar import Bar
44
40
  from auto_editor.utils.log import Log
@@ -412,81 +408,3 @@ class Levels:
412
408
 
413
409
  self.bar.end()
414
410
  return self.cache("motion", mobj, threshold_list[:index])
415
-
416
-
417
- def edit_method(val: str, filesetup: FileSetup, env: Env) -> NDArray[np.bool_]:
418
- assert isinstance(filesetup, FileSetup)
419
- src = filesetup.src
420
- tb = filesetup.tb
421
- ensure = filesetup.ensure
422
- strict = filesetup.strict
423
- bar = filesetup.bar
424
- temp = filesetup.temp
425
- log = filesetup.log
426
-
427
- if ":" in val:
428
- method, attrs = val.split(":", 1)
429
- else:
430
- method, attrs = val, ""
431
-
432
- levels = Levels(ensure, src, tb, bar, temp, log)
433
-
434
- if method == "none":
435
- return levels.none()
436
- if method == "all/e":
437
- return levels.all()
438
-
439
- try:
440
- obj = parse_with_palet(attrs, builder_map[method], env)
441
- except ParserError as e:
442
- log.error(e)
443
-
444
- try:
445
- if method == "audio":
446
- s = obj["stream"]
447
- if s == "all" or s == Sym("all"):
448
- total_list: NDArray[np.bool_] | None = None
449
- for s in range(len(src.audios)):
450
- audio_list = to_threshold(levels.audio(s), obj["threshold"])
451
- if total_list is None:
452
- total_list = audio_list
453
- else:
454
- total_list = boolop(total_list, audio_list, np.logical_or)
455
-
456
- if total_list is None:
457
- if strict:
458
- log.error("Input has no audio streams.")
459
- stream_data = levels.all()
460
- else:
461
- stream_data = total_list
462
- else:
463
- assert isinstance(s, int)
464
- stream_data = to_threshold(levels.audio(s), obj["threshold"])
465
-
466
- assert isinstance(obj["minclip"], int)
467
- assert isinstance(obj["mincut"], int)
468
-
469
- mut_remove_small(stream_data, obj["minclip"], replace=1, with_=0)
470
- mut_remove_small(stream_data, obj["mincut"], replace=0, with_=1)
471
-
472
- return stream_data
473
-
474
- if method == "motion":
475
- return to_threshold(
476
- levels.motion(obj["stream"], obj["blur"], obj["width"]),
477
- obj["threshold"],
478
- )
479
-
480
- if method == "subtitle":
481
- return levels.subtitle(
482
- obj["pattern"],
483
- obj["stream"],
484
- obj["ignore_case"],
485
- obj["max_count"],
486
- )
487
- except LevelError as e:
488
- if strict:
489
- log.error(e)
490
-
491
- return levels.all()
492
- raise ValueError("Unreachable")
@@ -177,11 +177,11 @@ def edit_media(
177
177
  elif path_ext == ".json":
178
178
  from auto_editor.formats.json import read_json
179
179
 
180
- tl = read_json(paths[0], ffmpeg, log)
180
+ tl = read_json(paths[0], log)
181
181
  sources = [] if tl.src is None else [tl.src]
182
182
  src = tl.src
183
183
  else:
184
- sources = [initFileInfo(path, ffmpeg, log) for path in paths]
184
+ sources = [initFileInfo(path, log) for path in paths]
185
185
  src = None if not sources else sources[0]
186
186
 
187
187
  del paths
@@ -135,10 +135,10 @@ class VideoStream:
135
135
  sar: Fraction
136
136
  time_base: Fraction | None
137
137
  pix_fmt: str | None
138
- color_range: str | None
139
- color_space: str | None
140
- color_primaries: str | None
141
- color_transfer: str | None
138
+ color_range: int
139
+ color_space: int
140
+ color_primaries: int
141
+ color_transfer: int
142
142
  bitrate: int
143
143
  lang: str | None
144
144
 
@@ -189,7 +189,7 @@ class FileInfo:
189
189
  return f"@{self.path.name}"
190
190
 
191
191
 
192
- def initFileInfo(path: str, ffmpeg: FFmpeg, log: Log) -> FileInfo:
192
+ def initFileInfo(path: str, log: Log) -> FileInfo:
193
193
  import av
194
194
 
195
195
  av.logging.set_level(av.logging.PANIC)
@@ -203,14 +203,11 @@ def initFileInfo(path: str, ffmpeg: FFmpeg, log: Log) -> FileInfo:
203
203
  audios: tuple[AudioStream, ...] = ()
204
204
  subtitles: tuple[SubtitleStream, ...] = ()
205
205
 
206
- _dir = os.path.dirname(ffmpeg.path)
207
- _ext = os.path.splitext(ffmpeg.path)[1]
208
- ffprobe = os.path.join(_dir, f"ffprobe{_ext}")
209
-
210
- for i, v in enumerate(cont.streams.video):
211
- vdur = 0.0
206
+ for v in cont.streams.video:
212
207
  if v.duration is not None and v.time_base is not None:
213
208
  vdur = float(v.duration * v.time_base)
209
+ else:
210
+ vdur = 0.0
214
211
 
215
212
  fps = v.average_rate
216
213
  if (fps is None or fps < 1) and v.name in ("png", "mjpeg", "webp"):
@@ -218,33 +215,11 @@ def initFileInfo(path: str, ffmpeg: FFmpeg, log: Log) -> FileInfo:
218
215
  if fps is None or fps == 0:
219
216
  fps = Fraction(30)
220
217
 
221
- _sar = c_range = c_space = c_primary = c_transfer = None
222
- try:
223
- _raw = get_stdout(
224
- [
225
- ffprobe,
226
- "-v",
227
- "error",
228
- "-select_streams",
229
- f"v:{i}",
230
- "-show_entries",
231
- "stream=sample_aspect_ratio:stream=color_range:stream=color_space:stream=color_primaries:stream=color_transfer",
232
- "-of",
233
- "default=noprint_wrappers=1:nokey=1",
234
- path,
235
- ]
236
- )
237
- _sar, c_range, c_space, c_primary, c_transfer = _raw.strip().split("\n")
238
- except Exception:
239
- log.debug("Unexpected ffprobe shape")
240
-
241
- if v.sample_aspect_ratio is None:
242
- try:
243
- sar = Fraction(_sar.replace(":", "/"))
244
- except Exception:
245
- sar = Fraction(1)
246
- else:
247
- sar = v.sample_aspect_ratio
218
+ sar = Fraction(1) if v.sample_aspect_ratio is None else v.sample_aspect_ratio
219
+ cc = v.codec_context
220
+
221
+ if v.name is None:
222
+ log.error(f"Can't detect codec for video stream {v}")
248
223
 
249
224
  videos += (
250
225
  VideoStream(
@@ -255,11 +230,11 @@ def initFileInfo(path: str, ffmpeg: FFmpeg, log: Log) -> FileInfo:
255
230
  vdur,
256
231
  sar,
257
232
  v.time_base,
258
- v.codec_context.pix_fmt,
259
- c_range,
260
- c_space,
261
- c_primary,
262
- c_transfer,
233
+ cc.pix_fmt,
234
+ cc.color_range,
235
+ cc.colorspace,
236
+ cc.color_primaries,
237
+ cc.color_trc,
263
238
  0 if v.bit_rate is None else v.bit_rate,
264
239
  v.language,
265
240
  ),
@@ -270,13 +245,14 @@ def initFileInfo(path: str, ffmpeg: FFmpeg, log: Log) -> FileInfo:
270
245
  if a.duration is not None and a.time_base is not None:
271
246
  adur = float(a.duration * a.time_base)
272
247
 
248
+ a_cc = a.codec_context
273
249
  audios += (
274
250
  AudioStream(
275
- a.codec_context.name,
276
- 0 if a.sample_rate is None else a.sample_rate,
277
- a.channels,
251
+ a_cc.name,
252
+ 0 if a_cc.sample_rate is None else a_cc.sample_rate,
253
+ a_cc.channels,
278
254
  adur,
279
- 0 if a.bit_rate is None else a.bit_rate,
255
+ 0 if a_cc.bit_rate is None else a_cc.bit_rate,
280
256
  a.language,
281
257
  ),
282
258
  )
@@ -32,13 +32,13 @@ def get_colorspace(src: FileInfo) -> str:
32
32
  s = src.videos[0]
33
33
  if s.pix_fmt == "rgb24":
34
34
  return "sRGB IEC61966-2.1"
35
- if s.color_space == "smpte170m":
36
- return "6-1-6 (Rec. 601 NTSC)"
37
- if s.color_space == "bt470bg":
35
+ if s.color_space == 5: # "bt470bg"
38
36
  return "5-1-6 (Rec. 601 PAL)"
39
- if s.color_primaries == "bt2020":
37
+ if s.color_space == 6: # "smpte170m"
38
+ return "6-1-6 (Rec. 601 NTSC)"
39
+ if s.color_primaries == 9: # "bt2020"
40
40
  # See: https://video.stackexchange.com/questions/22059/how-to-identify-hdr-video
41
- if s.color_transfer in ("arib-std-b67", "smpte2084"):
41
+ if s.color_transfer in (16, 18): # "smpte2084" "arib-std-b67"
42
42
  return "9-18-9 (Rec. 2020 HLG)"
43
43
  return "9-1-9 (Rec. 2020)"
44
44
 
@@ -79,7 +79,7 @@ def fcp11_write_xml(
79
79
  ffmpeg.run(
80
80
  ["-i", f"{src.path.resolve()}", "-map", f"0:a:{i}", f"{newtrack}"]
81
81
  )
82
- all_srcs.append(initFileInfo(f"{newtrack}", ffmpeg, log))
82
+ all_srcs.append(initFileInfo(f"{newtrack}", log))
83
83
  all_refs.append(f"r{(i + 1) * 2}")
84
84
 
85
85
  fcpxml = Element("fcpxml", version="1.10" if flavor == "resolve" else "1.11")
@@ -281,7 +281,6 @@ def fcp7_read_xml(path: str, ffmpeg: FFmpeg, log: Log) -> v3:
281
281
  if "pathurl" in fileobj:
282
282
  sources[file_id] = initFileInfo(
283
283
  uri_to_path(fileobj["pathurl"]),
284
- ffmpeg,
285
284
  log,
286
285
  )
287
286
  else:
@@ -315,7 +314,7 @@ def fcp7_read_xml(path: str, ffmpeg: FFmpeg, log: Log) -> v3:
315
314
  if file_id not in sources:
316
315
  fileobj = valid.parse(clipitem["file"], {"pathurl": str})
317
316
  sources[file_id] = initFileInfo(
318
- uri_to_path(fileobj["pathurl"]), ffmpeg, log
317
+ uri_to_path(fileobj["pathurl"]), log
319
318
  )
320
319
 
321
320
  if "filter" in clipitem:
@@ -363,7 +362,6 @@ def media_def(
363
362
  ET.SubElement(rate, "ntsc").text = ntsc
364
363
  ET.SubElement(vschar, "width").text = f"{tl.res[0]}"
365
364
  ET.SubElement(vschar, "height").text = f"{tl.res[1]}"
366
- ET.SubElement(vschar, "anamorphic").text = "FALSE"
367
365
  ET.SubElement(vschar, "pixelaspectratio").text = "square"
368
366
 
369
367
  for aud in src.audios:
@@ -389,7 +387,7 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
389
387
  src_to_id[src] = the_id
390
388
 
391
389
  xmeml = ET.Element("xmeml", version="5")
392
- sequence = ET.SubElement(xmeml, "sequence")
390
+ sequence = ET.SubElement(xmeml, "sequence", explodedTracks="true")
393
391
  ET.SubElement(sequence, "name").text = name
394
392
  ET.SubElement(sequence, "duration").text = f"{int(tl.out_len())}"
395
393
  rate = ET.SubElement(sequence, "rate")
@@ -400,13 +398,14 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
400
398
  vformat = ET.SubElement(video, "format")
401
399
  vschar = ET.SubElement(vformat, "samplecharacteristics")
402
400
 
403
- rate = ET.SubElement(vschar, "rate")
404
- ET.SubElement(rate, "timebase").text = f"{timebase}"
405
- ET.SubElement(rate, "ntsc").text = ntsc
406
401
  ET.SubElement(vschar, "width").text = f"{width}"
407
402
  ET.SubElement(vschar, "height").text = f"{height}"
408
403
  ET.SubElement(vschar, "pixelaspectratio").text = "square"
409
404
 
405
+ rate = ET.SubElement(vschar, "rate")
406
+ ET.SubElement(rate, "timebase").text = f"{timebase}"
407
+ ET.SubElement(rate, "ntsc").text = ntsc
408
+
410
409
  if len(tl.v) > 0 and len(tl.v[0]) > 0:
411
410
  track = ET.SubElement(video, "track")
412
411
 
@@ -420,6 +419,7 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
420
419
 
421
420
  clipitem = ET.SubElement(track, "clipitem", id=f"clipitem-{j+1}")
422
421
  ET.SubElement(clipitem, "name").text = src.path.stem
422
+ ET.SubElement(clipitem, "enabled").text = "TRUE"
423
423
  ET.SubElement(clipitem, "start").text = _start
424
424
  ET.SubElement(clipitem, "end").text = _end
425
425
  ET.SubElement(clipitem, "in").text = _in
@@ -433,6 +433,7 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
433
433
  media_def(filedef, pathurl, clip.src, tl, timebase, ntsc)
434
434
  file_defs.add(pathurl)
435
435
 
436
+ ET.SubElement(clipitem, "compositemode").text = "normal"
436
437
  if clip.speed != 1:
437
438
  clipitem.append(speedup(clip.speed * 100))
438
439
 
@@ -444,8 +445,6 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
444
445
  ET.SubElement(link, "mediatype").text = "video" if i == 0 else "audio"
445
446
  ET.SubElement(link, "trackindex").text = str(max(i, 1))
446
447
  ET.SubElement(link, "clipindex").text = str(j + 1)
447
- if i > 0:
448
- ET.SubElement(link, "groupindex").text = "1"
449
448
 
450
449
  # Audio definitions and clips
451
450
  audio = ET.SubElement(media, "audio")
@@ -489,6 +488,7 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
489
488
  premiereChannelType="stereo",
490
489
  )
491
490
  ET.SubElement(clipitem, "name").text = src.path.stem
491
+ ET.SubElement(clipitem, "enabled").text = "TRUE"
492
492
  ET.SubElement(clipitem, "start").text = _start
493
493
  ET.SubElement(clipitem, "end").text = _end
494
494
  ET.SubElement(clipitem, "in").text = _in
@@ -502,7 +502,7 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
502
502
 
503
503
  sourcetrack = ET.SubElement(clipitem, "sourcetrack")
504
504
  ET.SubElement(sourcetrack, "mediatype").text = "audio"
505
- ET.SubElement(sourcetrack, "trackindex").text = f"{t + 1}"
505
+ ET.SubElement(sourcetrack, "trackindex").text = f"{t}"
506
506
  labels = ET.SubElement(clipitem, "labels")
507
507
  ET.SubElement(labels, "label2").text = "Iris"
508
508
 
@@ -512,5 +512,5 @@ def fcp7_write_xml(name: str, output: str, tl: v3, log: Log) -> None:
512
512
  audio.append(track)
513
513
 
514
514
  tree = ET.ElementTree(xmeml)
515
- ET.indent(tree, space="\t", level=0)
515
+ ET.indent(tree, space=" ", level=0)
516
516
  tree.write(output, xml_declaration=True, encoding="utf-8")
@@ -6,7 +6,7 @@ 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 FFmpeg, FileInfo, initFileInfo
9
+ from auto_editor.ffwrapper import FileInfo, initFileInfo
10
10
  from auto_editor.lang.json import Lexer, Parser, dump
11
11
  from auto_editor.lib.err import MyError
12
12
  from auto_editor.timeline import (
@@ -42,7 +42,7 @@ def check_file(path: str, log: Log) -> None:
42
42
  log.error(f"Could not locate media file: '{path}'")
43
43
 
44
44
 
45
- def read_v3(tl: Any, ffmpeg: FFmpeg, log: Log) -> v3:
45
+ def read_v3(tl: Any, log: Log) -> v3:
46
46
  check_attrs(
47
47
  tl,
48
48
  log,
@@ -59,7 +59,7 @@ def read_v3(tl: Any, ffmpeg: FFmpeg, log: Log) -> v3:
59
59
  def make_src(v: str) -> FileInfo:
60
60
  if v in srcs:
61
61
  return srcs[v]
62
- temp = initFileInfo(v, ffmpeg, log)
62
+ temp = initFileInfo(v, log)
63
63
  srcs[v] = temp
64
64
  return temp
65
65
 
@@ -158,7 +158,7 @@ def read_v3(tl: Any, ffmpeg: FFmpeg, log: Log) -> v3:
158
158
  return v3(src, tb, sr, res, bg, v, a, v1=None)
159
159
 
160
160
 
161
- def read_v1(tl: Any, ffmpeg: FFmpeg, log: Log) -> v3:
161
+ def read_v1(tl: Any, log: Log) -> v3:
162
162
  from auto_editor.make_layers import clipify
163
163
 
164
164
  check_attrs(tl, log, "source", "chunks")
@@ -168,7 +168,7 @@ def read_v1(tl: Any, ffmpeg: FFmpeg, log: Log) -> v3:
168
168
 
169
169
  check_file(path, log)
170
170
 
171
- src = initFileInfo(path, ffmpeg, log)
171
+ src = initFileInfo(path, log)
172
172
 
173
173
  vtl: VSpace = []
174
174
  atl: ASpace = [[] for _ in range(len(src.audios))]
@@ -194,7 +194,7 @@ def read_v1(tl: Any, ffmpeg: FFmpeg, log: Log) -> v3:
194
194
  )
195
195
 
196
196
 
197
- def read_json(path: str, ffmpeg: FFmpeg, log: Log) -> v3:
197
+ def read_json(path: str, log: Log) -> v3:
198
198
  with open(path, encoding="utf-8", errors="ignore") as f:
199
199
  try:
200
200
  tl = Parser(Lexer(path, f)).expr()
@@ -206,9 +206,9 @@ def read_json(path: str, ffmpeg: FFmpeg, log: Log) -> v3:
206
206
  ver = tl["version"]
207
207
 
208
208
  if ver == "3":
209
- return read_v3(tl, ffmpeg, log)
209
+ return read_v3(tl, log)
210
210
  if ver == "1":
211
- return read_v1(tl, ffmpeg, log)
211
+ return read_v1(tl, log)
212
212
  if type(ver) is not str:
213
213
  log.error("version needs to be a string")
214
214
  log.error(f"Importing version {ver} timelines is not supported.")
@@ -25,16 +25,19 @@ will set the speed from 400 ticks to 800 ticks to 2.5x
25
25
  If timebase is 30, 400 ticks to 800 means 13.33 to 26.66 seconds
26
26
  """.strip(),
27
27
  "--edit-based-on": """
28
- Evalutes a palet expression that returns a bool-array?. The array is then used for
28
+ Evaluates a palet expression that returns a bool-array?. The array is then used for
29
29
  editing.
30
30
 
31
31
  Editing Methods:
32
32
  - audio ; Audio silence/loudness detection
33
33
  - threshold threshold? : 4%
34
- - stream (or/c nat? 'all "all") : 0
34
+ - stream (or/c nat? 'all) : 'all
35
35
  - mincut nat? : 6
36
36
  - minclip nat? : 3
37
37
 
38
+ ; mincut is more significant, there it has a larger default value.
39
+ ; minclip gets applied first, then mincut
40
+
38
41
  - motion ; Motion detection specialized for noisy real-life videos
39
42
  - threshold threshold? : 2%
40
43
  - stream nat? : 0
@@ -150,10 +153,6 @@ The special value `unset` may also be used, and means: Don't pass any value to f
150
153
  """.strip(),
151
154
  "--video-bitrate": """
152
155
  `--video-bitrate` sets the target bitrate for the video encoder. It accepts the same format as `--audio-bitrate` and the special `unset` value is allowed.
153
- """.strip(),
154
- "--silent-threshold": """
155
- Silent threshold is a percentage where 0% represents absolute silence and 100% represents the highest volume in the media file.
156
- Setting the threshold to `0%` will cut only out areas where area is absolutely silence.
157
156
  """.strip(),
158
157
  "--margin": """
159
158
  Default value: 0.2s,0.2s