import pixeltable as pxt import os import openai import gradio as gr import getpass from pixeltable.iterators import FrameIterator from pixeltable.functions.video import extract_audio from pixeltable.functions.audio import get_metadata from pixeltable.functions import openai # Store OpenAI API Key if 'OPENAI_API_KEY' not in os.environ: os.environ['OPENAI_API_KEY'] = getpass.getpass('Enter your OpenAI API key:') MAX_VIDEO_SIZE_MB = 35 CONCURRENCY_LIMIT = 1 def process_and_generate_post(video_file, social_media_type, progress=gr.Progress()): progress(0, desc="Initializing...") # Create a Table, a View, and Computed Columns pxt.drop_dir('directory', force=True) pxt.create_dir('directory') t = pxt.create_table( 'directory.video_table', { "video": pxt.Video, "sm_type": pxt.String } ) frames_view = pxt.create_view( "directory.frames", t, iterator=FrameIterator.create(video=t.video, fps=1) ) # Create computed columns to store transformations and persist outputs t.add_computed_column(audio=extract_audio(t.video, format='mp3')) t.add_computed_column(metadata=get_metadata(t.audio)) t.add_computed_column(transcription=openai.transcriptions(audio=t.audio, model='whisper-1')) t.add_computed_column(transcription_text=t.transcription.text) progress(0.1, desc="Creating UDFs...") # Custom User-Defined Function (UDF) for Generating Social Media Prompts @pxt.udf def prompt(A: str, B: str) -> list[dict]: system_msg = 'You are an expert in creating social media content and you generate effective post, based on user content. Respect the social media platform guidelines and constraints.' user_msg = f'A: "{A}" \n B: "{B}"' return [ {'role': 'system', 'content': system_msg}, {'role': 'user', 'content': user_msg} ] # Apply the UDF to create a new column t.add_computed_column(message=prompt(t.sm_type, t.transcription_text)) """## Generating Responses with OpenAI's GPT Model""" progress(0.2, desc="Calling LLMs") # # Generate responses using OpenAI's chat completion API t.add_computed_column(response=openai.chat_completions(messages=t.message, model='gpt-4o-mini-2024-07-18', max_tokens=500)) ## Extract the content of the response t.add_computed_column(answer=t.response.choices[0].message.content) if not video_file: return "Please upload a video file.", None try: # Check video file size video_size = os.path.getsize(video_file) / (1024 * 1024) # Convert to MB if video_size > MAX_VIDEO_SIZE_MB: return f"The video file is larger than {MAX_VIDEO_SIZE_MB} MB. Please upload a smaller file.", None progress(0.4, desc="Inserting video...") # # Insert a video into the table. Pixeltable supports referencing external data sources like URLs t.insert([{ "video": video_file, "sm_type": social_media_type }]) progress(0.6, desc="Generating posts...") # Retrieve Social media posts social_media_post = t.select(t.answer).tail(1)['answer'][0] # Retrieve Audio audio = t.select(t.audio).tail(1)['audio'][0] # Retrieve thumbnails thumbnails = frames_view.select(frames_view.frame).tail(6)['frame'] progress(0.8, desc="Preparing results...") # Retrieve Pixeltable Table containing all videos and stored data df_output = t.select(t.transcription_text).tail(1)['transcription_text'][0] #Display content return social_media_post, thumbnails, df_output, audio except Exception as e: return f"An error occurred: {str(e)}", None # Gradio Interface def gradio_interface(): with gr.Blocks(theme=gr.themes.Base()) as demo: # Header Section with Logo and Title gr.Markdown( """ <div style="text-align: left; margin-bottom: 20px;"> <img src="https://raw.githubusercontent.com/pixeltable/pixeltable/main/docs/resources/pixeltable-logo-large.png" alt="Pixeltable" style="max-width: 200px; margin-bottom: 20px;" /> <h1 style="margin-bottom: 0.5em;">📹 Video to Social Media Post Generator</h1> <p style="color: #666; margin-bottom: 1em;">Transform your videos into engaging social media content using AI</p> </div> """ ) with gr.Row(): # Left Column - Platform Features with gr.Column(): with gr.Accordion("🎯 Key Features", open=False): gr.Markdown( """ * 🎥 **Smart Video Processing** - Automatic frame extraction - High-quality audio separation - Real-time transcription * 🤖 **AI-Powered Content** - Platform-specific post generation - Engaging caption creation - Tone & style optimization * 📊 **Complete Analytics** - Transcription review - Thumbnail selection - Audio verification """ ) # Right Column - How It Works with gr.Column(): with gr.Accordion("🛠️ How It Works", open=False): gr.Markdown( """ 1. 📤 **Upload Your Video** - Choose your content - Select target platform - Start processing 2. 🔄 **AI Processing** - Video analysis - Content extraction - Post generation 3. ✨ **Review & Export** - Preview generated posts - Select thumbnails - Copy to clipboard """ ) # Main Interface with gr.Tabs() as tabs: # Upload Tab with gr.TabItem("📤 Upload & Generate", id=0): with gr.Row(): # Left Column - Input Controls with gr.Column(): video_input = gr.Video( label="Upload Your Video", include_audio=True, max_length=300, height='400px', autoplay=False ) with gr.Group(): gr.Markdown("### 🎯 Target Platform") social_media_type = gr.Radio( choices=[ "X (Twitter)", "Facebook", "LinkedIn", "Instagram" ], value="X (Twitter)", label="Select where you want to share:", interactive=True ) generate_btn = gr.Button( "🚀 Generate Post", scale=1, size="lg", variant="primary" ) # Right Column - Output Display with gr.Column(): output = gr.Textbox( label="✨ Generated Post", show_copy_button=True, lines=4 ) gr.Markdown("### 🖼️ Thumbnail Options") thumbnail = gr.Gallery( label="Select your preferred thumbnail", show_download_button=True, show_fullscreen_button=True, height='200px', object_fit="contain" ) # Review Tab with gr.TabItem("📝 Review & Export", id=1): with gr.Row(): with gr.Column(): df_output = gr.Textbox( label="📝 Video Transcription", show_copy_button=True, lines=8 ) audio = gr.Audio( label="🎵 Extracted Audio", show_download_button=True, type="filepath" ) # Example Section gr.Markdown("### 📚 Sample Usage") with gr.Row(): gr.Examples( examples=[ ["example1.mp4", "X (Twitter)"], ["example2.mp4", "LinkedIn"], ["example3.mp4", "Instagram"], ["example4.mp4", "Facebook"] ], inputs=[video_input, social_media_type], label="Try with sample videos:", examples_per_page=5 ) # Footer gr.HTML( """ <div style="text-align: center; margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #ccc;"> <p style="color: #666; font-size: 0.9em;"> Powered by <a href="https://github.com/pixeltable/pixeltable" target="_blank" style="color: #F25022; text-decoration: none;">Pixeltable</a> | <a href="https://docs.pixeltable.com" target="_blank" style="color: #666;">Documentation</a> | <a href="https://github.com/pixeltable/pixeltable" target="_blank" style="color: #666;">GitHub</a> </p> </div> """ ) # Wire up the generate button click event generate_btn.click( fn=process_and_generate_post, inputs=[video_input, social_media_type], outputs=[output, thumbnail, df_output, audio], api_name="generate", show_progress="full", trigger_mode='once' ) return demo # Launch the Gradio interface with production settings if __name__ == "__main__": demo = gradio_interface() demo.launch( server_name="0.0.0.0", # Allow external access server_port=7860, # Standard Gradio port share=False, # Disable sharing in production show_api=False, # Hide API docs in production show_error=False, # Hide detailed errors in production ssl_verify=True, # Enable SSL verification quiet=True # Reduce console output )