|
import gradio as gr |
|
import yt_dlp |
|
import os |
|
import re |
|
import time |
|
from moviepy.video.io.VideoFileClip import VideoFileClip |
|
|
|
|
|
def sanitize_filename(title): |
|
|
|
return re.sub(r'[<>:"/\\|?*]', '_', title) |
|
|
|
|
|
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': 'mp4/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', |
|
'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 |
|
|
|
|
|
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: |
|
|
|
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 |
|
|
|
|
|
def process_video(url, start_time, end_time): |
|
if not url: |
|
return None |
|
|
|
try: |
|
|
|
video_path = download_video(url) |
|
if not video_path: |
|
return None |
|
|
|
|
|
cropped_path = crop_video(video_path, start_time, end_time) |
|
if cropped_path and os.path.exists(cropped_path): |
|
time.sleep(1) |
|
return cropped_path |
|
|
|
return None |
|
except Exception as e: |
|
print(f"Processing error: {str(e)}") |
|
return None |
|
|
|
|
|
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") |
|
|
|
|
|
process_btn.click( |
|
fn=process_video, |
|
inputs=[url_input, start_time_input, end_time_input], |
|
outputs=output_file |
|
) |
|
|
|
return demo |
|
|
|
|
|
demo = create_interface() |
|
demo.launch() |