Added interpolation arg, updated docs, provided Dockerfile + instructions

This commit is contained in:
Amber McCloughan 2024-07-03 00:15:18 -04:00
parent 2b6437c1db
commit ad29252a41
3 changed files with 45 additions and 9 deletions

11
Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM python:3.12-slim-bookworm
WORKDIR /app
COPY video_to_gif.py /app/video_to_gif.py
RUN apt update && \
apt upgrade && \
apt install ffmpeg -y
ENTRYPOINT ["python", "video_to_gif.py"]

View File

@ -1,6 +1,9 @@
# video-to-gif # video-to-gif
## Usage
``` ```
usage: video_to_gif.py [-h] -i INPUT [-w WIDTH] [-r FRAMERATE] [-t TAG] usage: video_to_gif.py [-h] -i INPUT [-w WIDTH] [-r FRAMERATE]
[-s {fast_bilinear,bilinear,bicubic,experimental,neighbor,area,bicublin,gauss,sinc,lanczos,spline}]
[-interpolate {none,dup,blend,mci}] [-t TAG]
Use ffmpeg to make GIFs from videos Use ffmpeg to make GIFs from videos
@ -9,10 +12,20 @@ options:
-i INPUT, --input INPUT -i INPUT, --input INPUT
Input pattern like '/users/MyName/Videos/*.mov' Input pattern like '/users/MyName/Videos/*.mov'
-w WIDTH, --width WIDTH -w WIDTH, --width WIDTH
Width of the GIF in pixels, respecting aspect ratio Width of the GIF in pixels, respecting aspect ratio (default: 960)
-r FRAMERATE, --framerate FRAMERATE -r FRAMERATE, --framerate FRAMERATE
Framerate of GIF Framerate of GIF (default: 12)
-s {fast_bilinear,bilinear,bicubic,experimental,neighbor,area,bicublin,gauss,sinc,lanczos,spline}, --scaler {fast_bilinear,bilinear,bicubic,experimental,neighbor,area,bicublin,gauss,sinc,lanczos,spline}
Scaling algorithm to use (default: lanczos)
-interpolate {none,dup,blend,mci}, --interpolate {none,dup,blend,mci}
Interpolation method to use (default: none)
-t TAG, --tag TAG Optional tag included in file name -t TAG, --tag TAG Optional tag included in file name
— Be gay and do crime — Be gay and do crime
``` ```
## Docker
```shell
docker build -t video_to_gif:latest .
docker run video_to_gif --help
```

View File

@ -16,11 +16,13 @@ def get_args() -> Dict[str, Any]:
parser.add_argument('-i', '--input', type=str, required=True, parser.add_argument('-i', '--input', type=str, required=True,
help="Input pattern like '/users/MyName/Videos/*.mov'") help="Input pattern like '/users/MyName/Videos/*.mov'")
parser.add_argument('-w', '--width', type=str, default='960', parser.add_argument('-w', '--width', type=str, default='960',
help='Width of the GIF in pixels, respecting aspect ratio') help='Width of the GIF in pixels, respecting aspect ratio (default: 960)')
parser.add_argument('-r', '--framerate', type=str, parser.add_argument('-r', '--framerate', type=str,
default='12', help='Framerate of GIF') default='12', help='Framerate of GIF (default: 12)')
parser.add_argument('-s', '--scaler', type=str, choices=get_scaling_algorithms(), parser.add_argument('-s', '--scaler', type=str, choices=get_scaling_algorithms(),
default='lanczos', help='Scaling algorithm to use') default='lanczos', help='Scaling algorithm to use (default: lanczos)')
parser.add_argument('-interpolate', '--interpolate', type=str, choices=get_interpolation_methods(),
default='none', help='Interpolation method to use (default: none)')
parser.add_argument('-t', '--tag', type=str, default=get_tag(), parser.add_argument('-t', '--tag', type=str, default=get_tag(),
help='Optional tag included in file name') help='Optional tag included in file name')
return vars(parser.parse_args()) return vars(parser.parse_args())
@ -31,6 +33,10 @@ def get_scaling_algorithms() -> List[str]:
'area', 'bicublin', 'gauss', 'sinc', 'lanczos', 'spline'] 'area', 'bicublin', 'gauss', 'sinc', 'lanczos', 'spline']
def get_interpolation_methods() -> List[str]:
return ['none', 'dup', 'blend', 'mci']
# TODO: Figure out how to specify both scaling and dithering algorithms. # TODO: Figure out how to specify both scaling and dithering algorithms.
def get_dithering_algorithms() -> List[str]: def get_dithering_algorithms() -> List[str]:
return ['none', 'auto', 'bayer', 'ed', 'a_dither', 'x_dither'] return ['none', 'auto', 'bayer', 'ed', 'a_dither', 'x_dither']
@ -54,12 +60,18 @@ def generate_gif_files(inputs: List[str], args: Dict[str, Any]) -> Dict[str, str
width = args['width'] width = args['width']
framerate = args['framerate'] framerate = args['framerate']
scaler = args['scaler'] scaler = args['scaler']
interpolate = args['interpolate']
interpolate_cmd = ''
if interpolate != 'none':
interpolate_cmd = f"minterpolate=fps={ \
framerate}:mi_mode={interpolate},"
output_map = {} output_map = {}
for input in inputs: for input in inputs:
file_name = f"{Path(input).stem}_{tag}.gif" file_name = f"{Path(input).stem}_{tag}.gif"
full_path = f"{Path(input).parent}/{file_name}" full_path = f"{Path(input).parent}/{file_name}"
call_ffmpeg(f"-i {input} -f gif -r {framerate} -filter_complex scale={ \ call_ffmpeg(f"-i {input} -f gif -r {framerate} -filter_complex {interpolate_cmd}scale={ \
width}:-1:flags={scaler},split[v1][v2];[v1]palettegen[plt];[v2][plt]paletteuse { \ width}:-1:flags={scaler},split[v1][v2];[v1]palettegen[plt];[v2][plt]paletteuse { \
full_path}") full_path}")
output_map[input] = full_path output_map[input] = full_path