File size: 8,538 Bytes
e1c4426
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348e3c3
e1c4426
 
348e3c3
e1c4426
 
 
 
 
 
 
 
 
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
160
161
162
163
164
165
166
167
168
169
170
171

import gradio as gr
import yt_dlp
import os
import tempfile
import shutil
from pathlib import Path
import re

class YouTubeDownloader:
    def __init__(self):
        self.download_dir = tempfile.mkdtemp()

    def is_valid_youtube_url(self, url):
        youtube_regex = re.compile(
            r'(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/'
            r'(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'
        )
        return youtube_regex.match(url) is not None

    def get_video_info(self, url, progress=gr.Progress(), cookiefile=None):
        if not url or not url.strip():
            return None, "❌ Please enter a YouTube URL"

        if not self.is_valid_youtube_url(url):
            return None, "❌ Invalid YouTube URL. Please enter a valid YouTube video URL"

        try:
            progress(0.2, desc="Fetching video information...")
            ydl_opts = {
                'noplaylist': True,
                'extract_flat': False,
            }
            if cookiefile:
                ydl_opts['cookiefile'] = cookiefile

            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                try:
                    info = ydl.extract_info(url, download=False)
                    video_info = {
                        'title': info.get('title', 'Unknown'),
                        'description': info.get('description', 'No description available'),
                        'duration': info.get('duration', 0),
                        'view_count': info.get('view_count', 0),
                        'like_count': info.get('like_count', 0),
                        'comment_count': info.get('comment_count', 0),
                        'upload_date': info.get('upload_date', ''),
                        'uploader': info.get('uploader', 'Unknown'),
                        'channel': info.get('channel', 'Unknown'),
                        'channel_followers': info.get('channel_follower_count', 0),
                        'tags': info.get('tags', []),
                        'categories': info.get('categories', []),
                        'thumbnail': info.get('thumbnail', ''),
                        'webpage_url': info.get('webpage_url', url)
                    }
                    progress(1.0, desc="Information retrieved!")
                    return video_info, "βœ… Video information retrieved successfully"
                except yt_dlp.DownloadError as e:
                    error_msg = str(e)
                    if "Video unavailable" in error_msg:
                        return None, "❌ Video is unavailable or private"
                    elif "age-restricted" in error_msg.lower():
                        return None, "❌ Video is age-restricted"
                    else:
                        return None, f"❌ Failed to get video info: {error_msg}"
        except Exception as e:
            return None, f"❌ An unexpected error occurred: {str(e)}"

    def download_video(self, url, progress=gr.Progress(), cookiefile=None):
        if not url or not url.strip():
            return None, "❌ Please enter a YouTube URL"

        if not self.is_valid_youtube_url(url):
            return None, "❌ Invalid YouTube URL. Please enter a valid YouTube video URL"

        try:
            progress(0.1, desc="Initializing download...")
            ydl_opts = {
                'format': 'best[ext=mp4]/best',
                'outtmpl': os.path.join(self.download_dir, '%(title)s.%(ext)s'),
                'noplaylist': True,
            }
            if cookiefile:
                ydl_opts['cookiefile'] = cookiefile

            progress(0.3, desc="Fetching video information...")
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                try:
                    info = ydl.extract_info(url, download=False)
                    video_title = info.get('title', 'Unknown')
                    duration = info.get('duration', 0)
                    progress(0.5, desc=f"Downloading: {video_title[:50]}...")
                    ydl.download([url])
                    progress(0.9, desc="Finalizing download...")
                    downloaded_files = list(Path(self.download_dir).glob('*'))
                    if downloaded_files:
                        downloaded_file = downloaded_files[0]
                        file_size = downloaded_file.stat().st_size / (1024 * 1024)
                        progress(1.0, desc="Download completed!")
                        success_message = f"βœ… Successfully downloaded: {video_title}\n"
                        success_message += f"πŸ“ File size: {file_size:.1f} MB\n"
                        success_message += f"⏱️ Duration: {duration//60}:{duration%60:02d}" if duration else ""
                        return str(downloaded_file), success_message
                    else:
                        return None, "❌ Download completed but file not found"
                except yt_dlp.DownloadError as e:
                    error_msg = str(e)
                    if "Video unavailable" in error_msg:
                        return None, "❌ Video is unavailable or private"
                    elif "age-restricted" in error_msg.lower():
                        return None, "❌ Video is age-restricted and cannot be downloaded"
                    elif "copyright" in error_msg.lower():
                        return None, "❌ Video cannot be downloaded due to copyright restrictions"
                    else:
                        return None, f"❌ Download failed: {error_msg}"
        except Exception as e:
            return None, f"❌ An unexpected error occurred: {str(e)}"

    def cleanup(self):
        try:
            shutil.rmtree(self.download_dir, ignore_errors=True)
        except:
            pass

downloader = YouTubeDownloader()

def create_interface():
    with gr.Blocks(title="YouTube Video Downloader & Analyzer") as demo:
        url_input = gr.Textbox(label="YouTube URL", placeholder="https://www.youtube.com/watch?v=...")
        cookies_input = gr.File(label="Upload cookies.txt (optional)", type="filepath", file_types=[".txt"])
        download_btn = gr.Button("Download Video")
        status_output = gr.Textbox(label="Download Status")
        file_output = gr.File(label="Downloaded Video", visible=False)
        analysis_btn = gr.Button("Show Analysis Results", visible=False)
        analysis_output = gr.Textbox(label="Video Analysis Results", visible=False)
        video_info_state = gr.State(value=None)

        def handle_download(url, cookies_path):
            if not url or not url.strip():
                return "Please enter a YouTube URL", gr.File(visible=False), gr.Button(visible=False), None

            cookiefile = cookies_path.strip() if cookies_path and os.path.exists(cookies_path.strip()) else None
            video_info, info_message = downloader.get_video_info(url, cookiefile=cookiefile)
            file_path, download_message = downloader.download_video(url, cookiefile=cookiefile)
            print(f"[DEBUG] Download message: {download_message}")

            if file_path and video_info:
                success_message = f"{download_message}\n\nVideo downloaded successfully! Click 'Show Analysis Results' to see detailed information."
                return success_message, gr.File(value=file_path, visible=True), gr.Button(visible=True), video_info
            elif file_path:
                return f"{download_message}\n\nVideo downloaded but analysis data unavailable.", gr.File(value=file_path, visible=True), gr.Button(visible=False), None
            else:
                return f"❌ Download failed:\n{download_message}", gr.File(visible=False), gr.Button(visible=False), None

        def show_analysis(video_info):
            if video_info:
                return downloader.format_video_info(video_info), gr.Textbox(visible=True)
            return downloader.format_video_info(video_info)#"No analysis data available.", gr.Textbox(visible=True)

        download_btn.click(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, video_info_state])
        analysis_btn.click(show_analysis, inputs=[video_info_state], outputs=[analysis_output])
        url_input.submit(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, video_info_state])

    return demo

if __name__ == "__main__":
    demo = create_interface()
    import atexit
    atexit.register(downloader.cleanup)
    demo.launch()