Fix video thumbnail capture for new files
Add audio output (muted) so QMediaPlayer decodes frames. Add capture guard and timeout cleanup.
This commit is contained in:
parent
660abe42e7
commit
85ec13bf7c
@ -242,14 +242,22 @@ class LibraryView(QWidget):
|
|||||||
|
|
||||||
def _capture_video_thumb(self, index: int, source: str, dest: str) -> None:
|
def _capture_video_thumb(self, index: int, source: str, dest: str) -> None:
|
||||||
"""Grab first frame from video using Qt's QMediaPlayer + QVideoSink."""
|
"""Grab first frame from video using Qt's QMediaPlayer + QVideoSink."""
|
||||||
|
from PySide6.QtMultimedia import QAudioOutput
|
||||||
player = QMediaPlayer()
|
player = QMediaPlayer()
|
||||||
|
audio = QAudioOutput()
|
||||||
|
audio.setVolume(0)
|
||||||
|
player.setAudioOutput(audio)
|
||||||
sink = QVideoSink()
|
sink = QVideoSink()
|
||||||
player.setVideoSink(sink)
|
player.setVideoSink(sink)
|
||||||
|
captured = [False]
|
||||||
|
|
||||||
def _on_frame(frame: QVideoFrame):
|
def _on_frame(frame: QVideoFrame):
|
||||||
|
if captured[0]:
|
||||||
|
return
|
||||||
if frame.isValid():
|
if frame.isValid():
|
||||||
img = frame.toImage()
|
img = frame.toImage()
|
||||||
if not img.isNull():
|
if not img.isNull():
|
||||||
|
captured[0] = True
|
||||||
scaled = img.scaled(
|
scaled = img.scaled(
|
||||||
LIBRARY_THUMB_SIZE, LIBRARY_THUMB_SIZE,
|
LIBRARY_THUMB_SIZE, LIBRARY_THUMB_SIZE,
|
||||||
Qt.AspectRatioMode.KeepAspectRatio,
|
Qt.AspectRatioMode.KeepAspectRatio,
|
||||||
@ -257,15 +265,19 @@ class LibraryView(QWidget):
|
|||||||
)
|
)
|
||||||
scaled.save(dest, "JPEG", 85)
|
scaled.save(dest, "JPEG", 85)
|
||||||
self._signals.thumb_ready.emit(index, dest)
|
self._signals.thumb_ready.emit(index, dest)
|
||||||
sink.videoFrameChanged.disconnect(_on_frame)
|
player.stop()
|
||||||
|
player.deleteLater()
|
||||||
|
|
||||||
|
def _cleanup():
|
||||||
|
if not captured[0]:
|
||||||
player.stop()
|
player.stop()
|
||||||
player.deleteLater()
|
player.deleteLater()
|
||||||
|
|
||||||
sink.videoFrameChanged.connect(_on_frame)
|
sink.videoFrameChanged.connect(_on_frame)
|
||||||
player.setSource(QUrl.fromLocalFile(source))
|
player.setSource(QUrl.fromLocalFile(source))
|
||||||
player.play()
|
player.play()
|
||||||
# Pause immediately — we just need one frame
|
# Timeout cleanup if no frame arrives
|
||||||
QTimer.singleShot(100, player.pause)
|
QTimer.singleShot(5000, _cleanup)
|
||||||
|
|
||||||
def _on_thumb_ready(self, index: int, path: str) -> None:
|
def _on_thumb_ready(self, index: int, path: str) -> None:
|
||||||
thumbs = self._grid._thumbs
|
thumbs = self._grid._thumbs
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user