From 39a9600fe83eadab9e4dfd18bdfd5d3e9c32caed Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 17:26:56 -0500 Subject: [PATCH 01/12] 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. --- .../resources/qt/images/thumb_warning.png | Bin 0 -> 13010 bytes tagstudio/src/qt/modals/ffmpeg_checker.py | 58 ++++++++++++++++++ tagstudio/src/qt/ts_qt.py | 8 +++ 3 files changed, 66 insertions(+) create mode 100644 tagstudio/resources/qt/images/thumb_warning.png create mode 100644 tagstudio/src/qt/modals/ffmpeg_checker.py diff --git a/tagstudio/resources/qt/images/thumb_warning.png b/tagstudio/resources/qt/images/thumb_warning.png new file mode 100644 index 0000000000000000000000000000000000000000..b5ce2d3444b7591200914d2c4902764f91bc66c9 GIT binary patch literal 13010 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 MsijGkk;}vX0k#q&f&c&j literal 0 HcmV?d00001 diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py new file mode 100644 index 000000000..daf388357 --- /dev/null +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -0,0 +1,58 @@ +import logging +import math +from pathlib import Path +import subprocess + +from PIL import Image, ImageQt +from pydub.utils import which +from PySide6.QtCore import Signal, Qt, QUrl +from PySide6.QtGui import QPixmap, QDesktopServices +from PySide6.QtWidgets import QMessageBox + +class FfmpegChecker(QMessageBox): + warning_icon_128: Image.Image = Image.open( + str(Path(__file__).parents[3] / "resources/qt/images/thumb_warning.png") + ).resize((math.floor(24 * 1.25), math.floor(24 * 1.25))) + warning_icon_128.load() + + help_url = "https://github.com/TagStudioDev/TagStudio/blob/main/doc/index.md" + + def __init__(self): + super().__init__() + + #self.warning_icon = QPixmap.fromImage(ImageQt.ImageQt(self.warning_icon_128)) + #self.setIconPixmap(self.warning_icon) + self.setIcon(QMessageBox.Warning) + + self.setText("Warning: Could not find FFmpeg installation") + self.setStandardButtons(QMessageBox.Help | QMessageBox.Ignore) + self.setDefaultButton(QMessageBox.Ignore) + + self.setWindowModality(Qt.ApplicationModal) + self.setWindowTitle("Warning: Missing dependency") + + self.ffmpeg_installed = False + self.ffprobe_installed = False + + def installed(self): + """Checks if both FFmpeg and FFprobe are installed""" + if which("ffmpeg"): + self.ffmpeg_installed = True + logging.info(f"FFmpeg found!") + if which("ffprobe"): + self.ffprobe_installed = True + logging.info(f"FFprobe found!") + return self.ffmpeg_installed and self.ffprobe_installed + + def show_warning(self): + if not self.ffmpeg_installed: + self.setText("Warning: Could not find FFmpeg installation") + self.setInformativeText("FFmpeg is required for video/audio thumbnails and playback") + elif not self.ffprobe_installed: + # If ffmpeg is installed but not ffprobe + self.setText("Warning: Could not find FFprobe installation") + self.setInformativeText("FFprobe is required for video/audio thumbnails and playback") + + selection = self.exec() + if selection == QMessageBox.Help: + QDesktopServices.openUrl(QUrl(self.help_url)) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 0dee6580a..d1a2e5e08 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -92,6 +92,7 @@ from src.qt.modals.fix_dupes import FixDupeFilesModal from src.qt.modals.folders_to_tags import FoldersToTagsModal from src.qt.modals.drop_import import DropImport +from src.qt.modals.ffmpeg_checker import FfmpegChecker # this import has side-effect of import PySide resources import src.qt.resources_rc # pylint: disable=unused-import @@ -636,6 +637,8 @@ def create_folders_tags_modal(): ) self.open_library(Path(lib)) + self.check_ffmpeg() + if self.args.ci: # gracefully terminate the app in CI environment self.thumb_job_queue.put((self.SIGTERM.emit, [])) @@ -1846,6 +1849,11 @@ def open_library(self, path: Path): self.filter_items() self.main_window.toggle_landing_page(False) + def check_ffmpeg(self) -> None: + self.ffmpeg_checker = FfmpegChecker() + if not self.ffmpeg_checker.installed(): + self.ffmpeg_checker.show_warning() + def create_collage(self) -> None: """Generates and saves an image collage based on Library Entries.""" From 0f54dcbca0ee4e32077466241cea7c2abee599c4 Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 19:50:08 -0500 Subject: [PATCH 02/12] docs: Add FFmpeg installation guide --- doc/utilities/ffmpeg.md | 42 +++++++++++++++++++++++ tagstudio/src/qt/modals/ffmpeg_checker.py | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 doc/utilities/ffmpeg.md diff --git a/doc/utilities/ffmpeg.md b/doc/utilities/ffmpeg.md new file mode 100644 index 000000000..f9599cd6a --- /dev/null +++ b/doc/utilities/ffmpeg.md @@ -0,0 +1,42 @@ +FFmpeg is required for thumbnail previews and playback features on audio and video files. FFmpeg is a free Open Source project dedicated to the handling of multimedia (video, audio, etc) files. + +# Installation on Windows +--- +## Prebuilt Binaries +Pre-built binaries from trusted sources are available on the [FFmpeg website](https://www.ffmpeg.org/download.html#build-windows). + +To install: +1. Download 7z or zip file and extract it (right click > Extract All) +2. Move extracted contents to a unique folder (i.e; `c:\ffmpeg` or `c:\Program Files\ffmpeg`) +3. Add FFmpeg to your PATH + a. Go to "Edit the system environment variables" + b. Under "User Variables", select "Path" then edit + c. Click new and add `\bin` (e.g; `c:\ffmpeg\bin` or `c:\Program Files\ffmpeg\bin`) + d. Click okay + +## Package Managers +FFmpeg is also available from: + +1. WinGet (`winget install ffmpeg) +2. Scoop (`scoop install main/ffmpeg`) +3. Chocolatey (`choco install ffmpeg-full`) + +# Installation on Mac +--- +## Homebrew +FFmpeg is available via Homebrew and can be installed via; + +`brew install ffmpeg` + +# Installation on Linux +--- +## Package Managers +FFmpeg may be installed by default on some Linux distrobutions, but if not, it is available via your distro's package manager of choice + +1. Debian/Ubuntu (`sudo apt install ffmpeg`) +2. Fedora (`sudo dnf install ffmpeg-free`) +3. Arch (`sudo pacman -S ffmpeg`) + +# Help +--- +For additional help, please create an Issue on the [GitHub repository](https://github.com/TagStudioDev/TagStudio) or join the [Discord]() diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index daf388357..3fb440151 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -15,7 +15,7 @@ class FfmpegChecker(QMessageBox): ).resize((math.floor(24 * 1.25), math.floor(24 * 1.25))) warning_icon_128.load() - help_url = "https://github.com/TagStudioDev/TagStudio/blob/main/doc/index.md" + help_url = "https://github.com/TagStudioDev/TagStudio/blob/Alpha-v9.4/doc/utilities/ffmpeg.md" def __init__(self): super().__init__() From afaae568a6343404630324ddb9c1bc53f4404151 Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 20:03:48 -0500 Subject: [PATCH 03/12] ruff formatting --- tagstudio/src/qt/modals/ffmpeg_checker.py | 22 +++++++++++++++++----- tagstudio/src/qt/ts_qt.py | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index 3fb440151..327bc9f1b 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -9,7 +9,10 @@ from PySide6.QtGui import QPixmap, QDesktopServices from PySide6.QtWidgets import QMessageBox + class FfmpegChecker(QMessageBox): + """A warning dialog for if FFmpeg is missing.""" + warning_icon_128: Image.Image = Image.open( str(Path(__file__).parents[3] / "resources/qt/images/thumb_warning.png") ).resize((math.floor(24 * 1.25), math.floor(24 * 1.25))) @@ -20,14 +23,15 @@ class FfmpegChecker(QMessageBox): def __init__(self): super().__init__() - #self.warning_icon = QPixmap.fromImage(ImageQt.ImageQt(self.warning_icon_128)) - #self.setIconPixmap(self.warning_icon) + # self.warning_icon = QPixmap.fromImage(ImageQt.ImageQt(self.warning_icon_128)) + # self.setIconPixmap(self.warning_icon) self.setIcon(QMessageBox.Warning) self.setText("Warning: Could not find FFmpeg installation") self.setStandardButtons(QMessageBox.Help | QMessageBox.Ignore) self.setDefaultButton(QMessageBox.Ignore) + # Blocks other application interactions until resolved self.setWindowModality(Qt.ApplicationModal) self.setWindowTitle("Warning: Missing dependency") @@ -35,7 +39,8 @@ def __init__(self): self.ffprobe_installed = False def installed(self): - """Checks if both FFmpeg and FFprobe are installed""" + """Checks if both FFmpeg and FFprobe are installed and in the PATH.""" + # Same checker that ffmpeg-python uses if which("ffmpeg"): self.ffmpeg_installed = True logging.info(f"FFmpeg found!") @@ -45,14 +50,21 @@ def installed(self): return self.ffmpeg_installed and self.ffprobe_installed def show_warning(self): + """Displays the warning to the user and awaits respone.""" if not self.ffmpeg_installed: self.setText("Warning: Could not find FFmpeg installation") - self.setInformativeText("FFmpeg is required for video/audio thumbnails and playback") + self.setInformativeText( + "FFmpeg is required for video/audio thumbnails and playback" + ) elif not self.ffprobe_installed: # If ffmpeg is installed but not ffprobe self.setText("Warning: Could not find FFprobe installation") - self.setInformativeText("FFprobe is required for video/audio thumbnails and playback") + self.setInformativeText( + "FFprobe is required for video/audio thumbnails and playback" + ) + # Shows the dialog selection = self.exec() + # Selection will either be QMessageBox.Help or QMessageBox.Ignore if selection == QMessageBox.Help: QDesktopServices.openUrl(QUrl(self.help_url)) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index d1a2e5e08..11f22f013 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -1850,6 +1850,7 @@ def open_library(self, path: Path): self.main_window.toggle_landing_page(False) def check_ffmpeg(self) -> None: + """Checks if FFmpeg is installed and displays a warning if not.""" self.ffmpeg_checker = FfmpegChecker() if not self.ffmpeg_checker.installed(): self.ffmpeg_checker.show_warning() From d2e0949be12e1b088b0c032858a26c51463c4c09 Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 20:14:06 -0500 Subject: [PATCH 04/12] chore: Cleanup missing logic and warning message --- tagstudio/src/qt/modals/ffmpeg_checker.py | 31 +++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index 327bc9f1b..8c9cb729b 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -35,36 +35,35 @@ def __init__(self): self.setWindowModality(Qt.ApplicationModal) self.setWindowTitle("Warning: Missing dependency") - self.ffmpeg_installed = False - self.ffprobe_installed = False + self.ffmpeg_missing = True + self.ffprobe_missing = True def installed(self): """Checks if both FFmpeg and FFprobe are installed and in the PATH.""" # Same checker that ffmpeg-python uses if which("ffmpeg"): - self.ffmpeg_installed = True + self.ffmpeg_missing = False logging.info(f"FFmpeg found!") if which("ffprobe"): - self.ffprobe_installed = True + self.ffprobe_missing = False logging.info(f"FFprobe found!") - return self.ffmpeg_installed and self.ffprobe_installed + # Reverse from missing to installed + return not (self.ffmpeg_missing or self.ffprobe_missing) def show_warning(self): """Displays the warning to the user and awaits respone.""" - if not self.ffmpeg_installed: - self.setText("Warning: Could not find FFmpeg installation") - self.setInformativeText( - "FFmpeg is required for video/audio thumbnails and playback" - ) - elif not self.ffprobe_installed: - # If ffmpeg is installed but not ffprobe - self.setText("Warning: Could not find FFprobe installation") - self.setInformativeText( - "FFprobe is required for video/audio thumbnails and playback" - ) + missing = "FFmpeg" + # If ffmpeg is installed but not ffprobe + if self.ffprobe_missing and not self.ffmpeg_missing: + missing = "FFprobe" + self.setText(f"Warning: Could not find {missing} installation") + self.setInformativeText( + f"{missing} is required for multimedia thumbnails and playback" + ) # Shows the dialog selection = self.exec() + # Selection will either be QMessageBox.Help or QMessageBox.Ignore if selection == QMessageBox.Help: QDesktopServices.openUrl(QUrl(self.help_url)) From 1ad1313282d5ba5a80fb762aa89630d57f71696a Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 20:15:45 -0500 Subject: [PATCH 05/12] 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) --- tagstudio/resources/qt/images/thumb_warning.png | Bin 13010 -> 0 bytes tagstudio/src/qt/modals/ffmpeg_checker.py | 7 ------- 2 files changed, 7 deletions(-) delete mode 100644 tagstudio/resources/qt/images/thumb_warning.png diff --git a/tagstudio/resources/qt/images/thumb_warning.png b/tagstudio/resources/qt/images/thumb_warning.png deleted file mode 100644 index b5ce2d3444b7591200914d2c4902764f91bc66c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13010 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 MsijGkk;}vX0k#q&f&c&j diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index 8c9cb729b..1b4982322 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -13,18 +13,11 @@ class FfmpegChecker(QMessageBox): """A warning dialog for if FFmpeg is missing.""" - warning_icon_128: Image.Image = Image.open( - str(Path(__file__).parents[3] / "resources/qt/images/thumb_warning.png") - ).resize((math.floor(24 * 1.25), math.floor(24 * 1.25))) - warning_icon_128.load() - help_url = "https://github.com/TagStudioDev/TagStudio/blob/Alpha-v9.4/doc/utilities/ffmpeg.md" def __init__(self): super().__init__() - # self.warning_icon = QPixmap.fromImage(ImageQt.ImageQt(self.warning_icon_128)) - # self.setIconPixmap(self.warning_icon) self.setIcon(QMessageBox.Warning) self.setText("Warning: Could not find FFmpeg installation") From 0f782f6662fcbbedeb14d530c5d005b32bebb0db Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 20:22:22 -0500 Subject: [PATCH 06/12] fix: Ignore dialog with X button --- tagstudio/src/qt/modals/ffmpeg_checker.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index 1b4982322..8bd344c2a 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -21,8 +21,12 @@ def __init__(self): self.setIcon(QMessageBox.Warning) self.setText("Warning: Could not find FFmpeg installation") - self.setStandardButtons(QMessageBox.Help | QMessageBox.Ignore) + self.setStandardButtons( + QMessageBox.Help | QMessageBox.Ignore | QMessageBox.Cancel + ) self.setDefaultButton(QMessageBox.Ignore) + # Enables the cancel button but hides it to allow for click X to close dialog + self.button(QMessageBox.Cancel).hide() # Blocks other application interactions until resolved self.setWindowModality(Qt.ApplicationModal) @@ -57,6 +61,6 @@ def show_warning(self): # Shows the dialog selection = self.exec() - # Selection will either be QMessageBox.Help or QMessageBox.Ignore + # Selection will either be QMessageBox.Help or (QMessageBox.Ignore | QMessageBox.Cancel) which can be ignored if selection == QMessageBox.Help: QDesktopServices.openUrl(QUrl(self.help_url)) From 9f111829d8eedcede9ab3e913172cd74aa32e680 Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Tue, 3 Sep 2024 21:09:26 -0500 Subject: [PATCH 07/12] fix: Move startup checks after CI --- .github/workflows/apprun.yaml | 3 ++- tagstudio/src/qt/ts_qt.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/apprun.yaml b/.github/workflows/apprun.yaml index 9894f168e..9685aea1e 100644 --- a/.github/workflows/apprun.yaml +++ b/.github/workflows/apprun.yaml @@ -33,7 +33,8 @@ jobs: libxcb-xinerama0 \ libopengl0 \ libxcb-cursor0 \ - libpulse0 + libpulse0 \ + ffmpeg - name: Install dependencies run: | diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 11f22f013..d84100df1 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -637,11 +637,12 @@ def create_folders_tags_modal(): ) self.open_library(Path(lib)) - self.check_ffmpeg() - if self.args.ci: # gracefully terminate the app in CI environment self.thumb_job_queue.put((self.SIGTERM.emit, [])) + else: + # Startup Checks + self.check_ffmpeg() app.exec() From a7d64ecdbe14685f7027efe41fb0dcd89c0bf23b Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Fri, 6 Sep 2024 11:12:51 -0500 Subject: [PATCH 08/12] chore: Unreverse install check logic --- tagstudio/src/qt/modals/ffmpeg_checker.py | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index 8bd344c2a..1859848e9 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -18,9 +18,12 @@ class FfmpegChecker(QMessageBox): def __init__(self): super().__init__() + self.setWindowTitle("Warning: Missing dependency") + self.setText("Warning: Could not find FFmpeg installation") self.setIcon(QMessageBox.Warning) + # Blocks other application interactions until resolved + self.setWindowModality(Qt.ApplicationModal) - self.setText("Warning: Could not find FFmpeg installation") self.setStandardButtons( QMessageBox.Help | QMessageBox.Ignore | QMessageBox.Cancel ) @@ -28,30 +31,27 @@ def __init__(self): # Enables the cancel button but hides it to allow for click X to close dialog self.button(QMessageBox.Cancel).hide() - # Blocks other application interactions until resolved - self.setWindowModality(Qt.ApplicationModal) - self.setWindowTitle("Warning: Missing dependency") - - self.ffmpeg_missing = True - self.ffprobe_missing = True + self.ffmpeg = False + self.ffprobe = False def installed(self): """Checks if both FFmpeg and FFprobe are installed and in the PATH.""" # Same checker that ffmpeg-python uses if which("ffmpeg"): - self.ffmpeg_missing = False - logging.info(f"FFmpeg found!") + self.ffmpeg = True if which("ffprobe"): - self.ffprobe_missing = False - logging.info(f"FFprobe found!") - # Reverse from missing to installed - return not (self.ffmpeg_missing or self.ffprobe_missing) + self.ffprobe = True + + logging.info( + f"[FFmpegChecker] FFmpeg found: {self.ffmpeg}, FFprobe found: {self.ffprobe}" + ) + return self.ffmpeg and self.ffprobe def show_warning(self): """Displays the warning to the user and awaits respone.""" missing = "FFmpeg" # If ffmpeg is installed but not ffprobe - if self.ffprobe_missing and not self.ffmpeg_missing: + if not self.ffprobe and self.ffmpeg: missing = "FFprobe" self.setText(f"Warning: Could not find {missing} installation") From 01868d5d41a9d1995f851e3ffa7fcac9f5965073 Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Fri, 6 Sep 2024 15:14:41 -0500 Subject: [PATCH 09/12] doc: Improve docs formatting --- doc/utilities/ffmpeg.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/utilities/ffmpeg.md b/doc/utilities/ffmpeg.md index f9599cd6a..127d8563c 100644 --- a/doc/utilities/ffmpeg.md +++ b/doc/utilities/ffmpeg.md @@ -8,23 +8,23 @@ Pre-built binaries from trusted sources are available on the [FFmpeg website](ht To install: 1. Download 7z or zip file and extract it (right click > Extract All) 2. Move extracted contents to a unique folder (i.e; `c:\ffmpeg` or `c:\Program Files\ffmpeg`) -3. Add FFmpeg to your PATH - a. Go to "Edit the system environment variables" - b. Under "User Variables", select "Path" then edit - c. Click new and add `\bin` (e.g; `c:\ffmpeg\bin` or `c:\Program Files\ffmpeg\bin`) - d. Click okay +3. Add FFmpeg to your PATH + 1. Go to "Edit the system environment variables" + 2. Under "User Variables", select "Path" then edit + 3. Click new and add `\bin` (e.g; `c:\ffmpeg\bin` or `c:\Program Files\ffmpeg\bin`) + 4. Click okay ## Package Managers FFmpeg is also available from: -1. WinGet (`winget install ffmpeg) +1. WinGet (`winget install ffmpeg`) 2. Scoop (`scoop install main/ffmpeg`) 3. Chocolatey (`choco install ffmpeg-full`) # Installation on Mac --- ## Homebrew -FFmpeg is available via Homebrew and can be installed via; +FFmpeg is available via [Homebrew](https://brew.sh/) and can be installed via; `brew install ffmpeg` From 97c70b165d15d49e08a2b3da34d8263a512a95eb Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Sat, 7 Sep 2024 16:09:01 -0500 Subject: [PATCH 10/12] docs: Point help url to new docs sites --- doc/{utilities => help}/ffmpeg.md | 4 ---- tagstudio/src/qt/modals/ffmpeg_checker.py | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) rename doc/{utilities => help}/ffmpeg.md (98%) diff --git a/doc/utilities/ffmpeg.md b/doc/help/ffmpeg.md similarity index 98% rename from doc/utilities/ffmpeg.md rename to doc/help/ffmpeg.md index 127d8563c..569e13ae9 100644 --- a/doc/utilities/ffmpeg.md +++ b/doc/help/ffmpeg.md @@ -1,7 +1,6 @@ FFmpeg is required for thumbnail previews and playback features on audio and video files. FFmpeg is a free Open Source project dedicated to the handling of multimedia (video, audio, etc) files. # Installation on Windows ---- ## Prebuilt Binaries Pre-built binaries from trusted sources are available on the [FFmpeg website](https://www.ffmpeg.org/download.html#build-windows). @@ -22,14 +21,12 @@ FFmpeg is also available from: 3. Chocolatey (`choco install ffmpeg-full`) # Installation on Mac ---- ## Homebrew FFmpeg is available via [Homebrew](https://brew.sh/) and can be installed via; `brew install ffmpeg` # Installation on Linux ---- ## Package Managers FFmpeg may be installed by default on some Linux distrobutions, but if not, it is available via your distro's package manager of choice @@ -38,5 +35,4 @@ FFmpeg may be installed by default on some Linux distrobutions, but if not, it i 3. Arch (`sudo pacman -S ffmpeg`) # Help ---- For additional help, please create an Issue on the [GitHub repository](https://github.com/TagStudioDev/TagStudio) or join the [Discord]() diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index 1859848e9..d1b372777 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -13,7 +13,7 @@ class FfmpegChecker(QMessageBox): """A warning dialog for if FFmpeg is missing.""" - help_url = "https://github.com/TagStudioDev/TagStudio/blob/Alpha-v9.4/doc/utilities/ffmpeg.md" + HELP_URL = "https://docs.tagstud.io/help/ffmpeg/" def __init__(self): super().__init__() @@ -63,4 +63,4 @@ def show_warning(self): # Selection will either be QMessageBox.Help or (QMessageBox.Ignore | QMessageBox.Cancel) which can be ignored if selection == QMessageBox.Help: - QDesktopServices.openUrl(QUrl(self.help_url)) + QDesktopServices.openUrl(QUrl(self.HELP_URL)) From 162b23dd1c739160add64aa3c7efd6e2d2bfcf0a Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Sat, 7 Sep 2024 22:43:33 -0500 Subject: [PATCH 11/12] Remove ffmpeg docs page --- doc/help/ffmpeg.md | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 doc/help/ffmpeg.md diff --git a/doc/help/ffmpeg.md b/doc/help/ffmpeg.md deleted file mode 100644 index 569e13ae9..000000000 --- a/doc/help/ffmpeg.md +++ /dev/null @@ -1,38 +0,0 @@ -FFmpeg is required for thumbnail previews and playback features on audio and video files. FFmpeg is a free Open Source project dedicated to the handling of multimedia (video, audio, etc) files. - -# Installation on Windows -## Prebuilt Binaries -Pre-built binaries from trusted sources are available on the [FFmpeg website](https://www.ffmpeg.org/download.html#build-windows). - -To install: -1. Download 7z or zip file and extract it (right click > Extract All) -2. Move extracted contents to a unique folder (i.e; `c:\ffmpeg` or `c:\Program Files\ffmpeg`) -3. Add FFmpeg to your PATH - 1. Go to "Edit the system environment variables" - 2. Under "User Variables", select "Path" then edit - 3. Click new and add `\bin` (e.g; `c:\ffmpeg\bin` or `c:\Program Files\ffmpeg\bin`) - 4. Click okay - -## Package Managers -FFmpeg is also available from: - -1. WinGet (`winget install ffmpeg`) -2. Scoop (`scoop install main/ffmpeg`) -3. Chocolatey (`choco install ffmpeg-full`) - -# Installation on Mac -## Homebrew -FFmpeg is available via [Homebrew](https://brew.sh/) and can be installed via; - -`brew install ffmpeg` - -# Installation on Linux -## Package Managers -FFmpeg may be installed by default on some Linux distrobutions, but if not, it is available via your distro's package manager of choice - -1. Debian/Ubuntu (`sudo apt install ffmpeg`) -2. Fedora (`sudo dnf install ffmpeg-free`) -3. Arch (`sudo pacman -S ffmpeg`) - -# Help -For additional help, please create an Issue on the [GitHub repository](https://github.com/TagStudioDev/TagStudio) or join the [Discord]() From c7d79b680ba6c79a605b60a7c6c5b001c1c0ccbb Mon Sep 17 00:00:00 2001 From: Sean Krueger Date: Sat, 7 Sep 2024 23:21:38 -0500 Subject: [PATCH 12/12] Use which from python stdlib --- tagstudio/src/qt/modals/ffmpeg_checker.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tagstudio/src/qt/modals/ffmpeg_checker.py b/tagstudio/src/qt/modals/ffmpeg_checker.py index d1b372777..deed05ed5 100644 --- a/tagstudio/src/qt/modals/ffmpeg_checker.py +++ b/tagstudio/src/qt/modals/ffmpeg_checker.py @@ -1,10 +1,10 @@ import logging import math from pathlib import Path +from shutil import which import subprocess from PIL import Image, ImageQt -from pydub.utils import which from PySide6.QtCore import Signal, Qt, QUrl from PySide6.QtGui import QPixmap, QDesktopServices from PySide6.QtWidgets import QMessageBox @@ -36,7 +36,6 @@ def __init__(self): def installed(self): """Checks if both FFmpeg and FFprobe are installed and in the PATH.""" - # Same checker that ffmpeg-python uses if which("ffmpeg"): self.ffmpeg = True if which("ffprobe"):