Enhance Avisynth video workflow and metadata tools

This commit is contained in:
ajp_anton
2026-07-30 03:20:19 +00:00
parent d60ce51b14
commit 100cad1cb5
26 changed files with 2350 additions and 1161 deletions
+42
View File
@@ -28,6 +28,10 @@ class OutputTimeline:
dropped_frame_count: int
source_frame_count: int
matrix: int | None
absolute_timestretch: float = 1.0
primaries: int | None = None
transfer: int | None = None
color_range: int | None = None
def build_output_timeline(
@@ -40,6 +44,10 @@ def build_output_timeline(
audio_segments: list[tuple[float, float]] = []
consumed_source_frames: list[int] = []
matrices: set[int] = set()
primaries_values: set[int] = set()
transfers: set[int] = set()
ranges: set[int] = set()
timestretches: set[float] = set()
dropped_count = 0
leading_trimmed = False
last_consumed_source_frame: int | None = None
@@ -79,6 +87,14 @@ def build_output_timeline(
consumed_source_frames.append(frame.source_frame)
if frame.matrix is not None:
matrices.add(frame.matrix)
if frame.primaries is not None:
primaries_values.add(frame.primaries)
if frame.transfer is not None:
transfers.add(frame.transfer)
if frame.color_range is not None:
ranges.add(frame.color_range)
if frame.absolute_timestretch is not None:
timestretches.add(frame.absolute_timestretch)
_append_audio_segment(
audio_segments,
start=probe.frame_timestamps[frame.source_frame],
@@ -102,6 +118,20 @@ def build_output_timeline(
f"Output frames have mixed _Matrix values for {probe.path}: "
+ ", ".join(str(value) for value in sorted(matrices))
)
_require_one_color_value("_Primaries", primaries_values, probe)
_require_one_color_value("_Transfer", transfers, probe)
_require_one_color_value("_ColorRange", ranges, probe)
if len(timestretches) > 1:
raise RuntimeError(
f"Output frames have mixed absolute timestretch values for {probe.path}: "
+ ", ".join(str(value) for value in sorted(timestretches))
)
absolute_timestretch = next(iter(timestretches), 1.0)
if absolute_timestretch <= 0:
raise RuntimeError(
f"Output frames have an invalid absolute timestretch for {probe.path}: "
f"{absolute_timestretch}"
)
source_count = len(probe.frame_timestamps)
beginning_trimmed = leading_trimmed or kept_frames[0].source_frame > 0
@@ -120,9 +150,21 @@ def build_output_timeline(
dropped_frame_count=dropped_count,
source_frame_count=source_count,
matrix=next(iter(matrices)) if matrices else None,
absolute_timestretch=absolute_timestretch,
primaries=next(iter(primaries_values)) if primaries_values else None,
transfer=next(iter(transfers)) if transfers else None,
color_range=next(iter(ranges)) if ranges else None,
)
def _require_one_color_value(name: str, values: set[int], probe: VideoProbe) -> None:
if len(values) > 1:
raise RuntimeError(
f"Output frames have mixed {name} values for {probe.path}: "
+ ", ".join(str(value) for value in sorted(values))
)
def _append_audio_segment(
segments: list[tuple[float, float]],
*,