-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvideo_converter.py
More file actions
130 lines (98 loc) · 4.4 KB
/
Copy pathvideo_converter.py
File metadata and controls
130 lines (98 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python3
"""
Video to ASCII converter for Bad Apple HAProxy Lua player
"""
import cv2
import numpy as np
import json
import os
from typing import List, Tuple
class VideoToASCII:
def __init__(self, width: int = 80, height: int = 24):
self.width = width
self.height = height
self.ascii_chars = ["@", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]
def frame_to_ascii(self, frame: np.ndarray) -> str:
"""Convert a frame to ASCII art"""
resized = cv2.resize(frame, (self.width, self.height))
if len(resized.shape) == 3:
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
else:
gray = resized
normalized = cv2.normalize(gray, None, 0, 255, cv2.NORM_MINMAX)
ascii_frame = []
for row in normalized:
ascii_row = ""
for pixel in row:
char_index = int(pixel / 255 * (len(self.ascii_chars) - 1))
ascii_row += self.ascii_chars[char_index]
ascii_frame.append(ascii_row)
return "\n".join(ascii_frame)
def convert_video(self, input_path: str, output_dir: str = "frames") -> Tuple[List[str], float]:
"""Convert video to ASCII frames"""
if not os.path.exists(input_path):
raise FileNotFoundError(f"Video file not found: {input_path}")
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(input_path)
if not cap.isOpened():
raise ValueError(f"Cannot open video file: {input_path}")
fps = cap.get(cv2.CAP_PROP_FPS)
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = total_frames / fps
print(f"Video info: {total_frames} frames, {fps:.2f} FPS, {duration:.2f}s")
print(f"ASCII size: {self.width}x{self.height}")
frames = []
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
ascii_frame = self.frame_to_ascii(frame)
frames.append(ascii_frame)
frame_count += 1
if frame_count % 100 == 0:
print(f"Processed {frame_count}/{total_frames} frames")
cap.release()
print(f"Converted {len(frames)} frames")
frames_data = {
"fps": fps,
"total_frames": len(frames),
"width": self.width,
"height": self.height,
"frames": frames
}
output_file = os.path.join(output_dir, "bad_apple_frames.json")
with open(output_file, 'w') as f:
json.dump(frames_data, f, separators=(',', ':'))
print(f"Frames saved to: {output_file}")
lua_output = os.path.join(output_dir, "bad_apple_frames.lua")
self.save_lua_format(frames_data, lua_output)
return frames, fps
def save_lua_format(self, frames_data: dict, output_file: str):
"""Save frames in Lua format"""
with open(output_file, 'w') as f:
f.write("-- Bad Apple frames data for HAProxy Lua\n")
f.write("local bad_apple_data = {\n")
f.write(f" fps = {frames_data['fps']},\n")
f.write(f" total_frames = {frames_data['total_frames']},\n")
f.write(f" width = {frames_data['width']},\n")
f.write(f" height = {frames_data['height']},\n")
f.write(" frames = {\n")
for i, frame in enumerate(frames_data['frames'], 1):
escaped_frame = frame.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
f.write(f' [{i}] = "{escaped_frame}",\n')
f.write(" }\n")
f.write("}\n\n")
f.write("return bad_apple_data\n")
print(f"Lua format saved to: {output_file}")
def main():
converter = VideoToASCII(width=80, height=24)
try:
frames, fps = converter.convert_video("video.mp4")
print(f"Conversion complete! {len(frames)} frames at {fps:.2f} FPS")
except Exception as e:
print(f"Error: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())