Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: show audio/video file lengths #741

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion tagstudio/src/qt/widgets/item_thumb.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (C) 2025 Travis Abendshien (CyanVoxel).
# Licensed under the GPL-3.0 License.
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
import subprocess
import time
import typing
from enum import Enum
Expand All @@ -11,7 +12,7 @@

import structlog
from PIL import Image, ImageQt
from PySide6.QtCore import QEvent, QMimeData, QSize, Qt, QUrl
from PySide6.QtCore import QEvent, QMimeData, QSize, Qt, QThreadPool, QUrl
from PySide6.QtGui import QAction, QDrag, QEnterEvent, QPixmap
from PySide6.QtWidgets import (
QBoxLayout,
Expand All @@ -28,7 +29,9 @@
from src.core.library import ItemType, Library
from src.core.media_types import MediaCategories, MediaType
from src.qt.flowlayout import FlowWidget
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.file_opener import FileOpenerHelper
from src.qt.helpers.vendored.ffmpeg import FFPROBE_CMD
from src.qt.platform_strings import open_file_str, trash_term
from src.qt.translations import Translations
from src.qt.widgets.thumb_button import ThumbButton
Expand Down Expand Up @@ -127,6 +130,7 @@ def __init__(
self.driver = driver
self.item_id: int | None = None
self.thumb_size: tuple[int, int] = thumb_size
self.filename: Path | None = None
self.show_filename_label: bool = show_filename_label
self.label_height = 12
self.label_spacing = 4
Expand Down Expand Up @@ -261,6 +265,7 @@ def __init__(

# Count Badge ----------------------------------------------------------
# Used for Tag Group + Collation counts, video length, word count, etc.
self.count_badge_set: bool = False
self.count_badge = QLabel()
self.count_badge.setObjectName("countBadge")
self.count_badge.setText("-:--")
Expand Down Expand Up @@ -405,6 +410,7 @@ def set_count(self, count: str) -> None:
self.count_badge.setHidden(True)

def set_filename_text(self, filename: Path | None):
self.filename = filename
self.set_item_path(filename)
self.file_label.setText(str(filename.name))

Expand All @@ -423,6 +429,35 @@ def set_filename_visibility(self, set_visible: bool):
self.setFixedHeight(self.thumb_size[1])
self.show_filename_label = set_visible

def update_count_badge(self, filename) -> None:
"""Updates the count badge."""
if self.count_badge_set or self.filename is None:
return

def set_video_audio():
"""Gets length of audio or video and sets count badge."""
args = [
FFPROBE_CMD,
"-v",
"error",
"-show_entries",
"format=duration",
"-of",
"default=noprint_wrappers=1:nokey=1",
filename,
]
probe = subprocess.run(args, capture_output=True)
probe_result: str = probe.stdout.strip().decode("utf-8")
if probe_result != "N/A" and probe_result != "":
duration: float = float(probe_result)
minutes: int = int(duration // 60)
seconds: int = int(duration - (minutes * 60))
self.count_badge.setText(f"{minutes:02}:{seconds:02}")
self.count_badge_set = True

runnable = CustomRunnable(set_video_audio)
QThreadPool.globalInstance().start(runnable)

def update_thumb(self, timestamp: float, image: QPixmap | None = None):
"""Update attributes of a thumbnail element."""
if timestamp > ItemThumb.update_cutoff:
Expand Down Expand Up @@ -476,6 +511,7 @@ def show_check_badges(self, show: bool):
badge.setHidden(is_hidden)

def enterEvent(self, event: QEnterEvent) -> None: # noqa: N802
self.update_count_badge(self.filename)
self.show_check_badges(show=True)
return super().enterEvent(event)

Expand Down