Skip to content

Instantly share code, notes, and snippets.

@vxgmichel
Last active Jan 24, 2022
Embed
What would you like to do?
Video conversion for Turing Complete 80x24 display.
#!/usr/bin/env python
"""
Convert an mp4 video file to uncompressed 80x24 video frames.
Frames are represented as 80 x 24 pixels (3 bytes per pixel representing RGB colors).
For instance, data between offset 57600 (`10 * 80 * 24 * 3`) and `63360` (`11 * 80 * 24 * 3`)
represents the 11th frame.
Example usage:
$ pip install youtube-dl numpy opencv-python
$ youtube-dl https://youtu.be/UkgK8eUdpAo -f mp4 -o badapple.mp4
$ ./convert.py badapple.mp4 badapple.bin
"""
import argparse
from pathlib import Path
from typing import Optional
import cv2
import numpy as np
def mp4_to_np(path: Path, nb_frames: Optional[int] = None):
capture = cv2.VideoCapture(str(path))
count = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
count = count if nb_frames is None else min(count, nb_frames)
array = np.empty((count, height, width, 3), np.uint8)
for i in range(count):
_, array[i] = capture.read()
capture.release()
return array
def main(source: Path, destination: Path, nb_frames: Optional[int] = None):
buf = mp4_to_np(source, nb_frames)
count, width, height, depth = buf.shape
target = np.empty((count, 24, 80, 3), np.uint8)
for i in range(count):
target[i] = cv2.resize(buf[i], dsize=(80, 24), interpolation=cv2.INTER_CUBIC)
destination.write_bytes(target.tobytes())
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("source", type=Path)
parser.add_argument("destination", type=Path)
parser.add_argument("--nb-frames", "-n", type=int, default=None)
namespace = parser.parse_args()
main(namespace.source, namespace.destination, namespace.nb_frames)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment