Fix check ffmpeg part 2

This commit is contained in:
Lovi 2024-12-28 17:44:37 +01:00
parent 1f8a534069
commit ada678f0fd
2 changed files with 73 additions and 44 deletions

View File

@ -144,20 +144,23 @@ def print_duration_table(file_path: str, description: str = "Duration", return_s
- str: The formatted duration string if return_string is True. - str: The formatted duration string if return_string is True.
- dict: A dictionary with keys 'h', 'm', 's' representing hours, minutes, and seconds if return_string is False. - dict: A dictionary with keys 'h', 'm', 's' representing hours, minutes, and seconds if return_string is False.
""" """
video_duration = get_video_duration(file_path) try:
video_duration = get_video_duration(file_path)
if video_duration is not None: if video_duration is not None:
hours, minutes, seconds = format_duration(video_duration) hours, minutes, seconds = format_duration(video_duration)
formatted_duration = f"[yellow]{int(hours)}[red]h [yellow]{int(minutes)}[red]m [yellow]{int(seconds)}[red]s" formatted_duration = f"[yellow]{int(hours)}[red]h [yellow]{int(minutes)}[red]m [yellow]{int(seconds)}[red]s"
duration_dict = {'h': hours, 'm': minutes, 's': seconds} duration_dict = {'h': hours, 'm': minutes, 's': seconds}
if description: if description:
console.print(f"[cyan]{description} for [white]([green]{os.path.basename(file_path)}[white]): {formatted_duration}") console.print(f"[cyan]{description} for [white]([green]{os.path.basename(file_path)}[white]): {formatted_duration}")
else:
if return_string:
return formatted_duration
else: else:
return duration_dict if return_string:
return formatted_duration
else:
return duration_dict
except:
return None
def get_ffprobe_info(file_path): def get_ffprobe_info(file_path):

View File

@ -116,21 +116,34 @@ class FFMPEGDownloader:
def _check_existing_binaries(self) -> Tuple[Optional[str], Optional[str], Optional[str]]: def _check_existing_binaries(self) -> Tuple[Optional[str], Optional[str], Optional[str]]:
""" """
Check if FFmpeg binaries already exist in the base directory. Check if FFmpeg binaries already exist in the base directory.
Enhanced to check both the binary directory and system paths on macOS.
Returns:
Tuple[Optional[str], Optional[str], Optional[str]]: Paths to ffmpeg, ffprobe, and ffplay executables.
Returns None for each executable that is not found.
""" """
config = FFMPEG_CONFIGURATION[self.os_name] config = FFMPEG_CONFIGURATION[self.os_name]
executables = config['executables'] executables = config['executables']
found_executables = [] found_executables = []
for executable in executables: # For macOS, check both binary directory and system paths
exe_paths = glob.glob(os.path.join(self.base_dir, executable)) if self.os_name == 'darwin':
if exe_paths: potential_paths = [
found_executables.append(exe_paths[0]) '/usr/local/bin',
else: '/opt/homebrew/bin',
found_executables.append(None) '/usr/bin',
self.base_dir
]
for executable in executables:
found = None
for path in potential_paths:
full_path = os.path.join(path, executable)
if os.path.exists(full_path) and os.access(full_path, os.X_OK):
found = full_path
break
found_executables.append(found)
else:
# Original behavior for other operating systems
for executable in executables:
exe_paths = glob.glob(os.path.join(self.base_dir, executable))
found_executables.append(exe_paths[0] if exe_paths else None)
return tuple(found_executables) if len(found_executables) == 3 else (None, None, None) return tuple(found_executables) if len(found_executables) == 3 else (None, None, None)
@ -275,41 +288,55 @@ class FFMPEGDownloader:
def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]: def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
""" """
Check for FFmpeg executables in the system and download them if not found. Check for FFmpeg executables in the system and download them if not found.
Enhanced detection for macOS systems.
Returns: Returns:
Tuple[Optional[str], Optional[str], Optional[str]]: Paths to ffmpeg, ffprobe, and ffplay executables. Tuple[Optional[str], Optional[str], Optional[str]]: Paths to ffmpeg, ffprobe, and ffplay executables.
Returns None for each executable that couldn't be found or downloaded.
The function first checks if FFmpeg executables are available in the system PATH:
- On Windows, uses the 'where' command
- On Unix-like systems, uses 'which'
If the executables are not found in PATH, it attempts to download and install them
using the FFMPEGDownloader class.
""" """
try: try:
system_platform = platform.system().lower() system_platform = platform.system().lower()
# Check for Windows platform # Special handling for macOS
if system_platform == 'windows': if system_platform == 'darwin':
# Common installation paths on macOS
potential_paths = [
'/usr/local/bin', # Homebrew default
'/opt/homebrew/bin', # Apple Silicon Homebrew
'/usr/bin', # System default
os.path.expanduser('~/Applications/binary'), # Custom installation
'/Applications/binary' # Custom installation
]
# Using subprocess.call to check the executables and subprocess.check_output to get the path for path in potential_paths:
ffmpeg_path = subprocess.check_output(['where', 'ffmpeg'], text=True).strip().split('\n')[0] if subprocess.call(['where', 'ffmpeg'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 else None ffmpeg_path = os.path.join(path, 'ffmpeg')
ffprobe_path = subprocess.check_output(['where', 'ffprobe'], text=True).strip().split('\n')[0] if subprocess.call(['where', 'ffprobe'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 else None ffprobe_path = os.path.join(path, 'ffprobe')
ffplay_path = subprocess.check_output(['where', 'ffplay'], text=True).strip().split('\n')[0] if subprocess.call(['where', 'ffplay'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 else None ffplay_path = os.path.join(path, 'ffplay')
if (os.path.exists(ffmpeg_path) and os.path.exists(ffprobe_path) and
os.access(ffmpeg_path, os.X_OK) and os.access(ffprobe_path, os.X_OK)):
# Return found executables, with ffplay being optional
ffplay_path = ffplay_path if os.path.exists(ffplay_path) else None
return ffmpeg_path, ffprobe_path, ffplay_path
# If all three executables are found, return their paths # Windows detection
if all([ffmpeg_path, ffprobe_path, ffplay_path]): elif system_platform == 'windows':
return ffmpeg_path, ffprobe_path, ffplay_path try:
ffmpeg_path = subprocess.check_output(['where', 'ffmpeg'], text=True).strip().split('\n')[0]
ffprobe_path = subprocess.check_output(['where', 'ffprobe'], text=True).strip().split('\n')[0]
ffplay_path = subprocess.check_output(['where', 'ffplay'], text=True).strip().split('\n')[0]
if ffmpeg_path and ffprobe_path:
return ffmpeg_path, ffprobe_path, ffplay_path
except subprocess.CalledProcessError:
pass
# Check for Unix-like systems (Linux, macOS) # Linux detection
else: else:
ffmpeg_path = shutil.which('ffmpeg') ffmpeg_path = shutil.which('ffmpeg')
ffprobe_path = shutil.which('ffprobe') ffprobe_path = shutil.which('ffprobe')
ffplay_path = shutil.which('ffplay') ffplay_path = shutil.which('ffplay')
# If all three executables are found, return their paths if ffmpeg_path and ffprobe_path:
if all([ffmpeg_path, ffprobe_path, ffplay_path]):
return ffmpeg_path, ffprobe_path, ffplay_path return ffmpeg_path, ffprobe_path, ffplay_path
# If executables were not found, attempt to download FFmpeg # If executables were not found, attempt to download FFmpeg
@ -317,6 +344,5 @@ def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
return downloader.download() return downloader.download()
except Exception as e: except Exception as e:
# Log any unexpected errors that may occur during the check or download process
logging.error(f"Error checking or downloading FFmpeg executables: {e}") logging.error(f"Error checking or downloading FFmpeg executables: {e}")
return None, None, None return None, None, None