diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ea26a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.mp4 +.idea/* +.idea + diff --git a/pyvid2term.py b/pyvid2term.py new file mode 100644 index 0000000..e14c670 --- /dev/null +++ b/pyvid2term.py @@ -0,0 +1,75 @@ +import cv2 +import sys +import time + +BLACK = "⬛" +WHITE = "⬜" + +def frame_to_emoji(frame, threshold=128): + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + + lines = [] + for row in gray: + line = "".join( + WHITE if pixel > threshold else BLACK + for pixel in row + ) + lines.append(line) + + return "\n".join(lines) + +def main(video_path, width=80): + cap = cv2.VideoCapture(video_path) + + if not cap.isOpened(): + print(f"Could not open {video_path}") + return + + fps = cap.get(cv2.CAP_PROP_FPS) + if fps <= 0: + fps = 24 + + frame_delay = 1.0 / fps + + while True: + start = time.time() + + ret, frame = cap.read() + if not ret: + break + + h, w = frame.shape[:2] + + # terminal characters are taller than wide + aspect = h / w + height = max(1, int(width * aspect * 0.5)) + + frame = cv2.resize( + frame, + (width, height), + interpolation=cv2.INTER_AREA + ) + + emoji_frame = frame_to_emoji(frame) + + # clear screen, move cursor to home pos + sys.stdout.write("\033[H\033[J") + sys.stdout.write(emoji_frame) + sys.stdout.flush() + + elapsed = time.time() - start + sleep_time = frame_delay - elapsed + if sleep_time > 0: + time.sleep(sleep_time) + + cap.release() + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python pyvid2term.py video.mp4 [width]") + sys.exit(1) + + video = sys.argv[1] + width = int(sys.argv[2]) if len(sys.argv) > 2 else 80 + + main(video, width) \ No newline at end of file