Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import tempfile | |
| import os | |
| from model_pipeline import run_model_on_video # Assuming this function exists and is correctly implemented | |
| # Page setup | |
| st.set_page_config( | |
| page_title="AI Cricket Commentary", | |
| layout="wide", | |
| initial_sidebar_state="collapsed", | |
| menu_items={ | |
| 'Get Help': 'https://www.example.com/help', | |
| 'Report a bug': "https://www.example.com/bug", | |
| 'About': "# AI Cricket Commentary Generator" | |
| } | |
| ) | |
| # Custom CSS for a professional, dark theme look | |
| st.markdown(""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap'); | |
| html, body, .stApp { | |
| background-color: #0d0e12; | |
| font-family: 'Inter', sans-serif; | |
| color: #e0e0e0; | |
| } | |
| .main-title { | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| color: #e0e0e0; | |
| text-align: center; | |
| margin-top: 1rem; | |
| margin-bottom: 0.2rem; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| gap: 0.75rem; | |
| } | |
| .subtitle { | |
| font-size: 1.1rem; | |
| color: #a0a0a0; | |
| font-weight: 400; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .section-header { | |
| font-size: 1.5rem; | |
| font-weight: 600; | |
| color: #e0e0e0; | |
| margin-top: 3rem; | |
| margin-bottom: 1.5rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| /* Main container for the "Try It Yourself" section to fix alignment */ | |
| .main-content-container { | |
| display: flex; | |
| justify-content: space-between; | |
| gap: 2rem; | |
| margin-bottom: 2rem; | |
| } | |
| /* Custom file uploader styling to match the image */ | |
| .stFileUploader { | |
| background: #1f2229; | |
| border: 2px dashed #444a56; | |
| padding: 1.5rem; | |
| border-radius: 12px; | |
| text-align: center; | |
| cursor: pointer; | |
| transition: border-color 0.3s ease, background 0.3s ease; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .stFileUploader:hover { | |
| border-color: #6a6f7b; | |
| background: #282b33; | |
| } | |
| .stFileUploader [data-testid="stFileUploaderDropzone"] { | |
| background: transparent !important; | |
| border: none !important; | |
| padding: 0 !important; | |
| } | |
| .stFileUploader [data-testid="stFileUploaderFile"] { | |
| background-color: #2c2e36; | |
| color: #e0e0e0; | |
| border-radius: 8px; | |
| padding: 0.5rem; | |
| margin-top: 1rem; | |
| } | |
| .stFileUploader [data-testid="stFileUploaderDropzone"] [data-testid="stMarkdownContainer"] { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .stFileUploader [data-testid="stMarkdownContainer"] p:first-child { | |
| font-size: 1rem; | |
| font-weight: 600; | |
| color: #e0e0e0; | |
| margin-bottom: 0.25rem; | |
| } | |
| .stFileUploader [data-testid="stMarkdownContainer"] p:nth-child(2) { | |
| font-size: 0.8rem; | |
| color: #7b7d85; | |
| } | |
| /* Uploaded video display */ | |
| .stVideo { | |
| border-radius: 12px; | |
| overflow: hidden; | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.3); | |
| } | |
| .video-container, .results-box { | |
| background: #1f2229; | |
| padding: 1.5rem; | |
| border-radius: 12px; | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.3); | |
| height: 100%; | |
| border: 1px solid #2c2f37; | |
| } | |
| .results-box h3 { | |
| margin-top: 0; | |
| color: #e0e0e0; | |
| } | |
| .results-box .placeholder-text { | |
| color: #7b7d85; | |
| text-align: center; | |
| padding-top: 2rem; | |
| padding-bottom: 2rem; | |
| } | |
| /* Button styling */ | |
| .stButton>button { | |
| background: #007bff; | |
| color: white; | |
| font-weight: 600; | |
| border-radius: 8px; | |
| padding: 0.75rem 1.5rem; | |
| border: none; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 6px rgba(0, 123, 255, 0.2); | |
| } | |
| .stButton>button:hover { | |
| background: #0056b3; | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 10px rgba(0, 123, 255, 0.3); | |
| } | |
| .stDownloadButton>button { | |
| background: #444a56; | |
| color: #e0e0e0; | |
| font-weight: 600; | |
| border: none; | |
| border-radius: 8px; | |
| padding: 0.75rem 1.5rem; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.2); | |
| } | |
| .stDownloadButton>button:hover { | |
| background: #5d616d; | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 10px rgba(0,0,0,0.3); | |
| } | |
| /* Footer styling */ | |
| .footer { | |
| text-align: center; | |
| font-size: 0.9rem; | |
| color: #7b7d85; | |
| margin-top: 5rem; | |
| padding-top: 2rem; | |
| border-top: 1px solid #2c2f37; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # --- HEADER --- | |
| st.markdown('<h1 class="main-title">π AI Cricket Commentary Generator</h1>', unsafe_allow_html=True) | |
| st.markdown('<p class="subtitle">Revolutionizing Cricket Commentary with AI-driven analysis</p>', unsafe_allow_html=True) | |
| # --- TRY IT YOURSELF SECTION --- | |
| st.markdown('<h2 class="section-header">π¬ Try It Yourself</h2>', unsafe_allow_html=True) | |
| # Use st.columns to create a clean two-column layout for upload and commentary | |
| col_upload, col_display = st.columns(2) | |
| with col_upload: | |
| st.markdown("<h4>Upload Cricket Match Video</h4>", unsafe_allow_html=True) | |
| video_file = st.file_uploader( | |
| "Drag and drop file here\nLimit 200MB per file", | |
| type=["mp4", "mov", "avi", "mpeg4"], | |
| label_visibility="collapsed" | |
| ) | |
| with col_display: | |
| if video_file: | |
| st.markdown("<h4>Uploaded Video Preview</h4>", unsafe_allow_html=True) | |
| st.video(video_file) | |
| if st.button("π Generate Commentary", use_container_width=True): | |
| with st.spinner("Generating... please wait β³"): | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp: | |
| tmp.write(video_file.read()) | |
| temp_video_path = tmp.name | |
| try: | |
| commentary_text, audio_path, video_output_path = run_model_on_video(temp_video_path) | |
| st.success("β Commentary Generated Successfully!") | |
| st.markdown(f"**π AI Commentary Summary:**\n\n{commentary_text}") | |
| st.audio(audio_path, format="audio/mp3", autoplay=False) | |
| col_audio, col_video = st.columns(2) | |
| with col_audio: | |
| with open(audio_path, 'rb') as a: | |
| st.download_button("β¬οΈ Download Audio", a, file_name="commentary.mp3", use_container_width=True) | |
| with col_video: | |
| with open(video_output_path, 'rb') as v: | |
| st.download_button("β¬οΈ Download Final Video", v, file_name="final_video.mp4", use_container_width=True) | |
| st.video(video_output_path) | |
| except Exception as e: | |
| st.error(f"β An error occurred: {e}") | |
| st.exception(e) | |
| finally: | |
| try: | |
| if 'temp_video_path' in locals() and os.path.exists(temp_video_path): | |
| os.remove(temp_video_path) | |
| if 'audio_path' in locals() and os.path.exists(audio_path): | |
| os.remove(audio_path) | |
| if 'video_output_path' in locals() and os.path.exists(video_output_path): | |
| os.remove(video_output_path) | |
| except PermissionError: | |
| st.warning("Could not delete temporary files. Please delete them manually if necessary.") | |
| else: | |
| st.markdown('<div class="results-box">', unsafe_allow_html=True) | |
| st.markdown("<h3>AI Generated Commentary</h3>", unsafe_allow_html=True) | |
| st.markdown('<p class="placeholder-text">Upload a cricket video to see the preview and generate commentary.</p>', unsafe_allow_html=True) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # --- HOW IT WORKS SECTION --- | |
| st.markdown('<div class="section-header">βοΈ How It Works</div>', unsafe_allow_html=True) | |
| how_cols = st.columns(3) | |
| steps = [ | |
| ("π€ Upload Video", "Upload your cricket video file. Our system processes it frame by frame."), | |
| ("π§ AI Analysis", "The AI analyzes key events, recognizes shots, and predicts outcomes."), | |
| ("π£οΈ Generate Commentary", "High-quality, professional commentary is generated and ready for playback or download.") | |
| ] | |
| for col, (title, desc) in zip(how_cols, steps): | |
| with col: | |
| st.markdown(f'<div class="results-box"><h4>{title}</h4><p>{desc}</p></div>', unsafe_allow_html=True) | |
| # --- KEY FEATURES SECTION --- | |
| st.markdown('<div class="section-header">β Key Features</div>', unsafe_allow_html=True) | |
| feature_cols = st.columns(3) | |
| features = [ | |
| ("π― Shot Recognition", "Accurately detects shots like cover drives, sweeps, pulls, and hooks."), | |
| ("π Outcome Prediction", "Intelligently predicts boundaries, wickets, and other key outcomes."), | |
| ("ποΈ Broadcast-Quality Commentary", "Generates dynamic commentary using proper cricket terminology and flow."), | |
| ] | |
| for col, (title, desc) in zip(feature_cols, features): | |
| with col: | |
| st.markdown(f'<div class="results-box"><h5>{title}</h5><p>{desc}</p></div>', unsafe_allow_html=True) | |
| # --- FOOTER --- | |
| st.markdown('<div class="footer">Made with β€οΈ by AI Cricket Labs | Β© 2024</div>', unsafe_allow_html=True) | |