From 01c31ae17ded3e85f00e5a8ab6e2f19b05edc922 Mon Sep 17 00:00:00 2001 From: Amber Date: Sat, 29 Jun 2024 14:19:12 -0400 Subject: [PATCH] Greatly simplified things by doing palettegen and paletteuse in the same command; I also don't think ewa scaling was working, so I changed to plain old lanc --- README.md | 4 +--- video_to_gif.py | 47 +++++------------------------------------------ 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 4296323..ad8f0ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # video-to-gif ``` -usage: video_to_gif.py [-h] -i INPUT [-w WIDTH] [-r FRAMERATE] [-t TAG] [-f] [-c] +usage: video_to_gif.py [-h] -i INPUT [-w WIDTH] [-r FRAMERATE] [-t TAG] Use ffmpeg to make GIFs from videos @@ -13,8 +13,6 @@ options: -r FRAMERATE, --framerate FRAMERATE Framerate of GIF -t TAG, --tag TAG Optional tag included in file name - -f, --force_palette Force regeneration of GIF color palettes - -c, --clean_up Delete color palettes after finishing GIFs — Be gay and do crime ``` \ No newline at end of file diff --git a/video_to_gif.py b/video_to_gif.py index 8848e02..3660699 100644 --- a/video_to_gif.py +++ b/video_to_gif.py @@ -1,7 +1,6 @@ import argparse import glob -import os from pathlib import Path import random import string @@ -22,10 +21,6 @@ def get_args() -> Dict[str, Any]: default='12', help='Framerate of GIF') parser.add_argument('-t', '--tag', type=str, default=get_tag(), help='Optional tag included in file name') - parser.add_argument('-f', '--force_palette', action='store_const', - const=True, help='Force regeneration of GIF color palettes') - parser.add_argument('-c', '--clean_up', action='store_const', - const=True, help='Delete color palettes after finishing GIFs') return vars(parser.parse_args()) @@ -37,62 +32,30 @@ def get_inputs(args: Dict[str, Any]) -> List[str]: return glob.glob(args['input']) -def clean_up_palette_files(palette_map: Dict[str, str]) -> None: - for input in palette_map: - os.remove(palette_map[input]) - - def call_ffmpeg(command: str) -> str: print("ffmpeg", *command.split(' ')) return str(subprocess.run(["ffmpeg", '-hide_banner', '-loglevel', 'error', *command.split(' ')])) -def generate_palette_files_and_map(inputs: List[str], args: Dict[str, Any]) -> Dict[str, str]: - force_palette = args['force_palette'] - width = args['width'] - tag = args['tag'] - - palette_map = {} - for input in inputs: - file_name = f"{Path(input).stem}_{tag}_palette.png" - full_path = f"{Path(input).parent}/{file_name}" - if force_palette or not os.path.exists(full_path): - call_ffmpeg( - f"-i {input} -lavfi scale={width}:-1,palettegen -sws_flags ewa_lanczos -y {full_path}") - else: - print(f"Skipped regenerating palette file {file_name}...") - palette_map[input] = full_path - - return palette_map - - -def generate_gif_files(palette_map: Dict[str, str], args: Dict[str, Any]) -> Dict[str, str]: +def generate_gif_files(inputs: List[str], args: Dict[str, Any]) -> Dict[str, str]: tag = args['tag'] width = args['width'] framerate = args['framerate'] output_map = {} - for input in palette_map: - palette = palette_map[input] + for input in inputs: file_name = f"{Path(input).stem}_{tag}.gif" full_path = f"{Path(input).parent}/{file_name}" - call_ffmpeg(f"-i {input} -i {palette} -f gif -r {framerate} -lavfi scale={ \ - width}:-1,paletteuse -sws_flags ewa_lanczos {full_path}") + call_ffmpeg(f"-i {input} -f gif -r {framerate} -filter_complex scale={ \ + width}:-1:flags=lanczos,split[v1][v2];[v1]palettegen[plt];[v2][plt]paletteuse {full_path}") output_map[input] = full_path return output_map def make_gifs(args: Dict[str, Any]) -> None: - clean_up = args['clean_up'] inputs = get_inputs(args) - - palette_map = generate_palette_files_and_map(inputs, args) - output_map = generate_gif_files(palette_map, args) - - if clean_up: - clean_up_palette_files(palette_map) - + output_map = generate_gif_files(inputs, args) for input in output_map: print(f"Created {output_map[input]} from {input}")