From 25117062e8bdaa6ea82393069f01b18d4f251f51 Mon Sep 17 00:00:00 2001 From: Honney OC Date: Sun, 13 Sep 2026 23:20:16 +0000 Subject: [PATCH] feat: handle video decode errors with transcode fallback --- verify_sync.py | 52 ++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/verify_sync.py b/verify_sync.py index f6c3f0e..e76344a 100644 --- a/verify_sync.py +++ b/verify_sync.py @@ -406,6 +406,9 @@ class VerifyWindow(QtWidgets.QMainWindow): # Wait for media loaded to get actual duration self.media_player.durationChanged.connect(self._on_duration_changed) + # Handle video decode errors — transcode and retry + self.media_player.errorOccurred.connect(self._on_media_error) + def _on_duration_changed(self, dur_ms): """QMediaPlayer reports actual video duration in ms.""" vid_dur = dur_ms / 1000.0 @@ -424,6 +427,30 @@ class VerifyWindow(QtWidgets.QMainWindow): self.btn_play.setText("Play") self.audio_player.stop() + def _on_media_error(self, error, message): + """Handle video decode failure — transcode to H.264 and retry.""" + if getattr(self, "_transcode_attempted", False): + print(f"Video error even after transcode: {message}", file=sys.stderr) + return + print(f"Video decode error ({error.name}): {message}", file=sys.stderr) + print("Attempting fallback: transcoding to H.264 SDR...", file=sys.stderr) + self._transcode_attempted = True + + if self.temp_dir is None: + self.temp_dir = tempfile.mkdtemp(prefix="verify_sync_") + preview_path = os.path.join(self.temp_dir, "preview.mp4") + transcode_dur = 30.0 if self.mode == "short" else 0 + + if not transcode_to_h264_sdr(self.video_path, preview_path, transcode_dur): + print("Transcode also failed — video will remain black", file=sys.stderr) + return + + # Reload with the transcoded file + self.video_path = preview_path + from PyQt6.QtCore import QUrl + self.media_player.setSource(QUrl.fromLocalFile(os.path.abspath(preview_path))) + print(f"Retrying with transcoded preview: {preview_path}") + def _draw_waveforms(self): max_pts = 200_000 if self.mode == "full" else 80_000 @@ -670,31 +697,6 @@ def main(): app = QtWidgets.QApplication(sys.argv) apply_dark_theme(app) - # Check if QMediaPlayer supports the video codec; only transcode if needed - probe = QtMultimedia.QMediaPlayer() - probe.setSource(QtCore.QUrl.fromLocalFile(os.path.abspath(video_path))) - support = probe.support() - del probe - - if support != QtMultimedia.QMediaPlayer.Support.Supported: - if not temp_dir: - temp_dir = tempfile.mkdtemp(prefix="verify_sync_") - preview_path = os.path.join(temp_dir, "preview.mp4") - if not os.path.exists(preview_path): - transcode_dur = 30.0 if args.mode == "short" else 0 - print(f"Codec not supported by QMediaPlayer (support={support.name}), " - f"transcoding to H.264 SDR ({'%.1fs' % transcode_dur if transcode_dur else 'full'})...") - if not transcode_to_h264_sdr(video_path, preview_path, transcode_dur): - print(f"WARNING: transcode failed, using original video (may show black)", file=sys.stderr) - else: - video_path = preview_path - print(f"Preview ready: {preview_path}") - else: - video_path = preview_path - print(f"Using cached preview: {preview_path}") - else: - print(f"Codec supported by QMediaPlayer, using directly") - w = VerifyWindow(video_path, wav_a, wav_b, sr=sr, lag_sec=lag_sec, mode=args.mode, out_dir=out_dir, temp_dir=temp_dir, volume=volume)