Generate thumbnails on CPU and with high niceness

This commit is contained in:
Jan Hamal Dvořák 2025-03-11 12:14:31 +01:00
parent fd4e46791c
commit 6016db128c

View file

@ -1,9 +1,11 @@
from __future__ import annotations
import multiprocessing
import os
import sys
from concurrent.futures import ThreadPoolExecutor
from typing import TYPE_CHECKING
from queue import LifoQueue
from typing import TYPE_CHECKING, Any, cast
from gi.repository import GLib, Gst
@ -32,8 +34,10 @@ class Thumbnailer(ThreadPoolExecutor):
max_workers=MAX_WORKERS,
)
self._work_queue = cast(Any, LifoQueue())
def generate_thumbnail(self, file_item: FileItem):
"""Schedule thumbnail generation"""
"""Schedule thumbnail generation."""
if not file_item.full_path.is_file():
return
@ -41,39 +45,41 @@ class Thumbnailer(ThreadPoolExecutor):
if file_item.attempted_thumbnail:
return
if self._work_queue.qsize() >= MAX_WORKERS:
# print("[thumbnail] Ignoring:", file_item.full_path.name)
return
self.submit(generate_thumbnail_sync, file_item)
self.submit(generate_thumbnail_sync_nicely, file_item)
file_item.attempted_thumbnail = True
def generate_thumbnail_sync_nicely(file_item: FileItem):
os.nice(19)
return generate_thumbnail_sync(file_item)
def generate_thumbnail_sync(file_item: FileItem):
"""Generate thumbnail for a single file"""
# print("[thumbnailer] Generate:", file_item.full_path.name)
pipeline_str = (
"uridecodebin name=uridecodebin ! "
"uridecodebin name=uridecodebin force-sw-decoders=true ! "
"videoconvert ! "
"jpegenc quality=85 ! "
"appsink sync=false name=sink"
)
pipeline = Gst.parse_launch(pipeline_str)
assert isinstance(pipeline, Gst.Pipeline)
sink = pipeline.get_by_name("sink")
assert isinstance(sink, Gst.Element)
uridecodebin = pipeline.get_by_name("uridecodebin")
assert isinstance(uridecodebin, Gst.Element)
# Set file URI
uridecodebin.set_property("uri", Gst.filename_to_uri(str(file_item.full_path)))
pipeline: Gst.Pipeline | None = None
try:
pipeline = cast(Gst.Pipeline, Gst.parse_launch(pipeline_str))
sink = pipeline.get_by_name("sink")
assert isinstance(sink, Gst.Element)
uridecodebin = pipeline.get_by_name("uridecodebin")
assert isinstance(uridecodebin, Gst.Element)
# Set file URI
uridecodebin.set_property("uri", Gst.filename_to_uri(str(file_item.full_path)))
# Set pipeline to PAUSED to get duration
pipeline.set_state(Gst.State.PAUSED)
pipeline.get_state(Gst.CLOCK_TIME_NONE)
@ -119,4 +125,5 @@ def generate_thumbnail_sync(file_item: FileItem):
print("[thumbnailer]", err, file=sys.stderr)
finally:
pipeline.set_state(Gst.State.NULL)
if pipeline:
pipeline.set_state(Gst.State.NULL)