import gradio as gr import os from pathlib import Path from datetime import datetime from converter_fw import VideoConverter import tempfile import shutil class VideoConverterGUI: def __init__(self): self.converter = VideoConverter() self.current_progress = 0 self.status_message = "" self.output_dir = os.path.join(os.getcwd(), "converted_videos") os.makedirs(self.output_dir, exist_ok=True) # Define video extensions self.video_extensions = [ ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".mpeg", ".MP4", ".AVI", ".MKV", ".MOV", ".WMV", ".FLV", ".MPEG" ] def generate_output_filename(self, input_filename, output_format): name = Path(input_filename).stem timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") return f"{name}_{timestamp}.{output_format.lower()}" def update_video_display(self, files): """Update the video preview""" if not files or len(files) == 0: return None return files[0] def create_temp_copy(self, file_path): """Create a temporary copy of the input file""" file_ext = os.path.splitext(file_path)[1] temp_file = tempfile.NamedTemporaryFile(suffix=file_ext, delete=False) temp_path = temp_file.name temp_file.close() shutil.copy2(file_path, temp_path) return temp_path def is_valid_video(self, file_path): """Check if file has a valid video extension""" return any(file_path.lower().endswith(ext.lower()) for ext in self.video_extensions) def convert_videos(self, files, output_format, codec, resolution, bitrate, bitrate_unit, fps, progress=gr.Progress()): if not files: return "Please upload video files.", [] results = [] output_files = [] temp_files = [] # Filter valid video files valid_files = [f for f in files if self.is_valid_video(f.name)] if not valid_files: return "No valid video files found. Please upload video files.", [] total_files = len(valid_files) file_weight = 1.0 / total_files # Process bitrate input if bitrate.strip().lower() != "auto" and bitrate.strip() != "": try: bitrate_value = float(bitrate) if bitrate_unit == "kbps": bitrate_value = f"{bitrate_value}k" elif bitrate_unit == "Mbps": bitrate_value = f"{bitrate_value}M" else: return "Invalid bitrate unit selected.", [] except ValueError: return f"Invalid bitrate value: {bitrate}. Please enter a numeric value.", [] else: bitrate_value = "auto" try: for i, file in enumerate(valid_files): try: base_progress = i * file_weight # Create a temporary copy of the input file temp_input_path = self.create_temp_copy(file.name) temp_files.append(temp_input_path) original_filename = os.path.basename(file.name) progress(base_progress, desc=f"Converting {original_filename}") def progress_callback(file_progress): total_progress = base_progress + (file_progress * file_weight) progress(total_progress) output_filename = self.generate_output_filename(original_filename, output_format) print(f"Converting {temp_input_path} to {output_filename}") # Debug print success, message = self.converter.convert_video( temp_input_path, output_format, codec, self.output_dir, progress_callback, output_filename, resolution, bitrate_value, fps ) if success: output_path = os.path.join(self.output_dir, output_filename) if os.path.exists(output_path): output_files.append(output_path) results.append(message) except Exception as e: print(f"Detailed error for {file.name}: {str(e)}") # Debug print results.append(f"Error processing {os.path.basename(file.name)}: {str(e)}") finally: # Clean up temporary files for temp_file in temp_files: try: if os.path.exists(temp_file): os.remove(temp_file) except Exception as e: print(f"Error cleaning up {temp_file}: {str(e)}") success_count = sum(1 for msg in results if "Successfully" in msg) report = f"Conversion completed: {success_count}/{total_files} files converted successfully\n\n" report += "\n".join(results) return report, output_files if output_files else None def create_ui(self): with gr.Blocks() as app: gr.Markdown(f""" # Batch Video Converter GPU Acceleration: {"Available" if self.converter.gpu_available else "Not Available"} """) with gr.Column(): # Input Settings Section gr.Markdown("### Input Settings") with gr.Row(): with gr.Column(scale=1): input_videos = gr.Files( label="Upload Videos", file_count="multiple", file_types=["video"], type="filepath" ) with gr.Row(): preview = gr.Video( label="Video Preview", format="mp4", visible=True, interactive=False ) # Conversion Settings Section gr.Markdown("### Conversion Settings") with gr.Row(): format_dropdown = gr.Dropdown( choices=self.converter.formats, value="MP4", label="Output Format" ) codec_dropdown = gr.Dropdown( choices=self.converter.codecs, value="H.264", label="Codec" ) # Add output resolution, bitrate, and fps options with gr.Row(): resolution_dropdown = gr.Dropdown( choices=[ "Same as input", "3840x2160 (4K)", "2560x1440 (1440p)", "1920x1080 (1080p)", "1280x720 (720p)", "854x480 (480p)" ], value="Same as input", label="Output Resolution" ) with gr.Row(): bitrate_input = gr.Textbox( label="Output Bitrate", placeholder="Enter value or leave blank for auto", value="" ) bitrate_unit = gr.Dropdown( choices=["kbps", "Mbps"], value="Mbps", label="Bitrate Unit" ) with gr.Row(): fps_dropdown = gr.Dropdown( choices=[ "Same as input", "23.97", "24", "25", "29.97", "30", "60" ], value="Same as input", label="Output FPS" ) # Conversion Button and Progress Section convert_btn = gr.Button( "Convert Videos", variant="primary", size="lg" ) gr.Markdown("### Conversion Progress") output_text = gr.Textbox( label="Status", lines=10, show_copy_button=True ) # Download Section gr.Markdown("### Download Converted Videos") output_files = gr.Files( label="Converted Videos (Click to download)", interactive=False ) # Event handlers input_videos.change( fn=self.update_video_display, inputs=[input_videos], outputs=[preview] ) convert_btn.click( fn=self.convert_videos, inputs=[ input_videos, format_dropdown, codec_dropdown, resolution_dropdown, bitrate_input, bitrate_unit, fps_dropdown ], outputs=[ output_text, output_files ] ) return app def main(self): gui = VideoConverterGUI() app = gui.create_ui() app.launch() if __name__ == "__main__": VideoConverterGUI().main()