Spaces:
Runtime error
Runtime error
File size: 5,081 Bytes
a312ba3 d444fec a312ba3 a3186c3 5740d5f 85ade34 a312ba3 d444fec 80e5d31 69cd013 85ade34 5740d5f 85ade34 5740d5f 85ade34 5740d5f 85ade34 5740d5f 85ade34 a3186c3 69cd013 7bd3d0d d444fec 80e5d31 d444fec ebe0347 80e5d31 7bd3d0d 85ade34 ebe0347 5740d5f 85ade34 5740d5f d444fec 85ade34 69cd013 d444fec 69cd013 5740d5f 69cd013 ebe0347 85ade34 69cd013 ebe0347 69cd013 5740d5f 85ade34 5740d5f d444fec 85ade34 d444fec 85ade34 80e5d31 d444fec a312ba3 d444fec 98dbe18 | 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 | import gradio as gr
import subprocess
import json
import os
import requests
import urllib.parse
import time
from huggingface_hub import HfApi, InferenceClient
HF_TOKEN = os.getenv("HF_WRITE_TOKEN")
api = HfApi(token=HF_TOKEN)
DATASET_ID = "oviet711/render-factory"
def generate_ai_image(keyword, chunk_id):
print(f"🎨 [TIER 1] Meminta Visual dari Pollinations: {keyword}")
encoded_prompt = urllib.parse.quote(f"cinematic photography, ultra realistic, highly detailed, {keyword}, dark moody lighting, vertical")
url = f"https://image.pollinations.ai/prompt/{encoded_prompt}?width=1080&height=1920&nologo=true"
# TIER 1: Coba Pollinations AI
for attempt in range(2):
try:
response = requests.get(url, stream=True, timeout=10)
if response.status_code == 200:
bg_filename = f"bg_{chunk_id}.png"
with open(bg_filename, 'wb') as f:
for chunk in response.iter_content(1024):
f.write(chunk)
return bg_filename
except Exception as e:
print(f"⚠️ Pollinations batuk (Percobaan {attempt+1}): {e}")
time.sleep(1)
# TIER 2: Jika Pollinations Mati, otomatis pakai Hugging Face FLUX
print("🔄 [TIER 2] Beralih ke Hugging Face FLUX API...")
try:
client = InferenceClient(model="black-forest-labs/FLUX.1-schnell", token=HF_TOKEN)
prompt = f"cinematic shot, photorealistic, vertical 9:16, {keyword}, dark and moody lighting, masterpiece"
image = client.text_to_image(prompt)
bg_filename = f"bg_{chunk_id}.png"
image.save(bg_filename)
return bg_filename
except Exception as e:
print(f"⚠️ TIER 2 Gagal (Server HF Penuh): {e}")
# TIER 3: Jika semua gagal, return None (FFmpeg akan buat layar hitam)
return None
# HAPUS BARIS INI: import spaces (di bagian atas file)
# HAPUS BARIS INI: @spaces.GPU
def render_worker(json_data):
try:
data = json.loads(json_data)
chunk_id = data.get('chunk_id', '000')
text = data.get('text', 'Teks kosong')
keyword = data.get('keyword', 'fresh juice')
# ... (Sisa kode di bawahnya tetap sama persis, jangan diubah) ...
# LOGIKA DINAMIS: Kamera & Warna berganti berdasarkan ID potongan
cid = int(chunk_id)
# 1. Rotasi Efek Kamera (Zoompan)
camera_effects = [
"zoompan=z='min(zoom+0.0015,1.15)':d=500:s=1080x1920", # Maju perlahan ke tengah
"zoompan=z='min(zoom+0.0015,1.15)':y='0':d=500:s=1080x1920", # Maju perlahan ke atas
"zoompan=z='min(zoom+0.0015,1.15)':y='ih':d=500:s=1080x1920" # Maju perlahan ke bawah
]
selected_camera = camera_effects[cid % len(camera_effects)]
# 2. Rotasi Warna Subtitle (Format BGR: Kuning, Cyan, Putih)
text_colors = ["&H00FFFF", "&HFFFF00", "&HFFFFFF"]
selected_color = text_colors[cid % len(text_colors)]
# Audio
audio_file = f"audio_{chunk_id}.mp3"
vtt_file = f"sub_{chunk_id}.vtt"
subprocess.run([
"edge-tts", "--voice", "id-ID-GadisNeural", "--rate", "+15%",
"--text", text, "--write-media", audio_file, "--write-subtitles", vtt_file
], check=True)
# Visual
bg_image = generate_ai_image(keyword, chunk_id)
output_filename = f"chunk_{chunk_id}.mp4"
if bg_image:
cmd = [
"ffmpeg", "-y",
"-loop", "1", "-framerate", "30",
"-i", bg_image,
"-i", audio_file,
# Memasukkan Kamera Dinamis dan Warna Dinamis!
"-vf", f"scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1:1,{selected_camera},subtitles={vtt_file}:force_style='FontSize=20,PrimaryColour={selected_color},OutlineColour=&H000000,BorderStyle=1,Outline=2,Shadow=1,Alignment=2,MarginV=450'",
"-c:v", "libx264", "-c:a", "aac",
"-shortest", "-pix_fmt", "yuv420p", output_filename
]
else:
cmd = [
"ffmpeg", "-y",
"-f", "lavfi", "-i", "color=c=black:s=1080x1920:d=30",
"-i", audio_file,
"-vf", f"subtitles={vtt_file}:force_style='FontSize=20,PrimaryColour={selected_color},OutlineColour=&H000000,BorderStyle=1,Outline=2,Shadow=1,Alignment=2,MarginV=450'",
"-c:v", "libx264", "-c:a", "aac",
"-shortest", output_filename
]
subprocess.run(cmd, check=True)
api.upload_file(
path_or_fileobj=output_filename, path_in_repo=f"chunks/{output_filename}",
repo_id=DATASET_ID, repo_type="dataset"
)
return f"✅ SUKSES Chunk {chunk_id} (Efek Kamera: {cid%3})"
except Exception as e:
return f"❌ ERROR: {str(e)}"
demo = gr.Interface(fn=render_worker, inputs="text", outputs="text")
demo.launch() |