Skip to content

Instantly share code, notes, and snippets.

@timendum
Last active September 10, 2020 11:05
Show Gist options
  • Save timendum/c8e9c6b79ca44872a264e9f354dfdaf6 to your computer and use it in GitHub Desktop.
Save timendum/c8e9c6b79ca44872a264e9f354dfdaf6 to your computer and use it in GitHub Desktop.
Create a GIF with ffmpeg
ffmpeg -y -ss $BEGIN -t $LENGTH -i $INPUT cut.mkv
ffmpeg -i cut.mkv -vf cropdetect=24:16:0 -f null -
ffmpeg -i cut.mkv -vf crop=$CROP cropped.mkv
ffmpeg -y -i cropped.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
ffmpeg -y -i cropped.mkv -i palette.png -filter_complex "fps=10,scale=400:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
# example:
# $INPUT = file.mkv
# $BEGIN = 00:00:50.5
# $LENGTH = 1.6
# $CROP = 1920:800:0:140 (output of cropdetect)
"""Create subtitles with python, Imagemagick and FFMPEG"""
import subprocess
import json
SUBS = [
[0, 1.6, "First line"],
[1.7, 3.9, "Second line"],
]
FILE = "cropped.mkv"
FONT = "Impact"
FFPROBE = "ffprobe"
FFMPEG = "ffmpeg"
CONVERT = "convert"
def main():
jdimensions = subprocess.check_output(FFPROBE + " -v error -select_streams v:0 -show_entries stream=width,height -of json " + FILE, text=True)
dimensions = [json.loads(jdimensions)["streams"][0][k] for k in ('width', 'height')]
size = '{}x{}'.format(*dimensions)
font_size = round(dimensions[1] * 0.15)
# https://bbc.github.io/subtitle-guidelines/#Authoring-font-size
position = round(dimensions[1] / 2 - font_size * 1.1)
for i, sub in enumerate(SUBS):
subprocess.run(CONVERT + " -size {size} xc:none -font {font} -pointsize {pointsize} -fill white -stroke black -strokewidth 3 -gravity center -annotate +0+{position} \"{text}\" {i}.png".format(
size=size,
font=FONT,
pointsize=font_size,
position=position,
text=sub[2].upper(),
i=i
)
)
merge_inputs = " ".join(["-i {}.png".format(i) for i, _ in enumerate(SUBS)])
merge_filters = ";".join(["[v{i}][{ii}:v]overlay=0:0:enable='between(t,{ts},{te})'[v{ii}]".format(i=i,ii=i+1,ts=sub[0],te=sub[1]) for i, sub in enumerate(SUBS)])
merge_filters = "[0:v]" + merge_filters[4:]
merge_map = "[v{}]".format(len(SUBS))
subprocess.run(FFMPEG + " -i {file} {inputs} -filter_complex \"{filters}\" -pix_fmt yuv420p -map \"{map}\" -y subbed.mkv".format(
file=FILE,
inputs=merge_inputs,
filters=merge_filters,
map=merge_map,
))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment