|
|
|
import gradio as gr |
|
import numpy as np |
|
import torch |
|
import random |
|
from diffusers import DiffusionPipeline |
|
from PIL import Image, ImageDraw, ImageFont |
|
|
|
|
|
SUPPORTERS = random.randint(50, 200) |
|
KO_FI_LINK = "https://ko-fi.com/fecolywill" |
|
GA_TRACKING_ID = "G-XXXXXXXXXX" |
|
|
|
|
|
class Watermarker: |
|
def __init__(self): |
|
self.font = ImageFont.load_default() |
|
self.color = (255, 255, 255, 128) |
|
self.position = "bottom-right" |
|
self.text = "Made with AI Film Studio" |
|
|
|
def apply(self, frames): |
|
watermarked_frames = [] |
|
for frame in frames: |
|
img = Image.fromarray(frame) |
|
draw = ImageDraw.Draw(img, "RGBA") |
|
text_width = draw.textlength(self.text, font=self.font) |
|
|
|
if self.position == "bottom-right": |
|
x = img.width - text_width - 20 |
|
y = img.height - 30 |
|
elif self.position == "top-left": |
|
x, y = 20, 20 |
|
else: |
|
x = (img.width - text_width) // 2 |
|
y = (img.height - 30) // 2 |
|
|
|
draw.text((x, y), self.text, fill=self.color, font=self.font) |
|
watermarked_frames.append(np.array(img)) |
|
return np.stack(watermarked_frames) |
|
|
|
watermarker = Watermarker() |
|
|
|
|
|
def generate_video(prompt): |
|
|
|
pipe = DiffusionPipeline.from_pretrained( |
|
"cerspense/zeroscope_v2_576w", |
|
torch_dtype=torch.float16 |
|
) |
|
|
|
|
|
frames = pipe( |
|
prompt, |
|
num_frames=24, |
|
height=320, |
|
width=576 |
|
).frames |
|
|
|
|
|
return (np.stack(watermarker.apply(frames))), 12 |
|
|
|
|
|
analytics_js = f""" |
|
<script async src="https://www.googletagmanager.com/gtag/js?id={GA_TRACKING_ID}"></script> |
|
<script> |
|
window.dataLayer = window.dataLayer || []; |
|
function gtag(){{dataLayer.push(arguments);}} |
|
gtag('js', new Date()); |
|
gtag('config', '{GA_TRACKING_ID}'); |
|
|
|
function trackAction(action, label) {{ |
|
gtag('event', action, {{ |
|
'event_category': 'engagement', |
|
'event_label': label, |
|
'value': 1 |
|
}}); |
|
}} |
|
</script> |
|
""" |
|
|
|
|
|
support_html = f""" |
|
<div style="border-top:1px solid #e6e6e6; padding:25px; text-align:center; margin-top:30px; background:#f9f9f9; border-radius:8px;"> |
|
<h3 style="margin-bottom:10px;">β€οΈ Support This Project</h3> |
|
<p style="margin-bottom:15px;">Enjoying this free tool? Help me add more features!</p> |
|
<a href="{KO_FI_LINK}" target="_blank" onclick="trackAction('support', 'kofi_click')" style="padding:10px 20px; background:#29abe0; color:white; border-radius:5px; text-decoration:none; font-weight:bold; display:inline-block; margin-bottom:15px;"> |
|
β Buy Me a Coffee |
|
</a> |
|
<p style="color:#666; font-size:0.9em;">π {SUPPORTERS}+ creators have supported!</p> |
|
</div> |
|
""" |
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft(), title="AI Film Studio Pro") as app: |
|
|
|
gr.HTML(analytics_js) |
|
|
|
|
|
gr.Markdown("# π¬ AI Film Studio Pro") |
|
gr.Markdown("Generate professional videos with AI - **no experience needed!**") |
|
|
|
|
|
with gr.Tab("π₯ Video Creator"): |
|
with gr.Row(): |
|
prompt = gr.Textbox( |
|
label="Describe Your Scene", |
|
placeholder="A cyberpunk detective chases an android through neon streets...", |
|
lines=3 |
|
) |
|
style = gr.Dropdown( |
|
["Cinematic", "Anime", "Noir", "Cyberpunk"], |
|
label="Visual Style", |
|
value="Cinematic" |
|
) |
|
|
|
generate_btn = gr.Button("β¨ Generate Video", variant="primary") |
|
|
|
|
|
video = gr.Video( |
|
label="Your Generated Video", |
|
show_download_button=True, |
|
interactive=False |
|
) |
|
|
|
|
|
download_js = """ |
|
<script> |
|
document.querySelector('button[aria-label="Download"]').addEventListener('click', () => { |
|
trackAction('download', 'video_mp4'); |
|
alert('Video downloaded! Consider supporting to unlock HD versions π'); |
|
}); |
|
</script> |
|
""" |
|
gr.HTML(download_js) |
|
|
|
|
|
with gr.Accordion("βοΈ Watermark Settings", open=False): |
|
watermark_text = gr.Textbox( |
|
label="Watermark Text", |
|
value="Made with AI Film Studio" |
|
) |
|
watermark_color = gr.ColorPicker( |
|
label="Color", |
|
value="#ffffff" |
|
) |
|
watermark_opacity = gr.Slider( |
|
0, 100, value=50, |
|
label="Opacity (%)" |
|
) |
|
watermark_position = gr.Dropdown( |
|
["bottom-right", "top-left", "center"], |
|
label="Position", |
|
value="bottom-right" |
|
) |
|
|
|
def update_watermark(text, color, opacity, position): |
|
r, g, b = tuple(int(color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) |
|
watermarker.text = text |
|
watermarker.color = (r, g, b, int(255 * (opacity/100))) |
|
watermarker.position = position |
|
return "Watermark settings updated!" |
|
|
|
update_btn = gr.Button("Update Watermark") |
|
update_btn.click( |
|
fn=update_watermark, |
|
inputs=[watermark_text, watermark_color, watermark_opacity, watermark_position], |
|
outputs=gr.Textbox(visible=False) |
|
) |
|
|
|
|
|
gr.HTML(support_html) |
|
|
|
|
|
generate_btn.click( |
|
fn=generate_video, |
|
inputs=[prompt], |
|
outputs=video |
|
).then( |
|
lambda: gr.HTML("<script>trackAction('generation', 'video_created')</script>"), |
|
outputs=None |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
app.launch(debug=True) |