upniso_ads / engine.py
eishit32's picture
Create engine.py
4e0c39e verified
Raw
History Blame Contribute Delete
4.32 kB
import os
import random
import requests
from huggingface_hub import InferenceClient
from moviepy.editor import *
from moviepy.config import change_settings
# specific config for ImageMagick on Linux/HF Spaces
change_settings({"IMAGEMAGICK_BINARY": "/usr/bin/convert"})
def get_env(key):
val = os.getenv(key)
if not val:
print(f"⚠️ Missing Env Var: {key}")
return val
# --- 1. AI WRITING ENGINE ---
def generate_script():
"""Generates the raw ad script using Mistral/Llama."""
token = get_env("HF_TOKEN")
client = InferenceClient(token=token)
# The Prompt: Aggressive, Gen Z, No fluff
prompt = """
ROLE: Marketing Director for Upniso (Gen Z Creator Brand).
TONE: Rebellious, High-Voltage, Anti-Corporate.
RULE: NO EMOJIS. NO HASHTAGS IN SCRIPT.
TASK: Write a 4-line video script + Metadata.
OUTPUT FORMAT: Return ONLY text separated by '||'.
Structure:
1. Hook (Shocking statement)
2. Pain (Why current life sucks)
3. Vision (Upniso is the answer)
4. Call to Action (Short)
5. Caption (For social media)
Example:
You are sleeping on your potential||The 9 to 5 is a cage||Break out and build your empire||Join Upniso now||Time to wake up. Link in bio.
"""
try:
response = client.text_generation(
prompt,
model="mistralai/Mistral-7B-Instruct-v0.2",
max_new_tokens=250,
temperature=0.85
)
# Parse logic
parts = response.split("||")
if len(parts) < 5:
# Fallback if AI hallucinates format
return {
"hook": "WAKE UP.",
"pain": "Your art deserves better.",
"vision": "Build with Upniso.",
"cta": "Join Us.",
"caption": "No more excuses."
}
return {
"hook": parts[0].strip(),
"pain": parts[1].strip(),
"vision": parts[2].strip(),
"cta": parts[3].strip(),
"caption": parts[4].strip()
}
except Exception as e:
print(f"LLM Error: {e}")
return None
# --- 2. VIDEO PRODUCTION ENGINE ---
def fetch_stock_video(query):
"""Downloads a video from Pexels."""
api_key = get_env("PEXELS_API_KEY")
headers = {'Authorization': api_key}
url = f"https://api.pexels.com/videos/search?query={query}&per_page=3&orientation=portrait"
try:
r = requests.get(url, headers=headers)
data = r.json()
video = random.choice(data['videos'])
# Get highest quality link
link = video['video_files'][0]['link']
filename = f"temp_{random.randint(1,1000)}.mp4"
with open(filename, 'wb') as f:
f.write(requests.get(link).content)
return filename
except Exception:
return None
def build_video(script):
"""Edits the video clips together with text."""
print("🎬 Starting Video Render...")
# 1. Fetch Visuals
clips = []
keywords = ["storm", "fire", "cyberpunk", "running"] # Aggressive keywords
texts = [script['hook'], script['pain'], script['vision'], script['cta']]
for i, text in enumerate(texts):
vid_file = fetch_stock_video(keywords[i])
if vid_file:
# Process Video
clip = VideoFileClip(vid_file).subclip(0, 3) # 3 sec per clip
clip = clip.resize(height=1280)
clip = clip.crop(x1=clip.w/2 - 360, width=720, height=1280) # 9:16 Aspect
# Create Text Overlay
# Note: Using default font to avoid errors, white text, black stroke
txt = TextClip(text.upper(), color='white', font="Liberation-Sans-Bold", fontsize=60, method='caption', size=(650, None))
txt = txt.set_pos('center').set_duration(3)
combined = CompositeVideoClip([clip, txt])
clips.append(combined)
# Clean up temp file
os.remove(vid_file)
if not clips:
return None
final = concatenate_videoclips(clips)
# Export
output_path = "daily_ad.mp4"
final.write_videofile(output_path, fps=24, codec='libx264', audio_codec='aac')
return output_path