import os import gradio as gr import subprocess import cv2 from PIL import Image import google.generativeai as genai import base64 # ========== SETUP ========== def set_api_key(api_key): os.environ["GOOGLE_API_KEY"] = api_key genai.configure(api_key=api_key) # ========== TEXT TO IMAGE ========== def text_to_image(api_key, prompt, image_file, resolution): try: set_api_key(api_key) model = genai.GenerativeModel("imagen-3.0") if image_file: final_prompt = {"text": prompt, "image": Image.open(image_file)} else: final_prompt = prompt result = model.generate_content(final_prompt) if not result.candidates: return None, "❌ Gagal: tiada kandidat dihasilkan" image_bytes = result.candidates[0].content.parts[0].inline_data.data fname = "output_img.png" with open(fname, "wb") as f: f.write(base64.b64decode(image_bytes)) return fname, "✅ Gambar berjaya dihasilkan!" except Exception as e: return None, f"❌ Error: {str(e)}" # ========== SHORT VIDEO ========== def text_to_video(api_key, prompt, image_file, duration, aspect_ratio, resolution): try: set_api_key(api_key) model = genai.GenerativeModel("veo-3") # aspect ratio & res if aspect_ratio == "9:16": res = {"width": 720 if resolution == "720p" else 1080, "height": 1280 if resolution == "720p" else 1920} else: res = {"width": 1280 if resolution == "720p" else 1920, "height": 720 if resolution == "720p" else 1080} if image_file: final_prompt = {"text": prompt, "image": Image.open(image_file)} else: final_prompt = prompt result = model.generate_content({ "text": prompt, "config": { "duration_seconds": int(duration), "fps": 12, "video": {"width": res["width"], "height": res["height"]} } }) if not result.candidates: return None, "❌ Gagal: tiada kandidat video dihasilkan" video_bytes = result.candidates[0].content.parts[0].inline_data.data fname = "output_vid.mp4" with open(fname, "wb") as f: f.write(base64.b64decode(video_bytes)) return fname, "✅ Video berhasil dibuat!" except Exception as e: return None, f"❌ Error: {str(e)}" # ========== LONG VIDEO ========== def auto_segment_long_video(api_key, prompt, start_img, num_segments, duration_each, aspect_ratio, resolution): try: set_api_key(api_key) model = genai.GenerativeModel("veo-3") if aspect_ratio == "9:16": res = {"width": 720 if resolution == "720p" else 1080, "height": 1280 if resolution == "720p" else 1920} else: res = {"width": 1280 if resolution == "720p" else 1920, "height": 720 if resolution == "720p" else 1080} words = prompt.split() chunk_size = max(1, len(words) // num_segments) seg_prompts = [" ".join(words[i:i+chunk_size]) for i in range(0, len(words), chunk_size)][:num_segments] carry_image = Image.open(start_img) if start_img else None segment_files = [] for idx, text in enumerate(seg_prompts): if carry_image: final_prompt = {"text": text, "image": carry_image} else: final_prompt = text result = model.generate_content({ "text": text, "config": { "duration_seconds": int(duration_each), "fps": 12, "video": {"width": res["width"], "height": res["height"]} } }) if not result.candidates: return None, f"❌ Gagal buat segmen {idx}" video_bytes = result.candidates[0].content.parts[0].inline_data.data fname = f"seg_{idx}.mp4" with open(fname, "wb") as f: f.write(base64.b64decode(video_bytes)) segment_files.append(fname) cap = cv2.VideoCapture(fname) cap.set(cv2.CAP_PROP_POS_FRAMES, cap.get(cv2.CAP_PROP_FRAME_COUNT) - 1) ret, frame = cap.read() cap.release() if ret: framefile = f"carry_{idx}.jpg" cv2.imwrite(framefile, frame) carry_image = Image.open(framefile) # gabung semua segmen list_file = "segments.txt" with open(list_file, "w") as f: for seg in segment_files: f.write(f"file '{seg}'\n") final_out = "final_long.mp4" subprocess.run( ["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", list_file, "-c", "copy", final_out], check=True ) return final_out, "✅ Video panjang berhasil dibuat!" except Exception as e: return None, f"❌ Error: {str(e)}" # ========== UI ========== with gr.Blocks(css=""" body {background: linear-gradient(160deg,#0f0c29,#302b63,#24243e);} .gradio-container {color:white;} h1,h2,h3,h4,label {color:white !important;} button {background: linear-gradient(90deg,#6a11cb,#2575fc) !important; color:white !important;} """) as demo: gr.HTML("