app-tgljvp-56 / src /streamlit_app.py
Gertie01's picture
Upload src/streamlit_app.py with huggingface_hub
070dbbc verified
=== requirements.txt ===
streamlit
Pillow
=== config.py ===
import os
# --- General Configuration ---
APP_TITLE = "Sora 2 Simulator: Text & Image to Video Generation"
ANYCODER_LINK = "https://huggingface.co/spaces/akhaliq/anycoder"
ANYCODER_TEXT = "Built with anycoder"
# --- Generation Parameters ---
MIN_DURATION_S = 4
MAX_DURATION_S = 120
DEFAULT_DURATION_S = 30
GENERATION_COST_PER_SECOND = 0.05 # Mock cost
# --- Mock Output Configuration ---
# NOTE: Since actual binary files cannot be generated or shipped,
# we use mock placehoolder URLs/data.
MOCK_VIDEO_URL = "https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" # Public domain sample video
MOCK_AUDIO_DATA = "placeholder_audio.mp3"
# Mock audio data (Base64 encoded silence or small placeholder)
# In a real app, this would be a loaded audio file.
# Using a descriptive placeholder here for pure Python execution.
MOCK_AUDIO_DESCRIPTION = "Simulated high-fidelity audio track generated based on prompt."
# --- UI Texts ---
DISCLAIMER = (
"🚨 **IMPORTANT SIMULATION NOTICE:** The actual OpenAI Sora 2 model is not publicly available. "
"This application is a sophisticated simulation demonstrating the expected capabilities and workflow "
"of a next-generation video generation interface. Video output is a public domain placeholder."
)
=== utils.py ===
import time
import random
from config import MOCK_VIDEO_URL, MOCK_AUDIO_DESCRIPTION
def simulate_video_generation(prompt: str, duration_s: int, generate_audio: bool) -> dict:
"""
Simulates the intensive process of generating a video using a large AI model.
The mock duration is proportional to the requested video length.
"""
# Calculate simulated generation time (e.g., 0.5s per 10 seconds of video)
base_time = 3.0
time_per_second = 0.5
simulated_delay = base_time + (duration_s / 10 * time_per_second)
# Cap the delay for user experience
if simulated_delay > 15:
simulated_delay = 15 + random.uniform(0, 5) # Max 20s simulation
time.sleep(simulated_delay)
# Mock generation metadata
output = {
"status": "success",
"video_url": MOCK_VIDEO_URL,
"duration_s": duration_s,
"prompt_used": prompt,
"model_version": "Sora 2.1 (Simulated)",
"cost": round(duration_s * 0.05 + random.uniform(0.5, 1.5), 2), # Mock Cost calculation
"audio_description": MOCK_AUDIO_DESCRIPTION if generate_audio else None
}
return output
=== streamlit_app.py ===
import streamlit as st
from PIL import Image
import io
from config import (
APP_TITLE, ANYCODER_LINK, ANYCODER_TEXT,
MIN_DURATION_S, MAX_DURATION_S, DEFAULT_DURATION_S,
GENERATION_COST_PER_SECOND, DISCLAIMER
)
from utils import simulate_video_generation
# --- Configuration and Setup ---
st.set_page_config(
page_title=APP_TITLE,
layout="wide",
initial_sidebar_state="expanded"
)
# Initialize Session State
if 'generation_output' not in st.session_state:
st.session_state.generation_output = None
if 'is_running' not in st.session_state:
st.session_state.is_running = False
def clear_output():
"""Clears the previous generation results."""
st.session_state.generation_output = None
def handle_generation(prompt, image_file, duration_s, generate_audio):
"""Handles the submission and simulation process."""
if st.session_state.is_running:
st.warning("A generation task is already running. Please wait.")
return
st.session_state.is_running = True
clear_output()
input_prompt = prompt
if image_file:
# Simulate processing the image input
input_prompt = f"Image-to-Video: {image_file.name}. Prompt: {prompt}"
try:
# Display feedback and run simulation
with st.spinner(f"Generating high-fidelity video sequence ({duration_s}s)... This may take up to 20 seconds."):
output = simulate_video_generation(input_prompt, duration_s, generate_audio)
st.session_state.generation_output = output
st.balloons()
st.success("Video generation complete!")
except Exception as e:
st.error(f"An error occurred during simulation: {e}")
finally:
st.session_state.is_running = False
st.rerun()
# --- Sidebar UI ---
with st.sidebar:
st.title("Sora 2 Controls")
st.markdown(
f"""
**Maximum Duration:** {MAX_DURATION_S // 60}m {MAX_DURATION_S % 60}s
**Input Modes:** Text-to-Video, Image-to-Video
"""
)
# Custom CSS for the sidebar link
st.markdown(
f"""
<style>
.footer-link {{
font-size: 0.8rem;
color: #888888;
margin-top: 15px;
}}
</style>
<div class="footer-link">
<a href="{ANYCODER_LINK}" target="_blank">{ANYCODER_TEXT}</a>
</div>
""",
unsafe_allow_html=True
)
# --- Main Application UI ---
st.markdown(f"## {APP_TITLE}")
st.caption(DISCLAIMER)
st.divider()
# Input Form
with st.form("sora_generation_form", clear_on_submit=False):
col1, col2 = st.columns([3, 1])
with col1:
prompt = st.text_area(
"🎬 Describe your desired scene (Text-to-Video)",
placeholder="A golden retriever wearing a tiny chef's hat, baking bread on a cloud, cinematic 8K, highly detailed.",
height=100
)
with col2:
image_file = st.file_uploader(
"🖼️ Upload starting image (Image-to-Video)",
type=["png", "jpg", "jpeg"],
help="Optional: Start the video generation from a specific image."
)
if image_file:
st.image(image_file, caption="Input Image Preview", use_column_width=True)
st.subheader("Generation Settings")
settings_col1, settings_col2, settings_col3 = st.columns(3)
with settings_col1:
video_duration = st.slider(
"⏱️ Video Duration (seconds)",
min_value=MIN_DURATION_S,
max_value=MAX_DURATION_S,
value=DEFAULT_DURATION_S,
step=1,
help=f"Generates videos from {MIN_DURATION_S}s up to 2 minutes."
)
with settings_col2:
generate_audio = st.checkbox(
"🔊 Generate Realistic Audio Track",
value=True,
help="Sora 2 includes synchronized, high-fidelity audio generation."
)
with settings_col3:
# Mock Cost Display
mock_cost = round(video_duration * GENERATION_COST_PER_SECOND, 2)
st.metric(
label="Estimated Token Cost (Mock)",
value=f"${mock_cost:.2f}",
delta=f"${GENERATION_COST_PER_SECOND} / second"
)
st.markdown("---")
# Disable button if inputs are missing
is_disabled = not (prompt or image_file) or st.session_state.is_running
submit_button = st.form_submit_button(
label="⚡ Generate Video (Simulated)",
type="primary",
disabled=is_disabled
)
if submit_button:
if not prompt and image_file:
st.warning("Please provide a text prompt to guide the video generation, even if uploading an image.")
elif not prompt and not image_file:
st.error("Please provide either a text description or an image file to start.")
else:
handle_generation(prompt, image_file, video_duration, generate_audio)
# --- Output Display ---
if st.session_state.generation_output:
output = st.session_state.generation_output
st.subheader("🎥 Sora 2 Simulated Output")
st.info(f"Generated successfully in {output['duration_s']} seconds using **{output['model_version']}**.")
# Layout for metadata and video
output_col1, output_col2 = st.columns([1, 2])
with output_col1:
st.markdown("**Generation Metadata**")
st.json({
"Prompt Input": output['prompt_used'][:100] + "...",
"Output Duration": f"{output['duration_s']} seconds",
"Simulated Cost": f"${output['cost']:.2f}",
})
st.download_button(
label="⬇️ Download Video (Mock File)",
data="This is a simulated download link.",
file_name="sora_output_simulated.mp4",
mime="text/plain",
type="secondary"
)
with output_col2:
st.markdown("### Video Output (Public Placeholder)")
st.video(output['video_url'], format="video/mp4", start_time=0)
if output['audio_description']:
st.markdown("### Audio Track")
st.markdown(f"**Description:** {output['audio_description']}")
# Streamlit audio component using a simple placeholder representation
st.audio(data=b'', format="audio/mp3", loop=False)
st.caption("Audio component is displayed, simulating a synchronized audio track.")