Skip to content

Commit 2612980

Browse files
committed
Assert monotonic timelines
1 parent b5ebe80 commit 2612980

File tree

1 file changed

+40
-7
lines changed

1 file changed

+40
-7
lines changed

auto_editor/make_layers.py

+40-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from fractions import Fraction
4+
from math import ceil
45
from typing import TYPE_CHECKING, NamedTuple
56

67
import numpy as np
@@ -231,21 +232,35 @@ def echunk(
231232
chunks.append((src, start, arr_length, speed_map[arr[j]]))
232233
return chunks
233234

235+
# Assert timeline is monotonic because non-monotonic timelines are incorrect
236+
# here and causes back-seeking (performance issue) in video rendering.
237+
238+
# We don't properly check monotonicity for multiple sources, so skip those.
239+
240+
check_monotonic = len(sources) == 1
241+
last_i = 0
242+
234243
clips: list[Clip] = []
235-
i = 0
236244
start = 0
245+
237246
for chunk in echunk(speed_index, src_index):
238247
if chunk[3] != 99999:
239-
dur = round((chunk[2] - chunk[1]) / chunk[3])
248+
dur = int((chunk[2] - chunk[1]) / chunk[3])
240249
if dur == 0:
241250
continue
242251

243-
offset = int(chunk[1] / chunk[3])
252+
offset = ceil(chunk[1] / chunk[3])
253+
254+
if check_monotonic:
255+
max_end = start + dur - 1
256+
this_i = round((offset + max_end - start) * chunk[3])
257+
if this_i < last_i:
258+
raise ValueError("not monotonic", sources, this_i, last_i)
259+
last_i = this_i
260+
261+
clips.append(Clip(start, dur, offset, chunk[3], chunk[0]))
244262

245-
if not (clips and clips[-1].start == round(start)):
246-
clips.append(Clip(start, dur, offset, chunk[3], chunk[0]))
247263
start += dur
248-
i += 1
249264

250265
vtl: VSpace = []
251266
atl: ASpace = []
@@ -281,4 +296,22 @@ def chunkify(arr: NDArray, smap: dict[int, float]) -> Chunks:
281296
else:
282297
v1_compatiable = None
283298

284-
return v3(inp, tb, sr, res, args.background, vtl, atl, v1_compatiable)
299+
tl = v3(inp, tb, sr, res, args.background, vtl, atl, v1_compatiable)
300+
301+
# Additional monotonic check, o(n^2) time complexity so disable by default.
302+
303+
# if len(sources) != 1:
304+
# return tl
305+
306+
# last_i = 0
307+
# for index in range(tl.end):
308+
# for layer in tl.v:
309+
# for lobj in layer:
310+
# if index >= lobj.start and index < (lobj.start + lobj.dur):
311+
# _i = round((lobj.offset + index - lobj.start) * lobj.speed)
312+
# if (_i < last_i):
313+
# print(_i, last_i)
314+
# raise ValueError("not monotonic")
315+
# last_i = _i
316+
317+
return tl

0 commit comments

Comments
 (0)