auto-editor 24.19.1__tar.gz → 24.24.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.
- {auto_editor-24.19.1/auto_editor.egg-info → auto_editor-24.24.1}/PKG-INFO +2 -2
- auto_editor-24.24.1/auto_editor/__init__.py +2 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/__main__.py +6 -5
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/analyze.py +2 -11
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/edit.py +2 -3
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/ffwrapper.py +0 -2
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/formats/json.py +6 -3
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/make_layers.py +34 -34
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/render/video.py +0 -3
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/info.py +9 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/subdump.py +7 -7
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/bar.py +2 -2
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/log.py +5 -2
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/types.py +5 -4
- {auto_editor-24.19.1 → auto_editor-24.24.1/auto_editor.egg-info}/PKG-INFO +2 -2
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor.egg-info/requires.txt +1 -1
- {auto_editor-24.19.1 → auto_editor-24.24.1}/pyproject.toml +1 -1
- auto_editor-24.19.1/auto_editor/__init__.py +0 -2
- {auto_editor-24.19.1 → auto_editor-24.24.1}/LICENSE +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/README.md +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/ae-ffmpeg/ae_ffmpeg/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/ae-ffmpeg/ae_ffmpeg/py.typed +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/ae-ffmpeg/setup.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/formats/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/formats/fcp11.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/formats/fcp7.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/formats/shotcut.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/formats/utils.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/help.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lang/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lang/json.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lang/libmath.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lang/palet.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lib/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lib/contracts.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lib/data_structs.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/lib/err.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/output.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/preview.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/render/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/render/audio.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/render/subtitle.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/desc.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/levels.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/palet.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/repl.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/subcommands/test.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/timeline.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/__init__.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/chunks.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/cmdkw.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/container.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/encoder.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/utils/func.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/validate_input.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/vanparse.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor/wavfile.py +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor.egg-info/SOURCES.txt +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor.egg-info/dependency_links.txt +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor.egg-info/entry_points.txt +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/auto_editor.egg-info/top_level.txt +0 -0
- {auto_editor-24.19.1 → auto_editor-24.24.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: auto-editor
|
3
|
-
Version: 24.
|
3
|
+
Version: 24.24.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.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
|
15
|
+
Requires-Dist: pyav==12.1.0
|
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>
|
@@ -4,7 +4,7 @@ import sys
|
|
4
4
|
|
5
5
|
import auto_editor
|
6
6
|
from auto_editor.utils.func import setup_tempdir
|
7
|
-
from auto_editor.utils.log import Log
|
7
|
+
from auto_editor.utils.log import Log, Timer
|
8
8
|
from auto_editor.utils.types import (
|
9
9
|
Args,
|
10
10
|
bitrate,
|
@@ -312,8 +312,7 @@ def main() -> None:
|
|
312
312
|
if args.debug and args.input == []:
|
313
313
|
import platform as plat
|
314
314
|
|
315
|
-
|
316
|
-
print(f"Python Version: {plat.python_version()} {is64bit}")
|
315
|
+
print(f"Python Version: {plat.python_version()}")
|
317
316
|
print(f"Platform: {plat.system()} {plat.release()} {plat.machine().lower()}")
|
318
317
|
print(f"FFmpeg Version: {ffmpeg.version}\nFFmpeg Path: {ffmpeg.path}")
|
319
318
|
print(f"Auto-Editor Version: {auto_editor.version}")
|
@@ -323,13 +322,15 @@ def main() -> None:
|
|
323
322
|
log.error("You need to give auto-editor an input file.")
|
324
323
|
|
325
324
|
temp = setup_tempdir(args.temp_dir, Log())
|
326
|
-
log = Log(args.debug, args.quiet, temp
|
325
|
+
log = Log(args.debug, args.quiet, temp)
|
326
|
+
log.machine = args.progress == "machine"
|
327
327
|
log.debug(f"Temp Directory: {temp}")
|
328
328
|
|
329
329
|
paths = valid_input(args.input, ffmpeg, args, log)
|
330
|
+
timer = Timer(args.quiet or log.machine)
|
330
331
|
|
331
332
|
try:
|
332
|
-
edit_media(paths, ffmpeg, args, temp, log)
|
333
|
+
edit_media(paths, ffmpeg, args, temp, timer, log)
|
333
334
|
except KeyboardInterrupt:
|
334
335
|
log.error("Keyboard Interrupt")
|
335
336
|
log.cleanup()
|
@@ -170,8 +170,6 @@ class Levels:
|
|
170
170
|
# If there's no audio, get length in video metadata.
|
171
171
|
import av
|
172
172
|
|
173
|
-
av.logging.set_level(av.logging.PANIC)
|
174
|
-
|
175
173
|
with av.open(f"{self.src.path}") as cn:
|
176
174
|
if len(cn.streams.video) < 1:
|
177
175
|
self.log.error("Could not get media duration")
|
@@ -227,11 +225,7 @@ class Levels:
|
|
227
225
|
except Exception:
|
228
226
|
json_object = {}
|
229
227
|
|
230
|
-
entry = {
|
231
|
-
"type": str(arr.dtype),
|
232
|
-
"arr": arr.tolist(),
|
233
|
-
}
|
234
|
-
|
228
|
+
entry = {"type": str(arr.dtype), "arr": arr.tolist()}
|
235
229
|
src_key = f"{self.src.path}"
|
236
230
|
|
237
231
|
if src_key in json_object:
|
@@ -344,13 +338,10 @@ class Levels:
|
|
344
338
|
def motion(self, s: int, blur: int, width: int) -> NDArray[np.float64]:
|
345
339
|
import av
|
346
340
|
|
347
|
-
av.logging.set_level(av.logging.PANIC)
|
348
|
-
|
349
|
-
mobj = {"stream": s, "width": width, "blur": blur}
|
350
|
-
|
351
341
|
if s >= len(self.src.videos):
|
352
342
|
raise LevelError(f"motion: video stream '{s}' does not exist.")
|
353
343
|
|
344
|
+
mobj = {"stream": s, "width": width, "blur": blur}
|
354
345
|
if (arr := self.read_cache("motion", mobj)) is not None:
|
355
346
|
return arr
|
356
347
|
|
@@ -150,9 +150,8 @@ def parse_export(export: str, log: Log) -> dict[str, Any]:
|
|
150
150
|
|
151
151
|
|
152
152
|
def edit_media(
|
153
|
-
paths: list[str], ffmpeg: FFmpeg, args: Args, temp: str, log: Log
|
153
|
+
paths: list[str], ffmpeg: FFmpeg, args: Args, temp: str, timer: Timer, log: Log
|
154
154
|
) -> None:
|
155
|
-
timer = Timer(args.quiet)
|
156
155
|
bar = Bar(args.progress)
|
157
156
|
tl = None
|
158
157
|
|
@@ -223,7 +222,7 @@ def edit_media(
|
|
223
222
|
cmd.extend([os.path.join(temp, f"{s}s.{sub.ext}")])
|
224
223
|
ffmpeg.run(cmd)
|
225
224
|
|
226
|
-
tl = make_timeline(sources,
|
225
|
+
tl = make_timeline(sources, ensure, args, samplerate, bar, temp, log)
|
227
226
|
|
228
227
|
if export["export"] == "timeline":
|
229
228
|
from auto_editor.formats.json import make_json_timeline
|
@@ -181,11 +181,11 @@ def read_v1(tl: Any, log: Log) -> v3:
|
|
181
181
|
for i, chunk in enumerate(chunks):
|
182
182
|
if type(chunk) is not list or len(chunk) != 3:
|
183
183
|
log.error(f"Invalid chunk at chunk {i}")
|
184
|
-
if type(chunk[0])
|
184
|
+
if type(chunk[0]) not in (int, float) or chunk[0] < 0:
|
185
185
|
log.error(f"Invalid start at chunk {i}")
|
186
|
-
if type(chunk[1])
|
186
|
+
if type(chunk[1]) not in (int, float) or chunk[1] <= chunk[0]:
|
187
187
|
log.error(f"Invalid end at chunk {i}")
|
188
|
-
if type(chunk[2])
|
188
|
+
if type(chunk[2]) not in (int, float) or chunk[2] < 0.0 or chunk[2] > 99999.0:
|
189
189
|
log.error(f"Invalid speed at chunk {i}")
|
190
190
|
|
191
191
|
if i == 0 and chunk[0] != 0:
|
@@ -194,6 +194,9 @@ def read_v1(tl: Any, log: Log) -> v3:
|
|
194
194
|
log.error(f"Invalid start at chunk {i}")
|
195
195
|
last_end = chunk[1]
|
196
196
|
|
197
|
+
if type(chunk[0]) is float or type(chunk[1]) is float or type(chunk[2]) is int:
|
198
|
+
chunks[i] = (int(chunk[0]), int(chunk[1]), float(chunk[2]))
|
199
|
+
|
197
200
|
for c in clipify(chunks, src):
|
198
201
|
if src.videos:
|
199
202
|
if len(vtl) == 0:
|
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, NamedTuple
|
|
6
6
|
import numpy as np
|
7
7
|
|
8
8
|
from auto_editor.analyze import FileSetup, Levels
|
9
|
-
from auto_editor.ffwrapper import
|
9
|
+
from auto_editor.ffwrapper import FileInfo
|
10
10
|
from auto_editor.lang.palet import Lexer, Parser, env, interpret, is_boolarr
|
11
11
|
from auto_editor.lib.data_structs import print_str
|
12
12
|
from auto_editor.lib.err import MyError
|
@@ -110,9 +110,29 @@ def run_interpreter_for_edit_option(
|
|
110
110
|
return result
|
111
111
|
|
112
112
|
|
113
|
+
def make_sane_timebase(fps: Fraction) -> Fraction:
|
114
|
+
tb = round(fps, 2)
|
115
|
+
ntsc = Fraction(30_000, 1001)
|
116
|
+
film_ntsc = Fraction(24_000, 1001)
|
117
|
+
if tb == round(ntsc, 2):
|
118
|
+
return ntsc
|
119
|
+
if tb == round(film_ntsc, 2):
|
120
|
+
return film_ntsc
|
121
|
+
return tb
|
122
|
+
|
123
|
+
|
124
|
+
def parse_time(val: str, arr: NDArray, tb: Fraction) -> int: # raises: `CoerceError`
|
125
|
+
if val == "start":
|
126
|
+
return 0
|
127
|
+
if val == "end":
|
128
|
+
return len(arr)
|
129
|
+
|
130
|
+
num = time(val, tb)
|
131
|
+
return num if num >= 0 else num + len(arr)
|
132
|
+
|
133
|
+
|
113
134
|
def make_timeline(
|
114
135
|
sources: list[FileInfo],
|
115
|
-
ffmpeg: FFmpeg,
|
116
136
|
ensure: Ensure,
|
117
137
|
args: Args,
|
118
138
|
sr: int,
|
@@ -125,14 +145,9 @@ def make_timeline(
|
|
125
145
|
if inp is None:
|
126
146
|
tb, res = Fraction(30), (1920, 1080)
|
127
147
|
else:
|
128
|
-
tb =
|
129
|
-
|
130
|
-
|
131
|
-
if tb == round(ntsc, 2):
|
132
|
-
tb = ntsc
|
133
|
-
elif tb == round(film_ntsc, 2):
|
134
|
-
tb = film_ntsc
|
135
|
-
|
148
|
+
tb = make_sane_timebase(
|
149
|
+
inp.get_fps() if args.frame_rate is None else args.frame_rate
|
150
|
+
)
|
136
151
|
res = inp.get_res() if args.resolution is None else args.resolution
|
137
152
|
|
138
153
|
try:
|
@@ -171,36 +186,21 @@ def make_timeline(
|
|
171
186
|
speed_hash[len(speed_map) - 1] = speed
|
172
187
|
return len(speed_map) - 1
|
173
188
|
|
174
|
-
def parse_time(val: str, arr: NDArray) -> int:
|
175
|
-
if val == "start":
|
176
|
-
return 0
|
177
|
-
if val == "end":
|
178
|
-
return len(arr)
|
179
|
-
try:
|
180
|
-
num = time(val, tb)
|
181
|
-
return num if num >= 0 else num + len(arr)
|
182
|
-
except CoerceError as e:
|
183
|
-
log.error(e)
|
184
|
-
|
185
|
-
def mut_set_range(arr: NDArray, _ranges: list[list[str]], index: float) -> None:
|
186
|
-
for _range in _ranges:
|
187
|
-
assert len(_range) == 2
|
188
|
-
pair = [parse_time(val, arr) for val in _range]
|
189
|
-
arr[pair[0] : pair[1]] = index
|
190
|
-
|
191
189
|
try:
|
192
|
-
|
190
|
+
for _range in args.cut_out:
|
193
191
|
# always cut out even if 'silent_speed' is not 99,999
|
194
|
-
|
192
|
+
pair = [parse_time(val, speed_index, tb) for val in _range]
|
193
|
+
speed_index[pair[0] : pair[1]] = get_speed_index(99_999)
|
195
194
|
|
196
|
-
|
195
|
+
for _range in args.add_in:
|
197
196
|
# set to 'video_speed' index
|
198
|
-
|
197
|
+
pair = [parse_time(val, speed_index, tb) for val in _range]
|
198
|
+
speed_index[pair[0] : pair[1]] = 1
|
199
199
|
|
200
200
|
for speed_range in args.set_speed_for_range:
|
201
|
-
|
202
|
-
|
203
|
-
|
201
|
+
start_in = parse_time(speed_range[1], speed_index, tb)
|
202
|
+
end_in = parse_time(speed_range[2], speed_index, tb)
|
203
|
+
speed_index[start_in:end_in] = get_speed_index(speed_range[0])
|
204
204
|
except CoerceError as e:
|
205
205
|
log.error(e)
|
206
206
|
|
@@ -7,6 +7,7 @@ from typing import Any, Literal, TypedDict
|
|
7
7
|
|
8
8
|
from auto_editor.ffwrapper import initFileInfo
|
9
9
|
from auto_editor.lang.json import dump
|
10
|
+
from auto_editor.make_layers import make_sane_timebase
|
10
11
|
from auto_editor.timeline import v3
|
11
12
|
from auto_editor.utils.func import aspect_ratio
|
12
13
|
from auto_editor.utils.log import Log
|
@@ -68,6 +69,7 @@ class MediaJson(TypedDict, total=False):
|
|
68
69
|
subtitle: list[SubtitleJson]
|
69
70
|
container: ContainerJson
|
70
71
|
type: Literal["media", "timeline", "unknown"]
|
72
|
+
recommendedTimebase: str
|
71
73
|
version: Literal["v1", "v3"]
|
72
74
|
clips: int
|
73
75
|
|
@@ -108,6 +110,7 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
|
|
108
110
|
|
109
111
|
file_info[file] = {
|
110
112
|
"type": "media",
|
113
|
+
"recommendedTimebase": "30/1",
|
111
114
|
"video": [],
|
112
115
|
"audio": [],
|
113
116
|
"subtitle": [],
|
@@ -117,6 +120,12 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
|
|
117
120
|
},
|
118
121
|
}
|
119
122
|
|
123
|
+
if src.videos:
|
124
|
+
recTb = make_sane_timebase(src.videos[0].fps)
|
125
|
+
file_info[file]["recommendedTimebase"] = (
|
126
|
+
f"{recTb.numerator}/{recTb.denominator}"
|
127
|
+
)
|
128
|
+
|
120
129
|
for track, v in enumerate(src.videos):
|
121
130
|
w, h = v.width, v.height
|
122
131
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import sys
|
2
2
|
|
3
3
|
import av
|
4
|
-
from av.subtitles.subtitle import
|
4
|
+
from av.subtitles.subtitle import AssSubtitle, TextSubtitle
|
5
5
|
|
6
6
|
|
7
7
|
def main(sys_args: list[str] = sys.argv[1:]) -> None:
|
@@ -10,12 +10,12 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
|
|
10
10
|
for s in range(len(container.streams.subtitles)):
|
11
11
|
print(f"file: {input_file} ({s}:{container.streams.subtitles[s].name})")
|
12
12
|
for packet in container.demux(subtitles=s):
|
13
|
-
for
|
14
|
-
|
15
|
-
if
|
16
|
-
print(
|
17
|
-
elif
|
18
|
-
print(
|
13
|
+
for subset in packet.decode():
|
14
|
+
for sub in subset.rects:
|
15
|
+
if isinstance(sub, AssSubtitle):
|
16
|
+
print(sub.ass.decode("utf-8", errors="ignore"))
|
17
|
+
elif isinstance(sub, TextSubtitle):
|
18
|
+
print(sub.text.decode("utf-8", errors="ignore"))
|
19
19
|
print("------")
|
20
20
|
|
21
21
|
|
@@ -67,9 +67,9 @@ class Bar:
|
|
67
67
|
|
68
68
|
if self.machine:
|
69
69
|
index = min(index, self.total)
|
70
|
-
|
70
|
+
secs_til_eta = round(self.begin_time + rate - time(), 2)
|
71
71
|
print(
|
72
|
-
f"{self.title}~{index}~{self.total}~{
|
72
|
+
f"{self.title}~{index}~{self.total}~{secs_til_eta}",
|
73
73
|
end="\r",
|
74
74
|
flush=True,
|
75
75
|
)
|
@@ -24,7 +24,7 @@ class Timer:
|
|
24
24
|
|
25
25
|
|
26
26
|
class Log:
|
27
|
-
__slots__ = ("is_debug", "quiet", "temp")
|
27
|
+
__slots__ = ("is_debug", "quiet", "temp", "machine")
|
28
28
|
|
29
29
|
def __init__(
|
30
30
|
self, show_debug: bool = False, quiet: bool = False, temp: str | None = None
|
@@ -32,6 +32,7 @@ class Log:
|
|
32
32
|
self.is_debug = show_debug
|
33
33
|
self.quiet = quiet
|
34
34
|
self.temp = temp
|
35
|
+
self.machine = False
|
35
36
|
|
36
37
|
def debug(self, message: object) -> None:
|
37
38
|
if self.is_debug:
|
@@ -55,7 +56,9 @@ class Log:
|
|
55
56
|
self.debug(f"Failed to delete temp dir:\n{e}")
|
56
57
|
|
57
58
|
def conwrite(self, message: str) -> None:
|
58
|
-
if
|
59
|
+
if self.machine:
|
60
|
+
print(message, flush=True)
|
61
|
+
elif not self.quiet:
|
59
62
|
buffer = " " * (get_terminal_size().columns - len(message) - 3)
|
60
63
|
sys.stdout.write(f" {message}{buffer}\r")
|
61
64
|
|
@@ -164,8 +164,9 @@ def margin(val: str) -> tuple[str, str]:
|
|
164
164
|
return vals[0], vals[1]
|
165
165
|
|
166
166
|
|
167
|
-
def time_range(val: str) ->
|
168
|
-
|
167
|
+
def time_range(val: str) -> tuple[str, str]:
|
168
|
+
a = _comma_coerce("time_range", val, 2)
|
169
|
+
return a[0], a[1]
|
169
170
|
|
170
171
|
|
171
172
|
def speed_range(val: str) -> tuple[float, str, str]:
|
@@ -231,8 +232,8 @@ class Args:
|
|
231
232
|
extras: str | None = None
|
232
233
|
sn: bool = False
|
233
234
|
no_seek: bool = False
|
234
|
-
cut_out: list[
|
235
|
-
add_in: list[
|
235
|
+
cut_out: list[tuple[str, str]] = field(default_factory=list)
|
236
|
+
add_in: list[tuple[str, str]] = field(default_factory=list)
|
236
237
|
set_speed_for_range: list[tuple[float, str, str]] = field(default_factory=list)
|
237
238
|
frame_rate: Fraction | None = None
|
238
239
|
sample_rate: int | None = None
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: auto-editor
|
3
|
-
Version: 24.
|
3
|
+
Version: 24.24.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.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
|
15
|
+
Requires-Dist: pyav==12.1.0
|
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>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|