Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import requests | |
| import edge_tts | |
| import asyncio | |
| import os | |
| import subprocess | |
| import shutil | |
| import uuid | |
| import nest_asyncio | |
| import arabic_reshaper | |
| from bidi.algorithm import get_display | |
| # Bada damar gudanar da async a cikin Streamlit | |
| nest_asyncio.apply() | |
| # --- TSARIN UI NA PROFESSIONAL --- | |
| st.set_page_config(page_title="A-Chiwar Video Generator", page_icon="π", layout="wide") | |
| st.markdown(""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@700&family=Amiri&display=swap'); | |
| .stApp { background-color: #050e18; color: #f0e8d0; } | |
| .main-title { | |
| font-family: 'Cinzel', serif; font-size: 3rem; text-align: center; | |
| color: #d4af37; text-shadow: 2px 2px #000; padding: 20px; | |
| } | |
| .stButton>button { | |
| background: linear-gradient(45deg, #b8942c, #f5e07a); | |
| color: black; font-weight: bold; border-radius: 10px; width: 100%; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.markdown('<div class="main-title">A-CHIWAR VIDEO GENERATOR</div>', unsafe_allow_html=True) | |
| # --- FOLDERS NA AIKI --- | |
| TMP_DIR = "temp_assets" | |
| os.makedirs(TMP_DIR, exist_ok=True) | |
| # --- FUNCTIONS NA TAIMAKO --- | |
| def clean_arabic(text): | |
| """Gyara rubutun Larabci don FFmpeg ya nuna shi yadda ya kamata""" | |
| reshaped = arabic_reshaper.reshape(text) | |
| return get_display(reshaped) | |
| def get_pexels_video(query, api_key): | |
| headers = {"Authorization": api_key} | |
| url = f"https://api.pexels.com/videos/search?query={query}&per_page=1&orientation=portrait" | |
| r = requests.get(url, headers=headers).json() | |
| if 'videos' in r and len(r['videos']) > 0: | |
| return r['videos'][0]['video_files'][0]['link'] | |
| return None | |
| # --- SIDEBAR (SETTINGS) --- | |
| with st.sidebar: | |
| st.header("π API Keys") | |
| groq_key = st.text_input("Groq API Key", type="password") | |
| pexels_key = st.text_input("Pexels API Key", type="password") | |
| st.header("βοΈ Settings") | |
| lang = st.selectbox("Language", ["Arabic", "English"]) | |
| duration = st.slider("Duration (Seconds)", 15, 60, 30) | |
| theme = st.selectbox("Visual Theme", ["Nature", "Masjid", "Islamic Art", "Abstract"]) | |
| voice_type = st.radio("Voice", ["Male", "Female"]) | |
| # --- STEP 1: GENERATE SCRIPT --- | |
| topic = st.text_input("Mene ne Topic din bidiyonka?", placeholder="Misali: Alherin Allah...") | |
| if 'script' not in st.session_state: | |
| st.session_state.script = "" | |
| if st.button("βοΈ Generate Script"): | |
| if not groq_key: | |
| st.error("Saka Groq API Key!") | |
| else: | |
| with st.spinner("Muna rubuta script..."): | |
| prompt = f"Write a powerful Islamic video script about {topic} in {lang}. Max {duration * 2} words. Output ONLY the script." | |
| res = requests.post("https://api.groq.com/openai/v1/chat/completions", | |
| headers={"Authorization": f"Bearer {groq_key}"}, | |
| json={"model": "llama-3.3-70b-versatile", "messages": [{"role": "user", "content": prompt}]}) | |
| st.session_state.script = res.json()['choices'][0]['message']['content'] | |
| # --- STEP 2: EDIT & RENDER --- | |
| if st.session_state.script: | |
| edited_script = st.text_area("Gyara Script din anan idan akwai bukatar hakan:", value=st.session_state.script, height=200) | |
| if st.button("π GENERATE MASTERPIECE"): | |
| if not pexels_key: | |
| st.error("Saka Pexels API Key!") | |
| else: | |
| with st.spinner("Injin A-Chiwar yana hada bidiyonka..."): | |
| uid = str(uuid.uuid4())[:6] | |
| audio_path = os.path.join(TMP_DIR, f"audio_{uid}.mp3") | |
| video_url = get_pexels_video(theme, pexels_key) | |
| final_output = f"A_Chiwar_{uid}.mp4" | |
| # 1. Generate Voice | |
| v_name = "ar-SA-HamedNeural" if lang == "Arabic" and voice_type == "Male" else "en-US-AndrewNeural" | |
| asyncio.run(edge_tts.Communicate(edited_script, v_name).save(audio_path)) | |
| # 2. Download Background Video | |
| video_path = os.path.join(TMP_DIR, f"bg_{uid}.mp4") | |
| with open(video_path, "wb") as f: | |
| f.write(requests.get(video_url).content) | |
| # 3. FFmpeg Rendering (Hada bidiyo, sauti, da Caption) | |
| display_text = clean_arabic(edited_script) if lang == "Arabic" else edited_script.replace("'", "") | |
| # Wannan command din yana hada komai lokaci daya | |
| cmd = ( | |
| f'ffmpeg -y -i {video_path} -i {audio_path} ' | |
| f'-vf "scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,' | |
| f'drawtext=text=\'{display_text[:50]}...\':fontcolor=white:fontsize=40:x=(w-text_w)/2:y=(h-text_h)/2:box=1:boxcolor=black@0.5" ' | |
| f'-c:v libx264 -c:a aac -shortest {final_output}' | |
| ) | |
| subprocess.run(cmd, shell=True) | |
| if os.path.exists(final_output): | |
| st.success("An gama hada bidiyon!") | |
| st.video(final_output) | |
| with open(final_output, "rb") as f: | |
| st.download_button("π₯ Download Video", f, file_name=final_output) | |
| # Cleanup | |
| shutil.rmtree(TMP_DIR) | |
| os.makedirs(TMP_DIR, exist_ok=True) | |