Spaces:
Running on Zero
Running on Zero
| #!/usr/bin/env python3 | |
| """ | |
| generate_moldovan_video_scripts.py — Moldovan Viral Video & Short-Form Comedy Studio | |
| Generates 30-60s viral video concepts for TikTok, Instagram Reels, and YouTube Shorts. | |
| Includes scene-by-scene storyboard prompts for FLUX.1 / Sora, voiceover scripts (Kokoro TTS), | |
| on-screen text hooks, and comedy timing. | |
| """ | |
| import os | |
| import sys | |
| import re | |
| import json | |
| import argparse | |
| from typing import List, Dict | |
| SKETCH_CONCEPTS = [ | |
| { | |
| "title": "Moldoveanul la Vama Leușeni — Bagajul Secret", | |
| "category": "Satiră Socială & Diasporă", | |
| "duration_seconds": 45, | |
| "hook_text": "Băi, ce găsește vameșul în portbagaj când zici 'n-am nimic de declarat'?!", | |
| "hashtags": ["#moldova", "#chisinau", "#vama", "#leuseni", "#moldoveniinitalia", "#comedy", "#prikol"], | |
| "scenes": [ | |
| { | |
| "scene_num": 1, | |
| "time_range": "0:00 - 0:05", | |
| "visual_prompt": "Cinematic close-up of a nervous Moldovan driver sitting in a dusty Volkswagen Passat B5 at the Leuseni border checkpoint, wearing a dark leather jacket, night atmosphere with fluorescent border lights.", | |
| "voiceover": "Ora 3 dimineața la vama Leușeni. Vameșul vine tacticos la geam și întreabă: 'Ceva interzis aveți?'", | |
| "on_screen_text": "POV: Treci vama la 3 dimineața 🛂", | |
| "sound_effect": "Tension build-up, car engine idling" | |
| }, | |
| { | |
| "scene_num": 2, | |
| "time_range": "0:05 - 0:15", | |
| "visual_prompt": "Open trunk of the car packed to the brim with giant woven plastic market bags (kuleoace), a 20-liter glass demijohn wrapped in wicker full of red wine, and foil-wrapped packages.", | |
| "voiceover": "Și tu zici: 'Doamne ferește, dom' șef, două kuleoace cu haine și-o sticluță de apă!'... Între timp în portbagaj: 30 de litri de vin de casă, 4 găini tăiate de mama, 15 borcane de compot de cireșe și o găleată de brânză de oi!", | |
| "on_screen_text": "'Doar 2 kuleoace cu haine, dom' șef!' 😂", | |
| "sound_effect": "Record scratch, comedic dramatic brass" | |
| }, | |
| { | |
| "scene_num": 3, | |
| "time_range": "0:15 - 0:30", | |
| "visual_prompt": "Close-up of the border guard smiling knowingly while tapping the demijohn of red wine with his pen.", | |
| "voiceover": "Vameșul se uită lung la damigeană, o bate ușor cu pixul și zice: 'Măi băiatule, asta-i apă sfințită sau e cabernet din '22?'", | |
| "on_screen_text": "Vameșul expert în vinuri 🍷", | |
| "sound_effect": "Clinking glass sound" | |
| }, | |
| { | |
| "scene_num": 4, | |
| "time_range": "0:30 - 0:45", | |
| "visual_prompt": "The driver quickly offering a warm wrapped placinta with homemade cheese from the glove box with a huge friendly smile.", | |
| "voiceover": "Koroce, n-ai cum să nu scoți o plăcintă caldă cu brânză de oi pe loc! 'Hai davai, dom' vameș, luați o plăcintă și drum bun să avem!' Niciun scanner din lume nu rezistă la plăcinta moldovenească!", | |
| "on_screen_text": "Plăcinta rezolvă orice problemă! 🥧✨", | |
| "sound_effect": "Fast energetic Moldovan accordion festive outro" | |
| } | |
| ] | |
| }, | |
| { | |
| "title": "Babușca la Chișinău — 'De ce ești așa slab, maică?!'", | |
| "category": "Familie & Gastronomie", | |
| "duration_seconds": 40, | |
| "hook_text": "Ai slăbit 100 de grame? Babușca de la sat intră în alertă de gradul 0!", | |
| "hashtags": ["#moldova", "#babusca", "#zeama", "#sat", "#chisinau", "#mamaia", "#relatable"], | |
| "scenes": [ | |
| { | |
| "scene_num": 1, | |
| "time_range": "0:00 - 0:05", | |
| "visual_prompt": "Traditional Moldovan grandmother wearing a floral headscarf (batic) looking with utter shock and concern through a wooden village gate.", | |
| "voiceover": "Ai venit la sat după o lună de stat la Chișinău. Babușca te vede la poartă și-și pune mâinile-n cap!", | |
| "on_screen_text": "Când ajungi la sat după o lună 👵🏻🚨", | |
| "sound_effect": "Dramatic soap-opera zoom sound" | |
| }, | |
| { | |
| "scene_num": 2, | |
| "time_range": "0:05 - 0:20", | |
| "visual_prompt": "Steaming hot bowl of chicken noodle soup (zeama) with fresh dill and hot chili pepper on a rustic embroidered tablecloth, accompanied by huge chunks of homemade bread.", | |
| "voiceover": "'Doamne, maică, numai os și piele ai rămas! Ce vă dau ăștia la Chișinău să mâncați, pietre?' În fix 4 minute pe masă apare un lighean de zeamă fierbinte, o mămăligă cât roata carului și-un castron de friptură!", | |
| "on_screen_text": "Tratamentul de urgență: ZEAMĂ + MĂMĂLIGĂ 🍲", | |
| "sound_effect": "Sizzling meat in cast iron cauldron" | |
| }, | |
| { | |
| "scene_num": 3, | |
| "time_range": "0:20 - 0:40", | |
| "visual_prompt": "Young guy sitting at the table unable to move, while grandmother holds another plate of 5 giant cheese pies (placinte) trying to force-feed him.", | |
| "voiceover": "Zici: 'Babușcă, gata, nu mai pot, crap!'. Iar ea: 'Mai mănâncă 3 plăcinte că te ia vântul pe stradă!'... Pleci de la sat cu 8 kile în plus și 4 pungi de mâncare în portbagaj!", | |
| "on_screen_text": "Nu există 'm-am săturat' la sat! 😂", | |
| "sound_effect": "Belly full groan, comedic folk trumpet" | |
| } | |
| ] | |
| } | |
| ] | |
| def generate_video_scripts(output_dir: str): | |
| """Generate structured viral script files.""" | |
| os.makedirs(output_dir, exist_ok=True) | |
| for idx, sketch in enumerate(SKETCH_CONCEPTS, 1): | |
| file_slug = sketch["title"].lower().replace(" ", "_").replace("—", "").replace("-", "_").replace("'", "").replace("ș", "s").replace("ț", "t").replace("ă", "a").replace("î", "i").replace("?", "") | |
| file_slug = re.sub(r'[^a-z0-9_]', '', file_slug) | |
| md_content = f"# 🎬 {sketch['title']}\n\n" | |
| md_content += f"**Categorie:** {sketch['category']} | **Durată:** ~{sketch['duration_seconds']} secunde\n\n" | |
| md_content += f"### 🔥 Hook (Primele 3 secunde):\n> \"{sketch['hook_text']}\"\n\n" | |
| md_content += f"### 🏷️ Hashtags:\n`{' '.join(sketch['hashtags'])}`\n\n" | |
| md_content += "---\n\n## 🎥 Storyboard & Script Scenă cu Scenă\n\n" | |
| for sc in sketch["scenes"]: | |
| md_content += f"### Scena {sc['scene_num']} ({sc['time_range']})\n" | |
| md_content += f"* **Visual Prompt (FLUX.1 / Sora):** `{sc['visual_prompt']}`\n" | |
| md_content += f"* **Voiceover (Kokoro TTS):** \"{sc['voiceover']}\"\n" | |
| md_content += f"* **On-Screen Text:** `{sc['on_screen_text']}`\n" | |
| md_content += f"* **Sound Effect:** *{sc['sound_effect']}*\n\n" | |
| md_path = os.path.join(output_dir, f"{file_slug}.md") | |
| with open(md_path, 'w', encoding='utf-8') as f: | |
| f.write(md_content) | |
| json_path = os.path.join(output_dir, f"{file_slug}.json") | |
| with open(json_path, 'w', encoding='utf-8') as f: | |
| json.dump(sketch, f, ensure_ascii=False, indent=2) | |
| print(f"[✓] Generated Video Concept: {sketch['title']} -> {md_path}") | |
| def main(): | |
| default_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data/generated_video_scripts") | |
| parser = argparse.ArgumentParser(description="Generate Moldovan Short-Form Video Scripts") | |
| parser.add_argument("--output-dir", default=default_dir, help="Output directory") | |
| args = parser.parse_args() | |
| generate_video_scripts(args.output_dir) | |
| if __name__ == "__main__": | |
| main() | |