Skip to content

Instantly share code, notes, and snippets.

@Alvant
Last active October 10, 2020 16:40
Show Gist options
  • Save Alvant/dc0c5799f41982a9a528fce6f761b4c2 to your computer and use it in GitHub Desktop.
Save Alvant/dc0c5799f41982a9a528fce6f761b4c2 to your computer and use it in GitHub Desktop.
import argparse
import os
import warnings
from PIL import (
Image,
ImageDraw,
ImageFont,
)
import cv2
# https://github.com/RameshAditya/asciify
from asciify import runner
FONT_FILE_PATH = 'Roboto.ttf' # need mono font for proper width/height sizes
def save_frames(input_file_path, output_folder_path):
# https://stackoverflow.com/a/17109400/8094251
vc = cv2.VideoCapture(input_file_path)
current_index = 1
if vc.isOpened():
rval , frame = vc.read()
else:
rval = False
if not os.path.isdir(output_folder_path):
os.mkdir(output_folder_path)
while rval:
rval, frame = vc.read()
cv2.imwrite(
filename=os.path.join(output_folder_path, str(current_index) + '.jpg'),
img=frame
)
current_index = current_index + 1
cv2.waitKey(1)
vc.release()
def save_ascii_images(input_folder_path, output_folder_path):
image_names = os.listdir(input_folder_path)
image_names = [
file_name for file_name in image_names
if os.path.isfile(os.path.join(input_folder_path, file_name))
]
numbers = [int(f.split('.')[0]) for f in image_names]
source_image_extension = os.path.splitext(image_names[0])[-1]
target_image_extension = '.png'
if not os.path.isdir(output_folder_path):
os.mkdir(output_folder_path)
for number in sorted(numbers):
image_file_path = os.path.join(input_folder_path, f'{number}{source_image_extension}')
ascii_text = runner(image_file_path)
if ascii_text is None:
warnings.warn(f'Text is None for image "{image_file_path}"!')
else:
_save_image(
text=ascii_text,
path=os.path.join(output_folder_path, f'{number}{target_image_extension}'),
)
def _save_image(text, path, font_size=22):
# https://code-maven.com/create-images-with-python-pil-pillow
# https://stackoverflow.com/questions/17856242/how-to-convert-a-string-to-an-image
img = Image.new(
mode='RGB',
size=(1300, 955 - 2 * 17 * 2 - 4), # TODO: need to adjust this
color=(255, 255, 255),
)
draw = ImageDraw.Draw(img)
if os.path.isfile(FONT_FILE_PATH):
font = ImageFont.truetype(FONT_FILE_PATH, font_size)
else:
warnings.warn(f'No font file "{FONT_FILE_PATH}" found!')
font = None
draw.text(
xy=(0, -8 - 17 * 2), # TODO: need to adjust this
text=text,
font=font,
fill=(0, 0, 0),
spacing=-7, # so as to remove spacing between lines completely
)
# May be helpful for determining text size
# print(draw.textsize(text))
img.save(path)
def save_mp4(input_folder_path, output_file_path, extension='.png'):
# https://tsaith.github.io/combine-images-into-a-video-with-python-3-and-opencv-3.html
images = []
for f in os.listdir(input_folder_path):
if f.endswith(extension):
images.append(f)
images = sorted(images, key=lambda image: int(image.split('.')[0]))
# Determine the width and height from the first image
image_path = os.path.join(input_folder_path, images[0])
frame = cv2.imread(image_path)
cv2.imshow('video', frame)
height, width, channels = frame.shape
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # be sure to use lower case!
output_file = cv2.VideoWriter(output_file_path, fourcc, 20.0, (width, height))
for image in images:
image_path = os.path.join(input_folder_path, image)
frame = cv2.imread(image_path)
output_file.write(frame)
cv2.imshow('video', frame)
if (cv2.waitKey(1) & 0xFF) == ord('q'): # Hit `q` to exit
break
output_file.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
"--input",
required=True,
help="Input .mp4.",
)
parser.add_argument(
"--frames-folder",
required=True,
help="Folder for the original frames of the video file as images.",
)
parser.add_argument(
"--ascii-folder",
required=True,
help="Folder for ASCII images: one ASCII image for each frame of the original video.",
)
parser.add_argument(
"--output",
required=True,
help="Output .mp4.",
)
args = vars(parser.parse_args())
input_file_path = args['input']
frames_folder_path = args['frames_folder']
ascii_folder_path = args['ascii_folder']
output_file_path = args['output']
save_frames(
input_file_path=input_file_path,
output_folder_path=frames_folder_path,
)
save_ascii_images(
input_folder_path=frames_folder_path,
output_folder_path=ascii_folder_path,
)
save_mp4(
input_folder_path=ascii_folder_path,
output_file_path=output_file_path,
)
# TODO: maybe one will still need to use an external tool
# to reconvert .mp4 to .mp4 to fix some stuff
# One more step could be: .mp4 to .gif (using Giphy, for example)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment