Create a WebM video with a dynamic resolution.
Run the script like this:
python3 webm_resizer.py [-x shrink] [-y random] input_video.mp4 [output.webm]
The only required argument is the input video. If there’s no output path, the resized video will be saved in the same directory as the input video, with an “out.webm” extension. -x
and -y
are flags for which function to apply to the horizontal and vertical dimension, respectively. To see the list of available functions, run the script with the -h
flag.
In order to be more robust, some codecs allow a data stream to change attributes mid-playback. This script works in three steps:
- Read a video file and dump all the frames as individual PNG images in a temporary directory.
- Encode the image files as individual videos with a length of a single frame, using the VP9 codec. In this step, each frame is resized to an arbitrary resolution.
- Concatenate each frame-length video into a new WebM file with the same length as the input file. There is no re-encoding here, so each frame keeps its resolution.
- After everything is done, delete the temporary files.
Creating a new video per frame involves making everything a keyframe for their own individual video files, so the resized video will be larger in size than the input file. I don’t know a way to bypass this, other than to maybe reduce the bitrate of each frame file.
In order to resize one of the dimensions of a frame, this script uses functions like the following:
def my_func(frame_number: int, resolution: int) -> int:
frame_number
starts from 0, and resolution
is defined by the video; it can be either the horizontal or vertical resolution. This function returns the new resolution for the output frame, based on an arbitrary formula determined by the previously mentioned parameters.
An alternative way to write functions is to define a closure that accepts an int
representing the total number of frames in the video, and returning another function with the previously mentioned signature. This is useful for transformations that depend on the length of the video, like gradually shrinking it until the last frame is pixel-sized.
If it makes more sense, here’s the function signatures as type annotations:
from typing import Callable
resolution = int
frame = int
resolution_function = Callable[[frame, resolution], resolution]
resolution_closure = Callable[[frame], resolution_function]
- Python 3.
ffmpeg
andffprobe
inPATH
.
This project is licensed under the public-domain-equivalent BSD Zero Clause License.