File size: 5,228 Bytes
a17739e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import gradio as gr
import os
from utils import download_media_from_url, convert_media

def handle_url_input(url):
    """Downloads media from a URL and returns the path."""
    if not url:
        raise gr.Error("Please enter a valid URL")
    
    try:
        gr.Info("Attempting download... This may take a few seconds.")
        file_path = download_media_from_url(url)
        return file_path, file_path  # Return to state and video preview
    except Exception as e:
        # Friendly error message for common issues
        error_msg = str(e)
        if "403" in error_msg or "Forbidden" in error_msg:
            raise gr.Error("Access denied (403). The site might be blocking automated downloads from this server IP.")
        elif "Video unavailable" in error_msg:
            raise gr.Error("Video not found. It might be private or deleted.")
        else:
            raise gr.Error(f"Download failed: {error_msg}")

def handle_file_upload(file):
    """Handles direct file upload."""
    if not file:
        return None, None
    return file, file

def process_conversion(input_path, target_format):
    """Orchestrates the conversion process."""
    if not input_path:
        raise gr.Error("No media file selected. Please upload a file or enter a URL.")
    
    gr.Info(f"Converting to {target_format}...")
    
    try:
        output_path, is_audio = convert_media(input_path, target_format)
        
        # Return logic: (Video_Component, Audio_Component, File_Download_Component)
        if is_audio:
            return {
                video_output: gr.Video(visible=False),
                audio_output: gr.Audio(value=output_path, visible=True),
                file_output: gr.File(value=output_path, visible=True)
            }
        else:
            return {
                video_output: gr.Video(value=output_path, visible=True),
                audio_output: gr.Audio(visible=False),
                file_output: gr.File(value=output_path, visible=True)
            }
            
    except Exception as e:
        raise gr.Error(f"Conversion failed: {str(e)}")

# --- Gradio 6 Application Definition ---

with gr.Blocks(
    title="Universal Media Converter",
    theme=gr.themes.Soft(),
    footer_links=[
        {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
        {"label": "yt-dlp Documentation", "url": "https://github.com/yt-dlp/yt-dlp"}
    ]
) as demo:
    
    # State to hold the path of the currently loaded file
    current_file_state = gr.State()

    with gr.Row():
        gr.Markdown(
            """
            # 🔄 Universal Media Converter
            [Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)
            
            Robust downloader and converter for Twitter/X, YouTube, TikTok, and more.
            """
        )

    with gr.Row():
        with gr.Column(scale=1):
            with gr.Tabs():
                with gr.Tab("🔗 From URL"):
                    gr.Markdown("Paste a link from X (Twitter), YouTube, or TikTok.")
                    url_input = gr.Textbox(
                        label="Paste URL",
                        placeholder="https://x.com/user/status/...",
                        show_label=False
                    )
                    url_btn = gr.Button("Fetch Media", variant="primary")
                
                with gr.Tab("📁 Upload File"):
                    upload_input = gr.File(
                        label="Drop Video File",
                        file_types=["video", "audio"],
                        type="filepath"
                    )

            # Preview of the input
            input_preview = gr.Video(label="Input Preview", interactive=False)

        with gr.Column(scale=1):
            gr.Markdown("### Conversion Settings")
            
            target_format = gr.Dropdown(
                choices=[
                    "MP4", "WEBM", "GIF", "AVI", "MOV", "MKV",  # Video
                    "MP3", "WAV", "FLAC", "AAC", "OGG"          # Audio
                ],
                value="MP4",
                label="Target Format",
                info="Select output format"
            )
            
            convert_btn = gr.Button("🚀 Convert Now", variant="secondary", size="lg")
            
            # Output Area
            gr.Markdown("### Result")
            video_output = gr.Video(label="Video Output", visible=False)
            audio_output = gr.Audio(label="Audio Output", visible=False)
            file_output = gr.File(label="Download Converted File")

    # --- Event Listeners ---

    url_btn.click(
        fn=handle_url_input,
        inputs=[url_input],
        outputs=[current_file_state, input_preview],
        api_visibility="public"
    )

    upload_input.upload(
        fn=handle_file_upload,
        inputs=[upload_input],
        outputs=[current_file_state, input_preview],
        api_visibility="public"
    )

    convert_btn.click(
        fn=process_conversion,
        inputs=[current_file_state, target_format],
        outputs=[video_output, audio_output, file_output],
        api_visibility="public"
    )

if __name__ == "__main__":
    demo.launch()