File size: 5,205 Bytes
af28c41
a74c154
5099e75
e6ca1ab
735f163
e6ca1ab
5099e75
e6ca1ab
 
 
 
 
a74c154
735f163
a74c154
 
735f163
a74c154
e6ca1ab
716c1e6
735f163
716c1e6
a74c154
735f163
a74c154
 
716c1e6
 
 
 
 
 
 
e6ca1ab
735f163
 
e6ca1ab
 
 
735f163
 
 
716c1e6
e6ca1ab
 
735f163
 
716c1e6
 
 
 
 
735f163
e6ca1ab
716c1e6
 
 
 
 
 
 
 
735f163
a74c154
735f163
 
 
 
 
 
716c1e6
 
 
 
 
 
 
 
735f163
 
716c1e6
735f163
716c1e6
 
 
 
735f163
716c1e6
 
 
 
 
 
 
 
735f163
 
716c1e6
5099e75
a74c154
735f163
a74c154
e6ca1ab
735f163
 
 
 
716c1e6
 
735f163
716c1e6
735f163
 
 
 
716c1e6
 
735f163
 
 
 
716c1e6
 
735f163
716c1e6
735f163
 
716c1e6
 
 
735f163
716c1e6
 
 
 
 
 
 
 
 
735f163
716c1e6
735f163
716c1e6
735f163
716c1e6
a74c154
5099e75
735f163
716c1e6
 
 
 
 
 
 
 
 
 
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
149
150
151
152
153
154
155
156
157
158
159
import gradio as gr
import yt_dlp
import os
import re
import time
from moviepy.video.io.VideoFileClip import VideoFileClip

# Function to sanitize the filename
def sanitize_filename(title):
    return re.sub(r'[<>:"/\\|?*]', '_', title)

# Function to download video and return the file path
def download_video(url):
    download_path = '/tmp/downloads'
    if not os.path.exists(download_path):
        os.makedirs(download_path)
    
    ydl_opts = {
        'outtmpl': os.path.join(download_path, '%(title)s.%(ext)s'),
        'format': 'best[ext=mp4]/best',  # Simplified format selection
        'merge_output_format': 'mp4',
        'max_filesize': 100 * 1024 * 1024,  # 100MB limit
    }
    
    try:
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            info = ydl.extract_info(url, download=True)
            video_path = ydl.prepare_filename(info)
            if os.path.exists(video_path):
                return video_path
            # If the file extension is different from mp4, look for the actual file
            possible_path = video_path.rsplit('.', 1)[0] + '.mp4'
            return possible_path if os.path.exists(possible_path) else None
    except Exception as e:
        print(f"Download error: {str(e)}")
        return None

# Function to crop the video
def crop_video(input_path, start_time, end_time):
    if not input_path or not os.path.exists(input_path):
        return None
        
    output_path = os.path.join('/tmp/downloads', f'cropped_{int(time.time())}.mp4')
    try:
        with VideoFileClip(input_path) as video:
            duration = video.duration
            end_time = min(end_time, duration)
            start_time = max(0, min(start_time, end_time - 1))
            
            # Limit output duration to 60 seconds
            if end_time - start_time > 60:
                end_time = start_time + 60
                
            cropped_video = video.subclip(start_time, end_time)
            # Use lower quality settings for faster processing
            cropped_video.write_videofile(
                output_path,
                codec='libx264',
                audio_codec='aac',
                preset='ultrafast',
                bitrate='1000k'
            )
            return output_path if os.path.exists(output_path) else None
    except Exception as e:
        print(f"Cropping error: {str(e)}")
        return None

# Main processing function
def process_video(url, start_time, end_time):
    try:
        if not url or not url.strip():
            return gr.File.update(value=None, visible=True)
            
        # Add basic URL validation
        if not url.startswith(('http://', 'https://')):
            return gr.File.update(value=None, visible=True)
            
        # Download video
        video_path = download_video(url)
        if not video_path:
            return gr.File.update(value=None, visible=True)
            
        # Crop video
        cropped_path = crop_video(video_path, float(start_time), float(end_time))
        if not cropped_path:
            return gr.File.update(value=None, visible=True)
            
        # Clean up original video
        try:
            os.remove(video_path)
        except:
            pass
            
        return gr.File.update(value=cropped_path, visible=True)
        
    except Exception as e:
        print(f"Processing error: {str(e)}")
        return gr.File.update(value=None, visible=True)

# Create Gradio interface
def create_interface():
    with gr.Blocks() as demo:
        gr.Markdown("# YouTube Video Downloader and Cropper")
        
        with gr.Row():
            url_input = gr.Textbox(
                label="YouTube URL",
                placeholder="Enter YouTube video URL here...",
                max_lines=1
            )
        
        with gr.Row():
            start_time_input = gr.Number(
                label="Start Time (seconds)",
                value=0,
                minimum=0,
                maximum=3600  # 1 hour max
            )
            end_time_input = gr.Number(
                label="End Time (seconds)",
                value=10,
                minimum=1,
                maximum=3600  # 1 hour max
            )
        
        with gr.Row():
            process_btn = gr.Button("Download and Crop Video")
        
        with gr.Row():
            output_file = gr.File(label="Cropped Video", visible=True)
            
        # Add error message component
        error_message = gr.Markdown(visible=False)
        
        def process_with_error_handling(*args):
            try:
                return process_video(*args)
            except Exception as e:
                return gr.File.update(value=None, visible=True)
        
        process_btn.click(
            fn=process_with_error_handling,
            inputs=[url_input, start_time_input, end_time_input],
            outputs=[output_file]
        )
    
    return demo

# Launch the app
if __name__ == "__main__":
    demo = create_interface()
    demo.queue()  # Enable queuing
    demo.launch(
        share=False,
        debug=True,
        server_name="0.0.0.0",
        server_port=7860,
        max_threads=3
    )