From cdda2e902411f21c8278c23523168e692c15eba8 Mon Sep 17 00:00:00 2001 From: jenstandstad Date: Mon, 27 Jul 2026 10:48:44 +0200 Subject: [PATCH] Adding fix to recover narration.json --- gnommo/parser.py | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/gnommo/parser.py b/gnommo/parser.py index f817071..4fc5e65 100644 --- a/gnommo/parser.py +++ b/gnommo/parser.py @@ -625,12 +625,35 @@ def parse_narration( default_filters = config.default_filters if config else {} narration = {} + _narr_video_exts = {".mov", ".mp4", ".webm", ".avi", ".mkv", ".m4v"} for segment_id, segment_data in data.items(): - if "source_file" not in segment_data: - raise ParseError( - f"Narration segment '{segment_id}' missing required field 'source_file'", - narration_path, - ) + if not segment_data.get("source_file"): + # source_file can drift out of an entry (case/sync churn between + # machines). Recover the way import/prune/trim do: find the raw + # recording whose stem matches the segment id, case-insensitively. + recovered = None + for sub in ("raw_mov", "processed"): + sub_dir = narration_dir / sub + if not sub_dir.is_dir(): + continue + for f in sorted(sub_dir.iterdir()): + if ( + f.is_file() + and f.suffix.lower() in _narr_video_exts + and f.stem.lower() == segment_id.lower() + ): + recovered = f"{sub}/{f.name}" + break + if recovered: + break + if recovered is None: + raise ParseError( + f"Narration segment '{segment_id}' missing required field 'source_file' " + f"and no matching recording was found in raw_mov/ or processed/. " + f"Add a 'source_file' or run 'import' to repair narration.json.", + narration_path, + ) + segment_data = {**segment_data, "source_file": recovered} # Resolve filter - can be a list or a string reference to default_filters filter_value = segment_data.get("filter", [])