Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import requests | |
| import time | |
| import base64 | |
| from pathlib import Path | |
| # Page config | |
| st.set_page_config( | |
| page_title="Vidsimplify - AI Video Generator", | |
| page_icon="π¬", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for better aesthetics | |
| st.markdown(""" | |
| <style> | |
| .stApp { | |
| background-color: #0e1117; | |
| color: #fafafa; | |
| } | |
| .stButton>button { | |
| background-color: #ff4b4b; | |
| color: white; | |
| border-radius: 20px; | |
| padding: 10px 24px; | |
| font-weight: bold; | |
| border: none; | |
| transition: all 0.3s ease; | |
| } | |
| .stButton>button:hover { | |
| background-color: #ff3333; | |
| transform: scale(1.05); | |
| } | |
| .stTextInput>div>div>input { | |
| border-radius: 10px; | |
| } | |
| .stTextArea>div>div>textarea { | |
| border-radius: 10px; | |
| } | |
| .css-1d391kg { | |
| padding-top: 3rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Sidebar | |
| with st.sidebar: | |
| st.title("π¬ Vidsimplify") | |
| st.markdown("---") | |
| st.markdown("### Configuration") | |
| api_url = st.text_input("API URL", value="http://localhost:8003") | |
| st.markdown("### Settings") | |
| quality = st.selectbox("Quality", ["low", "medium", "high", "ultra"], index=2) | |
| category = st.selectbox("Category", ["tech_system", "product_startup", "mathematical"], index=0) | |
| st.markdown("---") | |
| st.markdown("### About") | |
| st.info("Generate educational animation videos from text, blogs, or PDFs using Manim and AI.") | |
| # Main content | |
| st.title("AI Video Generator") | |
| st.markdown("Turn your content into engaging animations in minutes.") | |
| # Input tabs | |
| tab1, tab2, tab3 = st.tabs(["π Text / Script", "π Blog / URL", "π PDF Document"]) | |
| input_type = "text" | |
| input_data = "" | |
| with tab1: | |
| st.header("Text Input") | |
| st.markdown("Paste your script, blog post, or long text here.") | |
| text_input = st.text_area("Content", height=300, placeholder="Enter your text here...") | |
| if text_input: | |
| input_type = "text" | |
| input_data = text_input | |
| with tab2: | |
| st.header("URL Input") | |
| st.markdown("Enter the URL of a blog post or article.") | |
| url_input = st.text_input("URL", placeholder="https://example.com/blog-post") | |
| if url_input: | |
| input_type = "url" | |
| input_data = url_input | |
| with tab3: | |
| st.header("PDF Upload") | |
| st.markdown("Upload a PDF document to generate a video from.") | |
| uploaded_file = st.file_uploader("Choose a PDF file", type="pdf") | |
| if uploaded_file: | |
| input_type = "pdf" | |
| # Convert PDF to base64 | |
| bytes_data = uploaded_file.getvalue() | |
| base64_pdf = base64.b64encode(bytes_data).decode('utf-8') | |
| input_data = base64_pdf | |
| # Generate button | |
| if st.button("Generate Video", type="primary", use_container_width=True): | |
| if not input_data: | |
| st.error("Please provide input data.") | |
| else: | |
| try: | |
| with st.spinner("Submitting job to API..."): | |
| payload = { | |
| "input_type": input_type, | |
| "input_data": input_data, | |
| "quality": quality, | |
| "category": category | |
| } | |
| response = requests.post(f"{api_url}/api/videos", json=payload) | |
| if response.status_code == 200: | |
| job_data = response.json() | |
| job_id = job_data["job_id"] | |
| st.success(f"Job started! ID: {job_id}") | |
| # Polling for status | |
| progress_bar = st.progress(0) | |
| status_text = st.empty() | |
| video_placeholder = st.empty() | |
| while True: | |
| status_response = requests.get(f"{api_url}/api/jobs/{job_id}") | |
| if status_response.status_code == 200: | |
| status_data = status_response.json() | |
| status = status_data["status"] | |
| progress = status_data.get("progress", {}) | |
| percentage = progress.get("percentage", 0) | |
| message = progress.get("message", "Processing...") | |
| progress_bar.progress(percentage / 100) | |
| status_text.info(f"Status: {status.upper()} - {message}") | |
| if status == "completed": | |
| st.balloons() | |
| status_text.success("Video generation completed!") | |
| # Display video | |
| video_url = f"{api_url}/api/videos/{job_id}" | |
| st.video(video_url) | |
| break | |
| elif status == "failed": | |
| error_msg = status_data.get("error", "Unknown error") | |
| status_text.error(f"Job failed: {error_msg}") | |
| break | |
| time.sleep(2) | |
| else: | |
| st.error(f"Failed to start job: {response.text}") | |
| except requests.exceptions.ConnectionError: | |
| st.error(f"Could not connect to API at {api_url}. Is the server running?") | |
| except Exception as e: | |
| st.error(f"An error occurred: {str(e)}") | |
| # Footer | |
| st.markdown("---") | |
| st.markdown("Built with Streamlit and Manimator") | |