Spaces:
Sleeping
Sleeping
import gradio as gr | |
import torch | |
import os | |
from transformers import pipeline | |
from diffusers import StableDiffusionPipeline | |
from TTS.api import TTS | |
from moviepy.editor import * | |
# === SETUP === | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
text_gen = pipeline("text-generation", model="dbmdz/german-gpt2", device=0 if device == "cuda" else -1) | |
tts = TTS(model_name="tts_models/de/thorsten/vits", progress_bar=False).to(device) | |
sd = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5").to(device) | |
# === HELFER === | |
def generate_story(title): | |
prompt = f"Titel: {title}\nSchreibe eine kurze, gruselige Horrorgeschichte in etwa 150 Wörtern." | |
output = text_gen(prompt, max_length=200, do_sample=True, temperature=0.9)[0]['generated_text'] | |
return output.strip() | |
def generate_images(story, n=4): | |
prompts = [story[:100]] * n | |
images = [] | |
for i, prompt in enumerate(prompts): | |
image = sd(prompt).images[0] | |
path = f"bild_{i}.png" | |
image.save(path) | |
images.append(path) | |
return images | |
def synthesize_audio(text, path="narration.wav"): | |
tts.tts_to_file(text=text, file_path=path) | |
return path | |
def create_subtitles(text, duration, filename="untertitel.srt"): | |
lines = text.split(". ") | |
per_line = duration / len(lines) | |
with open(filename, "w", encoding="utf-8") as f: | |
for i, line in enumerate(lines): | |
start = i * per_line | |
end = (i + 1) * per_line | |
f.write(f"{i+1}\n") | |
f.write(f"{format_time(start)} --> {format_time(end)}\n") | |
f.write(line.strip() + "\n\n") | |
return filename | |
def format_time(seconds): | |
m, s = divmod(int(seconds), 60) | |
ms = int((seconds - int(seconds)) * 1000) | |
return f"00:{m:02}:{s:02},{ms:03}" | |
def generate_video(images, audio_path, story_text, out_path="output.mp4"): | |
audioclip = AudioFileClip(audio_path) | |
duration = audioclip.duration | |
img_duration = duration / len(images) | |
clips = [ImageClip(img).set_duration(img_duration).resize(height=720) for img in images] | |
videoclip = concatenate_videoclips(clips, method="compose").set_audio(audioclip) | |
srt_file = create_subtitles(story_text, duration) | |
videoclip = videoclip.set_duration(duration) | |
videoclip.write_videofile(out_path, fps=24, codec='libx264') | |
return out_path | |
# === INTERFACE === | |
def generate_horror_video(title): | |
story = generate_story(title) | |
images = generate_images(story) | |
audio = synthesize_audio(story) | |
video = generate_video(images, audio, story) | |
return video, story | |
iface = gr.Interface( | |
fn=generate_horror_video, | |
inputs=gr.Textbox(label="Gib den Titel deiner deutschen Gruselgeschichte ein"), | |
outputs=[ | |
gr.Video(label="Dein generiertes Horrorvideo"), | |
gr.Textbox(label="Generierte Geschichte") | |
], | |
title="Gruselige KI-Kurzgeschichten", | |
description="Gib einen Titel ein – KI erstellt eine deutsche Gruselgeschichte, Bilder, Stimme und Video (ohne Musik)." | |
) | |
if __name__ == "__main__": | |
iface.launch() |