Skip to content

Commit b2dbc57

Browse files
authored
feat(ui): warn user if FFmpeg not installed (#441)
* feat: Warn user if FFmpeg is not installed Creates a Warning dialog on startup if the program cannot find FFmpeg or FFprobe in the PATH. Other interactions with the program are blocked until the issue is either ignore or resolved. * docs: Add FFmpeg installation guide * ruff formatting * chore: Cleanup missing logic and warning message * chore: Remove custom icon Per QT docs, handling custom iconPixmap requires multiple icons per platform. Easier to just use universal, default warning icon (yellow triangle) * fix: Ignore dialog with X button * fix: Move startup checks after CI * chore: Unreverse install check logic * doc: Improve docs formatting * docs: Point help url to new docs sites * Remove ffmpeg docs page * Use which from python stdlib
1 parent 6490cc9 commit b2dbc57

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

.github/workflows/apprun.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ jobs:
3333
libxcb-xinerama0 \
3434
libopengl0 \
3535
libxcb-cursor0 \
36-
libpulse0
36+
libpulse0 \
37+
ffmpeg
3738
3839
- name: Install dependencies
3940
run: |
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import logging
2+
import math
3+
from pathlib import Path
4+
from shutil import which
5+
import subprocess
6+
7+
from PIL import Image, ImageQt
8+
from PySide6.QtCore import Signal, Qt, QUrl
9+
from PySide6.QtGui import QPixmap, QDesktopServices
10+
from PySide6.QtWidgets import QMessageBox
11+
12+
13+
class FfmpegChecker(QMessageBox):
14+
"""A warning dialog for if FFmpeg is missing."""
15+
16+
HELP_URL = "https://docs.tagstud.io/help/ffmpeg/"
17+
18+
def __init__(self):
19+
super().__init__()
20+
21+
self.setWindowTitle("Warning: Missing dependency")
22+
self.setText("Warning: Could not find FFmpeg installation")
23+
self.setIcon(QMessageBox.Warning)
24+
# Blocks other application interactions until resolved
25+
self.setWindowModality(Qt.ApplicationModal)
26+
27+
self.setStandardButtons(
28+
QMessageBox.Help | QMessageBox.Ignore | QMessageBox.Cancel
29+
)
30+
self.setDefaultButton(QMessageBox.Ignore)
31+
# Enables the cancel button but hides it to allow for click X to close dialog
32+
self.button(QMessageBox.Cancel).hide()
33+
34+
self.ffmpeg = False
35+
self.ffprobe = False
36+
37+
def installed(self):
38+
"""Checks if both FFmpeg and FFprobe are installed and in the PATH."""
39+
if which("ffmpeg"):
40+
self.ffmpeg = True
41+
if which("ffprobe"):
42+
self.ffprobe = True
43+
44+
logging.info(
45+
f"[FFmpegChecker] FFmpeg found: {self.ffmpeg}, FFprobe found: {self.ffprobe}"
46+
)
47+
return self.ffmpeg and self.ffprobe
48+
49+
def show_warning(self):
50+
"""Displays the warning to the user and awaits respone."""
51+
missing = "FFmpeg"
52+
# If ffmpeg is installed but not ffprobe
53+
if not self.ffprobe and self.ffmpeg:
54+
missing = "FFprobe"
55+
56+
self.setText(f"Warning: Could not find {missing} installation")
57+
self.setInformativeText(
58+
f"{missing} is required for multimedia thumbnails and playback"
59+
)
60+
# Shows the dialog
61+
selection = self.exec()
62+
63+
# Selection will either be QMessageBox.Help or (QMessageBox.Ignore | QMessageBox.Cancel) which can be ignored
64+
if selection == QMessageBox.Help:
65+
QDesktopServices.openUrl(QUrl(self.HELP_URL))

tagstudio/src/qt/ts_qt.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
from src.qt.modals.fix_dupes import FixDupeFilesModal
9393
from src.qt.modals.folders_to_tags import FoldersToTagsModal
9494
from src.qt.modals.drop_import import DropImport
95+
from src.qt.modals.ffmpeg_checker import FfmpegChecker
9596

9697
# this import has side-effect of import PySide resources
9798
import src.qt.resources_rc # pylint: disable=unused-import
@@ -639,6 +640,9 @@ def create_folders_tags_modal():
639640
if self.args.ci:
640641
# gracefully terminate the app in CI environment
641642
self.thumb_job_queue.put((self.SIGTERM.emit, []))
643+
else:
644+
# Startup Checks
645+
self.check_ffmpeg()
642646

643647
app.exec()
644648

@@ -1852,6 +1856,12 @@ def open_library(self, path: Path):
18521856
self.filter_items()
18531857
self.main_window.toggle_landing_page(False)
18541858

1859+
def check_ffmpeg(self) -> None:
1860+
"""Checks if FFmpeg is installed and displays a warning if not."""
1861+
self.ffmpeg_checker = FfmpegChecker()
1862+
if not self.ffmpeg_checker.installed():
1863+
self.ffmpeg_checker.show_warning()
1864+
18551865
def create_collage(self) -> None:
18561866
"""Generates and saves an image collage based on Library Entries."""
18571867

0 commit comments

Comments
 (0)