Skip to content

Instantly share code, notes, and snippets.

@simonbogh
Last active December 23, 2023 22:51
Show Gist options
  • Save simonbogh/7a231c84cfdaf8487c8cada2620655cc to your computer and use it in GitHub Desktop.
Save simonbogh/7a231c84cfdaf8487c8cada2620655cc to your computer and use it in GitHub Desktop.
Python script that uses ffmpeg to change the speed of a video-file
import os
import subprocess
import argparse
"""
This script uses ffmpeg to change the playback speed of an MKV file
and save it as an MP4 file with a watermark. The user must provide the
name of the input MKV file and the playback speed as command line
arguments when running the script.
The output MP4 file is saved with the same name as the input MKV file,
with a prefix indicating the speed increase (e.g. "1.5x_"), and a text
watermark in the upper left corner with the speed increase (e.g. "1.5x").
The font of the text is Helvetica, the font size is 48, the font color is black,
and the text is surrounded by a white box with a 50% opacity.
Example:
$ python 3 convert_video_speed.py input_video.mkv --speed 1.5 --add-watermark
Args:
filename (str): The name of the input MKV file.
speed (float): The speed to change the file (e.g. 1.5 for 1.5x speed).
"""
# Define command line arguments
parser = argparse.ArgumentParser(description='Change the speed of an MKV file using ffmpeg.')
parser.add_argument('filename', type=str, help='name of the input MKV file')
parser.add_argument('--speed', type=float, help='speed to change the file (e.g. 1.5 for 1.5x speed)')
parser.add_argument('--add-watermark', action='store_true', help='add a white box and text watermark to the video')
parser.add_argument('--remove-audio', action='store_true', help='remove audio from the output video')
args = parser.parse_args()
# Define output file name
prefix = f"{args.speed:.1f}x_"
basename, ext = os.path.splitext(args.filename)
output_file = prefix + basename + ".mp4"
# Define watermark text
watermark_text = f"{args.speed:.1f}x"
# Check if input file has audio stream
has_audio = False
if not args.remove_audio:
probe_command = ['ffprobe', '-v', 'error', '-select_streams', 'a:0', '-show_entries', 'stream=codec_type', '-of', 'default=nokey=1:noprint_wrappers=1', args.filename]
probe_output = subprocess.check_output(probe_command, stderr=subprocess.STDOUT)
if probe_output.decode().strip() == 'audio':
has_audio = True
# Define ffmpeg command
command = ['ffmpeg', '-i', args.filename]
filter_complex = []
if args.add_watermark:
filter_complex.append(f'[0:v]setpts={1.0/args.speed}*PTS,drawtext=text=\'{watermark_text}\':fontcolor=black:box=1:[email protected]:boxborderw=5:fontsize=48:x=20:y=30:font=Helvetica[v]')
else:
filter_complex.append(f'[0:v]setpts={1.0/args.speed}*PTS[v]')
if has_audio:
filter_complex.append(f'[0:a]atempo={args.speed}[a]')
command += ['-filter_complex', ';'.join(filter_complex)]
if has_audio:
command += ['-map', '[v]', '-map', '[a]']
else:
command += ['-map', '[v]']
command += ['-c:v', 'libx264', '-crf', '18', '-preset', 'fast', '-c:a', 'aac', '-b:a', '192k',
'-strict', '-2', '-f', 'mp4', output_file]
# Run ffmpeg command
subprocess.run(command)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment