|
|
import gradio as gr |
|
|
import numpy as np |
|
|
import cv2 |
|
|
import os |
|
|
import tempfile |
|
|
import time |
|
|
from PIL import Image, ImageDraw, ImageFont |
|
|
import textwrap |
|
|
from typing import Tuple, List |
|
|
import colorsys |
|
|
|
|
|
class CPUVideoGenerator: |
|
|
def __init__(self): |
|
|
self.temp_dir = tempfile.mkdtemp() |
|
|
|
|
|
def generate_text_video(self, prompt: str, duration: int = 5, fps: int = 24, |
|
|
style: str = "typewriter", width: int = 512, height: int = 512) -> str: |
|
|
"""Generate a video with animated text based on the prompt.""" |
|
|
|
|
|
|
|
|
output_path = os.path.join(self.temp_dir, f"video_{int(time.time())}.mp4") |
|
|
fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
|
|
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) |
|
|
|
|
|
total_frames = duration * fps |
|
|
|
|
|
try: |
|
|
if style == "typewriter": |
|
|
self._create_typewriter_animation(out, prompt, total_frames, width, height, fps) |
|
|
elif style == "fade": |
|
|
self._create_fade_animation(out, prompt, total_frames, width, height, fps) |
|
|
elif style == "slide": |
|
|
self._create_slide_animation(out, prompt, total_frames, width, height, fps) |
|
|
elif style == "glitch": |
|
|
self._create_glitch_animation(out, prompt, total_frames, width, height, fps) |
|
|
elif style == "wave": |
|
|
self._create_wave_animation(out, prompt, total_frames, width, height, fps) |
|
|
else: |
|
|
self._create_typewriter_animation(out, prompt, total_frames, width, height, fps) |
|
|
|
|
|
out.release() |
|
|
return output_path |
|
|
|
|
|
except Exception as e: |
|
|
out.release() |
|
|
raise e |
|
|
|
|
|
def _create_typewriter_animation(self, out, prompt: str, total_frames: int, |
|
|
width: int, height: int, fps: int): |
|
|
"""Create a typewriter effect animation.""" |
|
|
|
|
|
img = Image.new('RGB', (width, height), color=(20, 20, 30)) |
|
|
draw = ImageDraw.Draw(img) |
|
|
|
|
|
|
|
|
margin = 50 |
|
|
font_size = max(20, min(60, (width - 2 * margin) // 20)) |
|
|
font = self._get_font(font_size) |
|
|
|
|
|
|
|
|
lines = textwrap.wrap(prompt, width=30) |
|
|
line_height = font_size + 10 |
|
|
total_text_height = len(lines) * line_height |
|
|
start_y = (height - total_text_height) // 2 |
|
|
|
|
|
|
|
|
total_chars = sum(len(line) for line in lines) |
|
|
chars_per_frame = max(1, total_chars // (total_frames * 0.7)) |
|
|
|
|
|
char_count = 0 |
|
|
for frame_num in range(total_frames): |
|
|
|
|
|
for y in range(height): |
|
|
color_val = 20 + int(10 * (y / height)) |
|
|
color = (color_val, color_val, color_val + 10) |
|
|
cv2.rectangle(img, (0, y), (width, y + 1), color, -1) |
|
|
|
|
|
|
|
|
current_chars = min(char_count, total_chars) |
|
|
drawn_chars = 0 |
|
|
y_pos = start_y |
|
|
|
|
|
for line in lines: |
|
|
if drawn_chars >= current_chars: |
|
|
break |
|
|
|
|
|
line_end = min(len(line), current_chars - drawn_chars) |
|
|
if line_end > 0: |
|
|
|
|
|
text = line[:line_end] |
|
|
draw.text((margin + 2, y_pos + 2), text, font=font, fill=(0, 0, 0)) |
|
|
draw.text((margin, y_pos), text, font=font, fill=(200, 200, 220)) |
|
|
|
|
|
|
|
|
if drawn_chars + line_end < current_chars and frame_num % 10 < 5: |
|
|
text_width = font.getlength(text) |
|
|
draw.line([(margin + text_width, y_pos), |
|
|
(margin + text_width, y_pos + font_size)], |
|
|
fill=(255, 255, 100), width=2) |
|
|
|
|
|
drawn_chars += len(line) |
|
|
y_pos += line_height |
|
|
|
|
|
|
|
|
if char_count >= total_chars and frame_num % 20 < 10: |
|
|
last_line_y = start_y + (len(lines) - 1) * line_height |
|
|
last_line = lines[-1] |
|
|
text_width = font.getlength(last_line) |
|
|
draw.line([(margin + text_width, last_line_y), |
|
|
(margin + text_width, last_line_y + font_size)], |
|
|
fill=(255, 255, 100), width=2) |
|
|
|
|
|
|
|
|
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) |
|
|
out.write(frame) |
|
|
|
|
|
if char_count < total_chars: |
|
|
char_count += chars_per_frame |
|
|
|
|
|
def _create_fade_animation(self, out, prompt: str, total_frames: int, |
|
|
width: int, height: int, fps: int): |
|
|
"""Create a fade in/out animation.""" |
|
|
img = Image.new('RGB', (width, height), color=(30, 20, 40)) |
|
|
draw = ImageDraw.Draw(img) |
|
|
|
|
|
|
|
|
margin = 50 |
|
|
font_size = max(20, min(50, (width - 2 * margin) // 15)) |
|
|
font = self._get_font(font_size) |
|
|
|
|
|
lines = textwrap.wrap(prompt, width=25) |
|
|
line_height = font_size + 15 |
|
|
total_text_height = len(lines) * line_height |
|
|
start_y = (height - total_text_height) // 2 |
|
|
|
|
|
for frame_num in range(total_frames): |
|
|
|
|
|
fade_progress = frame_num / total_frames |
|
|
if fade_progress < 0.3: |
|
|
alpha = fade_progress / 0.3 |
|
|
elif fade_progress > 0.7: |
|
|
alpha = (1.0 - fade_progress) / 0.3 |
|
|
else: |
|
|
alpha = 1.0 |
|
|
|
|
|
|
|
|
for y in range(height): |
|
|
hue = (frame_num * 2 + y * 0.5) % 360 |
|
|
rgb = colorsys.hsv_to_rgb(hue / 360, 0.3, 0.2) |
|
|
color = tuple(int(c * 255) for c in rgb) |
|
|
cv2.rectangle(img, (0, y), (width, y + 1), color, -1) |
|
|
|
|
|
|
|
|
text_color = tuple(int(200 * alpha) for _ in range(3)) |
|
|
y_pos = start_y |
|
|
for line in lines: |
|
|
draw.text((margin, y_pos), line, font=font, fill=text_color) |
|
|
y_pos += line_height |
|
|
|
|
|
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) |
|
|
out.write(frame) |
|
|
|
|
|
def _create_slide_animation(self, out, prompt: str, total_frames: int, |
|
|
width: int, height: int, fps: int): |
|
|
"""Create a sliding text animation.""" |
|
|
img = Image.new('RGB', (width, height), color=(40, 30, 50)) |
|
|
draw = ImageDraw.Draw(img) |
|
|
|
|
|
font_size = max(25, min(60, (width - 2 * 50) // 12)) |
|
|
font = self._get_font(font_size) |
|
|
|
|
|
lines = textwrap.wrap(prompt, width=20) |
|
|
line_height = font_size + 15 |
|
|
|
|
|
for frame_num in range(total_frames): |
|
|
|
|
|
for y in range(height): |
|
|
intensity = 40 + int(20 * np.sin((frame_num + y) * 0.05)) |
|
|
color = (intensity, intensity - 10, intensity + 10) |
|
|
cv2.rectangle(img, (0, y), (width, y + 1), color, -1) |
|
|
|
|
|
|
|
|
slide_progress = (frame_num / total_frames) |
|
|
x_offset = int(width * (1 - 2 * abs(slide_progress - 0.5))) |
|
|
|
|
|
y_pos = (height - len(lines) * line_height) // 2 |
|
|
for line in lines: |
|
|
draw.text((x_offset, y_pos), line, font=font, fill=(220, 200, 180)) |
|
|
y_pos += line_height |
|
|
|
|
|
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) |
|
|
out.write(frame) |
|
|
|
|
|
def _create_glitch_animation(self, out, prompt: str, total_frames: int, |
|
|
width: int, height: int, fps: int): |
|
|
"""Create a glitch-style animation.""" |
|
|
img = Image.new('RGB', (width, height), color=(10, 10, 20)) |
|
|
draw = ImageDraw.Draw(img) |
|
|
|
|
|
font_size = max(20, min(50, (width - 2 * 50) // 15)) |
|
|
font = self._get_font(font_size) |
|
|
|
|
|
lines = textwrap.wrap(prompt, width=25) |
|
|
line_height = font_size + 10 |
|
|
total_text_height = len(lines) * line_height |
|
|
start_y = (height - total_text_height) // 2 |
|
|
|
|
|
for frame_num in range(total_frames): |
|
|
|
|
|
np_img = np.random.randint(0, 30, (height, width, 3), dtype=np.uint8) |
|
|
img = Image.fromarray(np_img) |
|
|
draw = ImageDraw.Draw(img) |
|
|
|
|
|
|
|
|
if frame_num % 5 == 0: |
|
|
for _ in range(3): |
|
|
y = np.random.randint(0, height) |
|
|
color = (np.random.randint(0, 255), np.random.randint(0, 255), np.random.randint(0, 255)) |
|
|
cv2.rectangle(np_img, (0, y), (width, y + np.random.randint(1, 5)), color, -1) |
|
|
|
|
|
|
|
|
y_pos = start_y |
|
|
for line in lines: |
|
|
|
|
|
offsets = [(0, 0), (2, 0), (-2, 2), (1, -1)] |
|
|
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 255)] |
|
|
|
|
|
for (dx, dy), color in zip(offsets, colors): |
|
|
if frame_num % 2 == 0 or frame_num % 3 == 0: |
|
|
draw.text((50 + dx + np.random.randint(-2, 3), |
|
|
y_pos + dy + np.random.randint(-2, 3)), |
|
|
line, font=font, fill=color) |
|
|
|
|
|
y_pos += line_height |
|
|
|
|
|
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) |
|
|
frame = cv2.GaussianBlur(frame, (3, 3), 0) if frame_num % 10 == 0 else frame |
|
|
out.write(frame) |
|
|
|
|
|
def _create_wave_animation(self, out, prompt: str, total_frames: int, |
|
|
width: int, height: int, fps: int): |
|
|
"""Create a wave text animation.""" |
|
|
img = Image.new('RGB', (width, height), color=(20, 40, 60)) |
|
|
draw = ImageDraw.Draw(img) |
|
|
|
|
|
font_size = max(25, min(55, (width - 2 * 50) // 12)) |
|
|
font = self._get_font(font_size) |
|
|
|
|
|
lines = textwrap.wrap(prompt, width=25) |
|
|
line_height = font_size + 15 |
|
|
|
|
|
for frame_num in range(total_frames): |
|
|
|
|
|
for y in range(height): |
|
|
wave = np.sin((frame_num + y * 5) * 0.1) * 20 |
|
|
color_val = int(40 + wave) |
|
|
color = (color_val // 2, color_val, color_val + 20) |
|
|
cv2.rectangle(img, (0, y), (width, y + 1), color, -1) |
|
|
|
|
|
|
|
|
y_pos = (height - len(lines) * line_height) // 2 |
|
|
for line_idx, line in enumerate(lines): |
|
|
for char_idx, char in enumerate(line): |
|
|
wave_offset = int(np.sin((frame_num * 0.1 + char_idx * 0.3 + line_idx)) * 10) |
|
|
x_pos = 50 + char_idx * (font_size * 0.6) |
|
|
y_offset = y_pos + line_idx * line_height + wave_offset |
|
|
|
|
|
|
|
|
hue = (frame_num * 2 + char_idx * 20 + line_idx * 50) % 360 |
|
|
rgb = colorsys.hsv_to_rgb(hue / 360, 0.8, 1.0) |
|
|
color = tuple(int(c * 255) for c in rgb) |
|
|
|
|
|
draw.text((x_pos, y_offset), char, font=font, fill=color) |
|
|
|
|
|
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) |
|
|
out.write(frame) |
|
|
|
|
|
def _get_font(self, size: int): |
|
|
"""Get font, fallback to default if custom font not available.""" |
|
|
try: |
|
|
return ImageFont.truetype("arial.ttf", size) |
|
|
except: |
|
|
try: |
|
|
return ImageFont.truetype("/System/Library/Fonts/Arial.ttf", size) |
|
|
except: |
|
|
try: |
|
|
return ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size) |
|
|
except: |
|
|
return ImageFont.load_default() |
|
|
|
|
|
def generate_pattern_video(self, pattern_type: str, duration: int = 5, fps: int = 24, |
|
|
width: int = 512, height: int = 512) -> str: |
|
|
"""Generate abstract pattern videos.""" |
|
|
output_path = os.path.join(self.temp_dir, f"pattern_{int(time.time())}.mp4") |
|
|
fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
|
|
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) |
|
|
|
|
|
total_frames = duration * fps |
|
|
|
|
|
try: |
|
|
if pattern_type == "spiral": |
|
|
self._create_spiral_pattern(out, total_frames, width, height) |
|
|
elif pattern_type == "particles": |
|
|
self._create_particle_pattern(out, total_frames, width, height) |
|
|
elif pattern_type == "waves": |
|
|
self._create_wave_pattern(out, total_frames, width, height) |
|
|
elif pattern_type == "fractal": |
|
|
self._create_fractal_pattern(out, total_frames, width, height) |
|
|
else: |
|
|
self._create_spiral_pattern(out, total_frames, width, height) |
|
|
|
|
|
out.release() |
|
|
return output_path |
|
|
|
|
|
except Exception as e: |
|
|
out.release() |
|
|
raise e |
|
|
|
|
|
def _create_spiral_pattern(self, out, total_frames: int, width: int, height: int): |
|
|
"""Create animated spiral pattern.""" |
|
|
center_x, center_y = width // 2, height // 2 |
|
|
|
|
|
for frame_num in range(total_frames): |
|
|
frame = np.zeros((height, width, 3), dtype=np.uint8) |
|
|
|
|
|
|
|
|
max_radius = min(width, height) // 2 |
|
|
points = 500 |
|
|
|
|
|
for i in range(points): |
|
|
t = i * 0.1 |
|
|
radius = (i / points) * max_radius |
|
|
angle = t + frame_num * 0.05 |
|
|
|
|
|
x = int(center_x + radius * np.cos(angle)) |
|
|
y = int(center_y + radius * np.sin(angle)) |
|
|
|
|
|
if 0 <= x < width and 0 <= y < height: |
|
|
hue = (i * 2 + frame_num * 5) % 360 |
|
|
rgb = colorsys.hsv_to_rgb(hue / 360, 1.0, 1.0) |
|
|
color = tuple(int(c * 255) for c in rgb) |
|
|
|
|
|
cv2.circle(frame, (x, y), 3, color, -1) |
|
|
|
|
|
out.write(frame) |
|
|
|
|
|
def _create_particle_pattern(self, out, total_frames: int, width: int, height: int): |
|
|
"""Create animated particle system.""" |
|
|
|
|
|
num_particles = 100 |
|
|
particles = [] |
|
|
for _ in range(num_particles): |
|
|
particles.append({ |
|
|
'x': np.random.randint(0, width), |
|
|
'y': np.random.randint(0, height), |
|
|
'vx': np.random.uniform(-2, 2), |
|
|
'vy': np.random.uniform(-2, 2), |
|
|
'size': np.random.randint(2, 8), |
|
|
'hue': np.random.randint(0, 360) |
|
|
}) |
|
|
|
|
|
for frame_num in range(total_frames): |
|
|
frame = np.zeros((height, width, 3), dtype=np.uint8) |
|
|
|
|
|
|
|
|
for particle in particles: |
|
|
|
|
|
particle['x'] += particle['vx'] |
|
|
particle['y'] += particle['vy'] |
|
|
|
|
|
|
|
|
if particle['x'] <= 0 or particle['x'] >= width: |
|
|
particle['vx'] *= -1 |
|
|
if particle['y'] <= 0 or particle['y'] >= height: |
|
|
particle['vy'] *= -1 |
|
|
|
|
|
|
|
|
particle['x'] = np.clip(particle['x'], 0, width - 1) |
|
|
particle['y'] = np.clip(particle['y'], 0, height - 1) |
|
|
|
|
|
|
|
|
hue = (particle['hue'] + frame_num * 2) % 360 |
|
|
rgb = colorsys.hsv_to_rgb(hue / 360, 1.0, 1.0) |
|
|
color = tuple(int(c * 255) for c in rgb) |
|
|
|
|
|
cv2.circle(frame, (int(particle['x']), int(particle['y'])), |
|
|
particle['size'], color, -1) |
|
|
|
|
|
|
|
|
for other in particles: |
|
|
dist = np.sqrt((particle['x'] - other['x'])**2 + |
|
|
(particle['y'] - other['y'])**2) |
|
|
if dist < 100 and dist > 0: |
|
|
cv2.line(frame, (int(particle['x']), int(particle['y'])), |
|
|
(int(other['x']), int(other['y'])), |
|
|
(color[0]//3, color[1]//3, color[2]//3), 1) |
|
|
|
|
|
out.write(frame) |
|
|
|
|
|
def _create_wave_pattern(self, out, total_frames: int, width: int, height: int): |
|
|
"""Create animated wave pattern.""" |
|
|
for frame_num in range(total_frames): |
|
|
frame = np.zeros((height, width, 3), dtype=np.uint8) |
|
|
|
|
|
|
|
|
for y in range(0, height, 5): |
|
|
for x in range(0, width, 5): |
|
|
|
|
|
wave1 = np.sin((x * 0.02 + frame_num * 0.05)) * 20 |
|
|
wave2 = np.cos((y * 0.02 + frame_num * 0.03)) * 20 |
|
|
wave3 = np.sin((x * 0.01 + y * 0.01 + frame_num * 0.02)) * 10 |
|
|
|
|
|
intensity = int(128 + wave1 + wave2 + wave3) |
|
|
intensity = np.clip(intensity, 0, 255) |
|
|
|
|
|
|
|
|
hue = (intensity + frame_num * 2) % 360 |
|
|
rgb = colorsys.hsv_to_rgb(hue / 360, 0.7, intensity / 255) |
|
|
color = tuple(int(c * 255) for c in rgb) |
|
|
|
|
|
cv2.rectangle(frame, (x, y), (x + 5, y + 5), color, -1) |
|
|
|
|
|
out.write(frame) |
|
|
|
|
|
def _create_fractal_pattern(self, out, total_frames: int, width: int, height: int): |
|
|
"""Create animated fractal-like pattern.""" |
|
|
for frame_num in range(total_frames): |
|
|
frame = np.zeros((height, width, 3), dtype=np.uint8) |
|
|
|
|
|
|
|
|
max_depth = 5 |
|
|
self._draw_fractal_tree(frame, width//2, height-50, -90, |
|
|
frame_num * 0.02, max_depth, 80) |
|
|
|
|
|
out.write(frame) |
|
|
|
|
|
def _draw_fractal_tree(self, frame, x, y, angle, time_offset, depth, length): |
|
|
"""Recursively draw fractal tree.""" |
|
|
if depth == 0: |
|
|
return |
|
|
|
|
|
|
|
|
end_x = x + int(length * np.cos(np.radians(angle))) |
|
|
end_y = y + int(length * np.sin(np.radians(angle))) |
|
|
|
|
|
|
|
|
hue = (depth * 60 + time_offset * 50) % 360 |
|
|
rgb = colorsys.hsv_to_rgb(hue / 360, 0.8, 0.8) |
|
|
color = tuple(int(c * 255) for c in rgb) |
|
|
|
|
|
|
|
|
cv2.line(frame, (x, y), (end_x, end_y), color, max(1, depth//2)) |
|
|
|
|
|
|
|
|
angle_variation = 20 + 10 * np.sin(time_offset) |
|
|
self._draw_fractal_tree(frame, end_x, end_y, angle - angle_variation, |
|
|
time_offset, depth - 1, length * 0.7) |
|
|
self._draw_fractal_tree(frame, end_x, end_y, angle + angle_variation, |
|
|
time_offset, depth - 1, length * 0.7) |
|
|
|
|
|
|
|
|
generator = CPUVideoGenerator() |
|
|
|
|
|
def generate_video(prompt: str, style: str, duration: int, fps: int, |
|
|
width: int, height: int, video_type: str) -> Tuple[str, str]: |
|
|
"""Main video generation function.""" |
|
|
try: |
|
|
if video_type == "Text Animation": |
|
|
video_path = generator.generate_text_video( |
|
|
prompt, duration, fps, style, width, height |
|
|
) |
|
|
else: |
|
|
video_path = generator.generate_pattern_video( |
|
|
style, duration, fps, width, height |
|
|
) |
|
|
|
|
|
return video_path, "β
Video generated successfully!" |
|
|
except Exception as e: |
|
|
return None, f"β Error: {str(e)}" |
|
|
|
|
|
|
|
|
with gr.Blocks(title="CPU Video Generator", theme=gr.themes.Soft()) as demo: |
|
|
gr.Markdown(""" |
|
|
# π¬ CPU Video Generator |
|
|
Built with [anycoder](https://huggingface.co/spaces/akhaliq/anycoder) |
|
|
|
|
|
Generate animated videos entirely on CPU! Choose from text animations or abstract patterns. |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
gr.Markdown("### π Input Settings") |
|
|
|
|
|
video_type = gr.Radio( |
|
|
choices=["Text Animation", "Pattern"], |
|
|
value="Text Animation", |
|
|
label="Video Type", |
|
|
info="Choose between text animations or abstract patterns" |
|
|
) |
|
|
|
|
|
prompt = gr.Textbox( |
|
|
label="Text Prompt (for Text Animation)", |
|
|
placeholder="Enter your text here...", |
|
|
value="Welcome to CPU Video Generation!", |
|
|
lines=3 |
|
|
) |
|
|
|
|
|
style = gr.Dropdown( |
|
|
choices=["typewriter", "fade", "slide", "glitch", "wave", |
|
|
"spiral", "particles", "waves", "fractal"], |
|
|
value="typewriter", |
|
|
label="Animation Style", |
|
|
info="Choose the animation style" |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
duration = gr.Slider( |
|
|
minimum=2, maximum=15, value=5, step=1, |
|
|
label="Duration (seconds)" |
|
|
) |
|
|
fps = gr.Slider( |
|
|
minimum=12, maximum=30, value=24, step=1, |
|
|
label="FPS" |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
width = gr.Slider( |
|
|
minimum=256, maximum=1024, value=512, step=64, |
|
|
label="Width" |
|
|
) |
|
|
height = gr.Slider( |
|
|
minimum=256, maximum=1024, value=512, step=64, |
|
|
label="Height" |
|
|
) |
|
|
|
|
|
generate_btn = gr.Button("π₯ Generate Video", variant="primary", size="lg") |
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("### πΉ Output") |
|
|
|
|
|
video_output = gr.Video( |
|
|
label="Generated Video", |
|
|
autoplay=False, |
|
|
show_download_button=True |
|
|
) |
|
|
|
|
|
status_output = gr.Textbox( |
|
|
label="Status", |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
|
|
|
gr.Markdown("### π‘ Examples") |
|
|
examples = gr.Examples( |
|
|
examples=[ |
|
|
["Hello World! This is CPU video generation.", "typewriter", 5, 24, 512, 512, "Text Animation"], |
|
|
["Amazing effects running on CPU only!", "wave", 7, 24, 640, 480, "Text Animation"], |
|
|
["", "spiral", 5, 24, 512, 512, "Pattern"], |
|
|
["", "particles", 8, 24, 640, 480, "Pattern"], |
|
|
["Glitch art with CPU power!", "glitch", 6, 24, 512, 512, "Text Animation"], |
|
|
["", "fractal", 10, 24, 512, 512, "Pattern"], |
|
|
], |
|
|
inputs=[prompt, style, duration, fps, width, height, video_type], |
|
|
outputs=[video_output, status_output], |
|
|
fn=generate_video, |
|
|
cache_examples=False |
|
|
) |
|
|
|
|
|
|
|
|
def update_visibility(video_type): |
|
|
if video_type == "Text Animation": |
|
|
return gr.update(visible=True), gr.update(choices=["typewriter", "fade", "slide", "glitch", "wave"], value="typewriter") |
|
|
else: |
|
|
return gr.update(visible=False), gr.update(choices=["spiral", "particles", "waves", "fractal"], value="spiral") |
|
|
|
|
|
video_type.change( |
|
|
update_visibility, |
|
|
inputs=[video_type], |
|
|
outputs=[prompt, style] |
|
|
) |
|
|
|
|
|
|
|
|
generate_btn.click( |
|
|
generate_video, |
|
|
inputs=[prompt, style, duration, fps, width, height, video_type], |
|
|
outputs=[video_output, status_output] |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch(share=True) |