Spaces:
Sleeping
Sleeping
import yt_dlp | |
import logging | |
import gradio as gr | |
import re | |
# Configure logging for debugging purposes | |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') | |
# Function to search YouTube videos using yt-dlp for better reliability | |
def youtube_search(query, max_results=50): | |
ydl_opts = { | |
'quiet': False, # Set to False to get more detailed output from yt-dlp | |
'extract_flat': 'in_playlist', | |
'logger': logging.getLogger(), # Use the logging module to capture yt-dlp logs | |
'simulate': True, | |
'noplaylist': True, # To avoid playlist entries | |
} | |
search_url = f"ytsearch{max_results}:{query}" | |
logging.debug(f"Starting YouTube search for query: {query}") | |
try: | |
with yt_dlp.YoutubeDL(ydl_opts) as ydl: | |
result = ydl.extract_info(search_url, download=False) | |
gallery_items = [] | |
detailed_entries = [] | |
if 'entries' in result: | |
logging.debug(f"Number of entries found: {len(result['entries'])}") | |
for entry in result['entries']: | |
video_id = entry.get('id') | |
thumbnail_url = entry.get('thumbnail') if entry.get('thumbnail') else "https://via.placeholder.com/150" | |
video_title = entry.get('title', "Unknown Title") | |
if video_id: | |
# Collect and display details | |
print("\n==============================") | |
print("Video Details:") | |
print("==============================") | |
print(f"ID: {entry.get('id', 'N/A')}") | |
print(f"Title: {entry.get('title', 'N/A')}") | |
print(f"Uploader: {entry.get('uploader', 'N/A')}") | |
print(f"Uploader ID: {entry.get('uploader_id', 'N/A')}") | |
print(f"Upload Date: {entry.get('upload_date', 'N/A')}") | |
print(f"Description: {entry.get('description', 'N/A')}") | |
print(f"Duration (seconds): {entry.get('duration', 'N/A')}") | |
print(f"View Count: {entry.get('view_count', 'N/A')}") | |
print(f"Like Count: {entry.get('like_count', 'N/A')}") | |
print(f"Dislike Count: {entry.get('dislike_count', 'N/A')}") | |
print(f"Comment Count: {entry.get('comment_count', 'N/A')}") | |
print(f"Average Rating: {entry.get('average_rating', 'N/A')}") | |
print(f"Thumbnail URL: {entry.get('thumbnail', 'N/A')}") | |
print(f"Webpage URL: {entry.get('webpage_url', 'N/A')}") | |
print(f"Channel URL: {entry.get('channel_url', 'N/A')}") | |
print(f"Categories: {entry.get('categories', 'N/A')}") | |
print(f"Tags: {entry.get('tags', 'N/A')}") | |
print(f"Channel ID: {entry.get('channel_id', 'N/A')}") | |
print(f"Age Restriction: {entry.get('age_limit', 'N/A')}") | |
print(f"Is Live: {entry.get('is_live', 'N/A')}") | |
print(f"FPS: {entry.get('fps', 'N/A')}") | |
print(f"Resolution: {entry.get('resolution', 'N/A')}") | |
print(f"Aspect Ratio: {entry.get('aspect_ratio', 'N/A')}") | |
print(f"Video Codec: {entry.get('vcodec', 'N/A')}") | |
print(f"Audio Codec: {entry.get('acodec', 'N/A')}") | |
print("==============================\n") | |
gallery_items.append((thumbnail_url, video_id, video_title)) | |
detailed_entries.append(entry) | |
else: | |
logging.warning("No entries found in search result.") | |
return gallery_items, "" | |
except Exception as e: | |
error_message = f"Error during YouTube yt-dlp request: {e}" | |
logging.error(error_message) | |
return [], error_message | |
# Function to display the video using the video URL | |
def show_video(video_url): | |
video_id = None | |
patterns = [ | |
r"youtube\.com/watch\?v=([^&?\/]+)", | |
r"youtube\.com/embed/([^&?\/]+)", | |
r"youtube\.com/v/([^&?\/]+)", | |
r"youtu\.be/([^&?\/]+)" | |
] | |
for pattern in patterns: | |
match = re.search(pattern, video_url) | |
if match: | |
video_id = match.group(1) | |
logging.debug(f"Extracted video ID: {video_id}") | |
break | |
if not video_id: | |
logging.error("Invalid YouTube URL. Please enter a valid YouTube video link.") | |
return "Invalid YouTube URL. Please enter a valid YouTube video link." | |
embed_url = f"https://www.youtube.com/embed/{video_id}" | |
logging.debug(f"Embed URL generated: {embed_url}") | |
html_code = f''' | |
<iframe width="560" height="315" src="{embed_url}" | |
frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" | |
allowfullscreen></iframe> | |
''' | |
return html_code | |
# Create the Gradio interface | |
with gr.Blocks() as demo: | |
gr.Markdown("## YouTube Video Search, Selection, and Playback") | |
with gr.Row(): | |
with gr.Column(scale=3): | |
search_query_input = gr.Textbox(label="Search YouTube", placeholder="Enter your search query here") | |
search_button = gr.Button("Search") | |
search_output = gr.Gallery(label="Search Results", columns=5, height="1500px") | |
error_output = gr.Textbox(label="Error Message", interactive=False, visible=False) | |
with gr.Column(scale=2): | |
selected_video_link = gr.Textbox(label="Selected Video Link", interactive=False) | |
play_video_button = gr.Button("Play Video") | |
video_output = gr.HTML(label="Video Player") | |
# Define search button behavior | |
def update_search_results(query): | |
gallery_items, error_message = youtube_search(query) | |
if error_message: | |
return [], error_message, gr.update(visible=True) | |
gallery_items_display = [(item[0], item[1]) for item in gallery_items] | |
return gallery_items_display, "", gr.update(visible=False) | |
# Update the selected video link field when a video is clicked in the gallery | |
def on_video_select(evt: gr.SelectData): | |
selected_video_id = evt.value["caption"] | |
video_url = f"https://www.youtube.com/watch?v={selected_video_id}" | |
logging.debug(f"Video selected: {video_url}") | |
return video_url | |
# Play the video when the Play Video button is clicked | |
def play_video(video_url): | |
logging.debug(f"Playing video with URL: {video_url}") | |
return show_video(video_url) | |
search_button.click(update_search_results, inputs=search_query_input, outputs=[search_output, error_output, error_output]) | |
search_output.select(on_video_select, inputs=None, outputs=selected_video_link) | |
play_video_button.click(play_video, inputs=selected_video_link, outputs=video_output) | |
# Launch the Gradio interface | |
demo.launch() | |