diff --git a/autopyvideothumbnailer b/autopyvideothumbnailer index 67bc3df..3c8a30f 100755 --- a/autopyvideothumbnailer +++ b/autopyvideothumbnailer @@ -7,21 +7,24 @@ import math import os import subprocess import click +import mimetypes + +from addict import Dict from pymediainfo import MediaInfo -VERBOSE = False +def is_video_file(video_file_path): + type_ = mimetypes.guess_type(video_file_path)[0] + return type_ is not None and type_.startswith("video/") -def is_video_file(video_file_path, video_extensions): - return video_file_path.lower().endswith(tuple(video_extensions)) -def find_video_files(directory, video_extensions): +def find_video_files(directory): # Recursively walk through directory for dirpath, dirs, files in os.walk(directory): for filename in files: filename_path = os.path.join(dirpath, filename) - if is_video_file(filename_path, video_extensions): + if is_video_file(filename_path): yield os.path.abspath(filename_path) @@ -42,60 +45,77 @@ def get_video_duration(video_file_path): return None -def call_thumbnailer(video_file, width, rows, *, skip_seconds=10): +def call_thumbnailer(video_file, width, columns, rows, *, skip_seconds=10): # Call external thumbnailer program subprocess.run( [ "pyvideothumbnailer", "--width", str(width), + "--columns", + str(columns), "--rows", str(rows), "--jpeg-quality", str(90), + "--header-font", + config.font, "--skip-seconds", str(skip_seconds), video_file, ] ) + def process(searchdir): - VIDEO_FILE_EXT = [".mp4", ".mkv", ".avi", ".mov", ".wmv"] - video_files = find_video_files(searchdir, VIDEO_FILE_EXT) + video_files = find_video_files(searchdir) for video_file in video_files: # Skip if .jpg file already exists thumbnails_file = video_file + ".jpg" if os.path.exists(thumbnails_file): - if VERBOSE: + if config.verbose: print(f"Skipping: {video_file} (thumbnails already exist)") continue try: duration = get_video_duration(video_file) if duration is not None: - # Calculate rows - COLS = 4 # pyvideothumbnailer default - EVERY = 5 * 60 # seconds - rows = math.ceil(duration / EVERY / COLS) + rows = math.ceil(duration / config.every / config.columns) skip_seconds = 10 if duration < 60: skip_seconds = 0 # Call the thumbnailer - WIDTH = 1600 - call_thumbnailer(video_file, WIDTH, rows, skip_seconds=skip_seconds) + call_thumbnailer( + video_file, + config.width, + config.columns, + rows, + skip_seconds=skip_seconds, + ) except (TypeError, UnicodeEncodeError, FileNotFoundError) as e: print(f"Error for {video_file}: {e}") +config = Dict() + + @click.command() -@click.argument('searchdirs', nargs=-1) -def main(searchdirs): +@click.argument("searchdirs", nargs=-1) +@click.option("-v", "--verbose", is_flag=True, default=False) +def main(searchdirs, verbose): """Run pyvideothumbnailer for every video file found""" + + config.verbose = verbose + config.width = 1600 + config.columns = 4 # pyvideothumbnailer default + config.every = 5 * 60 # seconds + config.font = "DejaVuSansMono.ttf" + if not searchdirs: - searchdirs=["."] + searchdirs = ["."] for searchdir in searchdirs: process(searchdir)