From 9e818dab3500d3b2d026464af40773a31eec45ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= <mordae@anilinux.org>
Date: Thu, 13 Mar 2025 23:42:07 +0100
Subject: [PATCH] Be smarter about thumbnails

---
 lazy_player/thumbnailer.py | 44 ++++++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/lazy_player/thumbnailer.py b/lazy_player/thumbnailer.py
index ca0f52c..6613aaf 100644
--- a/lazy_player/thumbnailer.py
+++ b/lazy_player/thumbnailer.py
@@ -89,30 +89,36 @@ def generate_thumbnail_sync(file_item: FileItem):
         if not success:
             raise RuntimeError("Failed to query duration")
 
-        # Seek to 1/3 of duration
-        seek_pos = duration // 3
-        pipeline.seek_simple(Gst.Format.TIME, DEFAULT_SEEK_FLAGS, seek_pos)
+        def get_sample(seek_pos: int) -> bytes:
+            pipeline.seek_simple(Gst.Format.TIME, DEFAULT_SEEK_FLAGS, seek_pos)
 
-        # Start playing to capture frame
-        pipeline.set_state(Gst.State.PLAYING)
+            # Start playing to capture frame
+            pipeline.set_state(Gst.State.PLAYING)
 
-        sample = sink.emit("pull-sample")
-        if not sample:
-            raise RuntimeError("Failed to pull sample")
+            sample = sink.emit("pull-sample")
+            if not sample:
+                raise RuntimeError("Failed to pull sample")
 
-        # Extract image data
-        buffer = sample.get_buffer()
-        if not buffer:
-            raise RuntimeError("Failed to get buffer")
+            # Extract image data
+            buffer = sample.get_buffer()
+            if not buffer:
+                raise RuntimeError("Failed to get buffer")
 
-        success, map_info = buffer.map(Gst.MapFlags.READ)
-        if not success:
-            raise RuntimeError("Failed to map buffer")
+            success, map_info = buffer.map(Gst.MapFlags.READ)
+            if not success:
+                raise RuntimeError("Failed to map buffer")
 
-        try:
-            thumbnail = bytes(map_info.data)
-        finally:
-            buffer.unmap(map_info)
+            try:
+                return bytes(map_info.data)
+            finally:
+                buffer.unmap(map_info)
+
+        candidates: list[bytes] = []
+
+        for i in range(3):
+            candidates.append(get_sample(duration // 3 - Gst.SECOND + i * Gst.SECOND))
+
+        thumbnail = max(candidates, key=len)
 
         def set_thumbnail():
             file_item.thumbnail.value = thumbnail