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() |