Last active
December 23, 2023 22:51
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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