| 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 |
| |
| |
| 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' |
| |
| |
| temp_dir = tempfile.mkdtemp() |
| audio_path = os.path.join(temp_dir, filename) |
| |
| try: |
| |
| video = mp.VideoFileClip(video_path) |
| audio = video.audio |
| |
| if audio is None: |
| return "❌ No audio found in the video!", None |
| |
| |
| audio.write_audiofile(audio_path, verbose=False, logger=None) |
| |
| |
| 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 |
| |
| |
| 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' |
| |
| |
| temp_dir = tempfile.mkdtemp() |
| dest_path = os.path.join(temp_dir, filename) |
| |
| try: |
| |
| if isinstance(video_path, str) and os.path.exists(video_path): |
| shutil.copy2(video_path, dest_path) |
| else: |
| |
| 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 |
| |
| |
| video_status, video_file = save_video(video_path, video_filename) |
| |
| |
| audio_status, audio_file = extract_audio(video_path, audio_filename) |
| |
| |
| 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, "" |
|
|
| |
| 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"] |
| ) |
| |
| |
| video_input.change( |
| fn=update_video_display, |
| inputs=[video_input], |
| outputs=[video_display, status_output] |
| ) |
| |
| |
| process_btn.click( |
| fn=process_all, |
| inputs=[video_input, video_filename, audio_filename], |
| outputs=[status_output, download_video, download_audio] |
| ) |
| |
| |
| clear_btn.click( |
| fn=clear_all, |
| outputs=[video_input, video_display, download_video, status_output, video_filename, audio_filename] |
| ) |
| |
| |
| 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 |
| """) |
|
|
| |
| 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;} |
| """ |
| ) |