#!/usr/bin/env python # -*- coding: utf-8 -*- import subprocess import gradio as gr import tempfile # Define supported subtitle formats (without the dot for conversion logic) SUPPORTED_SUBTITLE_FORMATS = ['srt', 'vtt', 'ass', 'ssa'] SUPPORTED_SUBTITLE_FORMATS2 = ['srt', 'vtt', 'ass', 'ssa'] # Define allowed file extensions for Gradio file uploader (with dot) ALLOWED_EXTENSIONS = [".srt", ".vtt", ".ass", ".ssa"] def convert_subtitle_file(src_format, dest_format, input_file_path): """ Convert the subtitle file from src_format to dest_format using ffmpeg. Parameters: src_format (str): The source subtitle format. dest_format (str): The target subtitle format. input_file_path (str): Path to the input subtitle file. Returns: tuple: (converted_file_path, error_message) """ # Create a temporary file to store the converted subtitle output_file = tempfile.NamedTemporaryFile(delete=False, suffix=f".{dest_format}") output_file_path = output_file.name output_file.close() # Close the file so that ffmpeg can write to it # Construct the ffmpeg command; the -y flag overwrites the output file if it exists cmd = [ "ffmpeg", "-y", "-i", input_file_path, output_file_path ] try: subprocess.run(cmd, check=True, capture_output=True, text=True, encoding='utf-8') return output_file_path, "" except subprocess.CalledProcessError as e: return "", e.stderr def convert_subtitles(uploaded_file_path, dest_format): """ Convert the uploaded subtitle file to the specified format. Parameters: uploaded_file_path (str): Path to the uploaded subtitle file. dest_format (str): The target subtitle format. Returns: tuple: (converted_file_path, error_message) """ if uploaded_file_path is not None: # Determine the source format from the file extension (converted to lowercase) src_format = uploaded_file_path.split('.')[-1].lower() if src_format not in SUPPORTED_SUBTITLE_FORMATS: return "", "Unsupported file format. Please upload a valid subtitle file (supported: srt, vtt, ass, ssa)." try: converted_file_path, error_message = convert_subtitle_file(src_format, dest_format, uploaded_file_path) if converted_file_path: return converted_file_path, "" else: return "", f"Error during conversion: {error_message}" except Exception as e: return "", f"Error during conversion: {e}" return "", "No file uploaded." def main(): # Create the Gradio Blocks interface with a page title and custom CSS for better UI appearance. with gr.Blocks( analytics_enabled=False, title="Free Online Subtitle Converter - Convert SRT, VTT, ASS, SSA Subtitles Easily", css=""" /* Global background and font settings */ body { background-color: #f7f7f7; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; } /* Main container styling */ .gradio-container { max-width: 900px; margin: auto; background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); padding: 20px; } /* Convert button styling */ #convert-btn { background-color: #007bff; color: #ffffff; border: none; } #convert-btn:hover { background-color: #0056b3; } """ ) as demo: # Add SEO information, application description, and usage instructions with gr.Row(): with gr.Column(): gr.Markdown( """ # Free Online Subtitle Converter **Subtitle Converter** is a simple and easy-to-use online tool that supports converting subtitle files between SRT, VTT, ASS, and SSA formats. This application leverages [ffmpeg](https://ffmpeg.org/) for subtitle format conversion, making it ideal for various subtitle conversion needs. ## Application Overview - **Fast Conversion**: Upload your file and get the conversion done in seconds. - **Multiple Formats Supported**: Supports srt, vtt, ass, ssa formats. - **Online Tool**: No need to install any software; use it directly from your browser. ## Usage Instructions 1. Upload a subtitle file (supported formats: srt, vtt, ass, ssa) from the left side. 2. Select the desired target format from the dropdown menu. 3. Click the "Convert" button to initiate the conversion. 4. Once the conversion is complete, click the "Download Converted File" button to download your file. """ ) # Build the upload and conversion operation area with gr.Row(): # Left column: file upload and format selection with gr.Column(scale=1): file_input = gr.File(label="Upload Subtitle File", file_types=ALLOWED_EXTENSIONS, type="filepath") dest_format = gr.Dropdown(label='Convert To', choices=SUPPORTED_SUBTITLE_FORMATS2, value=SUPPORTED_SUBTITLE_FORMATS2[0]) convert_button = gr.Button("Convert", elem_id="convert-btn") # Right column: display conversion result and error messages with gr.Column(scale=1): result_file = gr.File(label="Download Converted File", visible=True) error_message = gr.Textbox(label="Error Message", visible=False, interactive=False) # Download button for the converted file download_button = gr.DownloadButton( label="Download Converted File", value=None, visible=True, variant="primary", ) def convert_and_show(uploaded_file_path, dest_format): """ Process the uploaded file conversion and return the conversion result or error message. Parameters: uploaded_file_path (str): Path to the uploaded subtitle file. dest_format (str): Target format for conversion. Returns: tuple: (converted_file_path, updated error message, download button value) """ if not uploaded_file_path: return None, gr.update(value="Please upload a subtitle file.", visible=True), None if not dest_format: return None, gr.update(value="Please select a target format.", visible=True), None file_path, error = convert_subtitles(uploaded_file_path, dest_format) if file_path: # Conversion successful, hide error message and update download link return file_path, gr.update(visible=False), file_path else: return None, gr.update(value=error, visible=True), None # Bind the click event to the convert function convert_button.click(fn=convert_and_show, inputs=[file_input, dest_format], outputs=[result_file, error_message, download_button]) # Footer information gr.Markdown( """ --- **Disclaimer**: This tool is intended for subtitle format conversion only. Please ensure you have the legal rights to use the uploaded files. """ ) # Launch the app without specifying a fixed port, making it suitable for Linux and Hugging Face Spaces demo.launch(share=True) if __name__ == "__main__": main()