File size: 3,910 Bytes
af28c41
a74c154
5099e75
e6ca1ab
735f163
e6ca1ab
5099e75
e6ca1ab
 
735f163
e6ca1ab
 
 
a74c154
735f163
 
a74c154
 
735f163
a74c154
e6ca1ab
735f163
 
a74c154
735f163
a74c154
 
e6ca1ab
a74c154
e6ca1ab
 
 
 
 
 
735f163
 
e6ca1ab
 
 
735f163
 
 
 
e6ca1ab
 
735f163
 
 
 
 
 
e6ca1ab
cd153ea
735f163
a74c154
735f163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5099e75
a74c154
735f163
a74c154
e6ca1ab
735f163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a74c154
5099e75
735f163
 
 
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
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):
    # Replace invalid characters with an underscore
    return re.sub(r'[<>:"/\\|?*]', '_', title)

# Function to download video and return the file path
def download_video(url):
    # Use /tmp for temporary storage in Hugging Face Spaces
    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': 'mp4/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',  # Prefer MP4 format
        'merge_output_format': 'mp4',
    }
    
    try:
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            info_dict = ydl.extract_info(url, download=True)
            title = info_dict.get('title', None)
            if title:
                sanitized_title = sanitize_filename(title)
                file_path = os.path.join(download_path, f"{sanitized_title}.mp4")
                return file_path if os.path.exists(file_path) else None
            return 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', 'cropped_video.mp4')
    try:
        with VideoFileClip(input_path) as video:
            # Ensure end_time doesn't exceed video duration
            duration = video.duration
            end_time = min(end_time, duration)
            if start_time >= end_time:
                return None
                
            cropped_video = video.subclip(start_time, end_time)
            cropped_video.write_videofile(output_path, codec='libx264', audio_codec='aac')
            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):
    if not url:
        return None
    
    try:
        # Download the video
        video_path = download_video(url)
        if not video_path:
            return None
            
        # Crop the video
        cropped_path = crop_video(video_path, start_time, end_time)
        if cropped_path and os.path.exists(cropped_path):
            time.sleep(1)  # Ensure file is fully written
            return cropped_path
            
        return None
    except Exception as e:
        print(f"Processing error: {str(e)}")
        return None

# 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..."
            )
            
        with gr.Row():
            start_time_input = gr.Number(
                label="Start Time (seconds)",
                value=0,
                minimum=0
            )
            end_time_input = gr.Number(
                label="End Time (seconds)",
                value=10,
                minimum=0
            )
            
        with gr.Row():
            process_btn = gr.Button("Download and Crop Video")
            output_file = gr.File(label="Download Cropped Video")
            
        # Connect the button to the processing function
        process_btn.click(
            fn=process_video,
            inputs=[url_input, start_time_input, end_time_input],
            outputs=output_file
        )
        
    return demo

# Launch the app
demo = create_interface()
demo.launch()