Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| import tempfile | |
| import shutil | |
| from datetime import datetime | |
| from pathlib import Path | |
| import moviepy.editor as mp | |
| def extract_audio(video_path, filename=None): | |
| """Extract audio from video and save as MP3""" | |
| if video_path is None: | |
| return "❌ Please upload or record a video first!", None | |
| # Generate filename if not provided | |
| if not filename: | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| if hasattr(video_path, 'name'): | |
| original_name = Path(video_path.name).stem | |
| filename = f"{original_name}_{timestamp}.mp3" | |
| else: | |
| filename = f"audio_{timestamp}.mp3" | |
| elif not filename.endswith('.mp3'): | |
| filename += '.mp3' | |
| # Create temp directory for the audio file | |
| temp_dir = tempfile.mkdtemp() | |
| audio_path = os.path.join(temp_dir, filename) | |
| try: | |
| # Extract audio using moviepy | |
| video = mp.VideoFileClip(video_path) | |
| audio = video.audio | |
| if audio is None: | |
| return "❌ No audio found in the video!", None | |
| # Write audio to file | |
| audio.write_audiofile(audio_path, verbose=False, logger=None) | |
| # Close the clips to free resources | |
| audio.close() | |
| video.close() | |
| return f"✅ Audio extracted successfully: {filename}", audio_path | |
| except Exception as e: | |
| return f"❌ Error extracting audio: {str(e)}", None | |
| def save_video(video_path, filename=None): | |
| """Save video to a temporary file for download""" | |
| if video_path is None: | |
| return "❌ Please upload or record a video first!", None | |
| # Generate filename if not provided | |
| if not filename: | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| if hasattr(video_path, 'name'): | |
| original_name = Path(video_path.name).stem | |
| filename = f"{original_name}_{timestamp}.mp4" | |
| else: | |
| filename = f"video_{timestamp}.mp4" | |
| elif not filename.endswith('.mp4'): | |
| filename += '.mp4' | |
| # Create temp directory for the download file | |
| temp_dir = tempfile.mkdtemp() | |
| dest_path = os.path.join(temp_dir, filename) | |
| try: | |
| # Copy the video to temp location | |
| if isinstance(video_path, str) and os.path.exists(video_path): | |
| shutil.copy2(video_path, dest_path) | |
| else: | |
| # Handle Gradio's temporary file object | |
| with open(video_path, 'rb') as src: | |
| with open(dest_path, 'wb') as dst: | |
| shutil.copyfileobj(src, dst) | |
| return f"✅ Video ready for download: {filename}", dest_path | |
| except Exception as e: | |
| return f"❌ Error processing video: {str(e)}", None | |
| def process_all(video_path, video_filename=None, audio_filename=None): | |
| """Process both video and audio extraction""" | |
| if video_path is None: | |
| return "❌ Please upload or record a video first!", None, None, None, None | |
| # Process video | |
| video_status, video_file = save_video(video_path, video_filename) | |
| # Process audio extraction | |
| audio_status, audio_file = extract_audio(video_path, audio_filename) | |
| # Combine status messages | |
| combined_status = f"{video_status}\n{audio_status}" | |
| return combined_status, video_file, audio_file | |
| def clear_all(): | |
| """Clear all inputs and outputs""" | |
| return None, None, None, "", None, None | |
| def update_video_display(video_path): | |
| """Update the video display when a new video is uploaded/recorded""" | |
| if video_path: | |
| return video_path, f"📹 Video loaded: {os.path.basename(video_path) if hasattr(video_path, 'name') else 'Recorded video'}" | |
| return None, "" | |
| # Create the Gradio interface | |
| with gr.Blocks(title="🎥 Video Recorder with Audio Extraction") as demo: | |
| gr.Markdown(""" | |
| # 🎥 Video Recorder with Audio Extraction | |
| Record or upload a video, then download both the video file and extracted MP3 audio! | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 📤 Input") | |
| video_input = gr.Video( | |
| label="Record or Upload Video", | |
| sources=["webcam", "upload"], | |
| interactive=True, | |
| include_audio=True, | |
| height=300 | |
| ) | |
| with gr.Group(): | |
| gr.Markdown("**📁 Filename Options**") | |
| video_filename = gr.Textbox( | |
| label="Video Filename (optional)", | |
| placeholder="my_video.mp4 or leave blank for auto-name", | |
| info="Leave blank for automatic naming" | |
| ) | |
| audio_filename = gr.Textbox( | |
| label="Audio Filename (optional)", | |
| placeholder="my_audio.mp3 or leave blank for auto-name", | |
| info="Leave blank for automatic naming" | |
| ) | |
| with gr.Row(): | |
| process_btn = gr.Button("📥 Process Video & Audio", variant="primary", scale=2) | |
| clear_btn = gr.Button("🗑️ Clear All", variant="secondary", scale=1) | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 📥 Output") | |
| status_output = gr.Textbox( | |
| label="Status", | |
| value="👋 Ready to record or upload a video!", | |
| interactive=False, | |
| lines=5 | |
| ) | |
| video_display = gr.Video( | |
| label="Video Preview", | |
| interactive=False, | |
| height=300 | |
| ) | |
| with gr.Tabs(): | |
| with gr.TabItem("🎬 Download Video"): | |
| download_video = gr.File( | |
| label="Download Video File", | |
| interactive=False, | |
| file_types=[".mp4", ".mov", ".avi", ".webm"] | |
| ) | |
| with gr.TabItem("🎵 Download Audio"): | |
| download_audio = gr.File( | |
| label="Download MP3 Audio", | |
| interactive=False, | |
| file_types=[".mp3"] | |
| ) | |
| # Update video display and status when video is uploaded/recorded | |
| video_input.change( | |
| fn=update_video_display, | |
| inputs=[video_input], | |
| outputs=[video_display, status_output] | |
| ) | |
| # Process both video and audio | |
| process_btn.click( | |
| fn=process_all, | |
| inputs=[video_input, video_filename, audio_filename], | |
| outputs=[status_output, download_video, download_audio] | |
| ) | |
| # Clear all inputs and outputs | |
| clear_btn.click( | |
| fn=clear_all, | |
| outputs=[video_input, video_display, download_video, status_output, video_filename, audio_filename] | |
| ) | |
| # Instructions | |
| gr.Markdown(""" | |
| ## 📋 How to Use: | |
| 1. **Record**: Click the webcam icon to record a video | |
| 2. **Upload**: Click the upload button to select a video file | |
| 3. **Optional**: Enter custom filenames for video and audio | |
| 4. **Process**: Click "Process Video & Audio" to generate both files | |
| 5. **Download**: Use the tabs to download video (MP4) or audio (MP3) | |
| ## 📝 Notes: | |
| - Supported video formats: MP4, MOV, AVI, WebM | |
| - Audio is extracted and saved as MP3 | |
| - Videos are processed temporarily and can be downloaded immediately | |
| - Use "Clear All" to start fresh | |
| ## 🎵 Audio Extraction: | |
| - Extracts audio track from video files | |
| - Saves as high-quality MP3 | |
| - Works with any video that contains audio | |
| """) | |
| # Launch configuration | |
| if __name__ == "__main__": | |
| demo.launch( | |
| theme="soft", | |
| css=""" | |
| .gradio-container {max-width: 1000px !important;} | |
| .video-container {border-radius: 10px; overflow: hidden;} | |
| .status-box {background: #f0f7ff; padding: 15px; border-radius: 8px; border-left: 4px solid #4a90e2;} | |
| .tabs {margin-top: 20px;} | |
| """ | |
| ) |