Spaces:
Sleeping
Sleeping
| import os | |
| import subprocess | |
| from yt_dlp import YoutubeDL | |
| from smolagents.tools import tool | |
| # Use FFmpeg to extract frames from the video | |
| def extract_frames_with_ffmpeg(video_path: str, num_frames: int) -> [str]: | |
| """Extract frames from video using FFmpeg""" | |
| if not os.path.exists(video_path): | |
| raise FileNotFoundError(f"Video file not found: {video_path}") | |
| # Get video duration using ffprobe | |
| duration_cmd = [ | |
| 'ffprobe', '-v', 'quiet', '-print_format', 'json', | |
| '-show_format', video_path | |
| ] | |
| try: | |
| result = subprocess.run(duration_cmd, capture_output=True, text=True, check=True) | |
| import json | |
| metadata = json.loads(result.stdout) | |
| duration = float(metadata['format']['duration']) | |
| # Calculate time intervals for frame extraction | |
| time_intervals = [duration * i / (num_frames + 1) for i in range(1, num_frames + 1)] | |
| extracted_files = [] | |
| for i, time_pos in enumerate(time_intervals): | |
| output_filename = f"{os.path.splitext(os.path.basename(video_path))[0]}_frame_{i+1:03d}.jpg" | |
| # Extract frame at specific time | |
| ffmpeg_cmd = [ | |
| 'ffmpeg', '-i', video_path, '-ss', str(time_pos), | |
| '-vframes', '1', '-q:v', '2', '-y', output_filename | |
| ] | |
| subprocess.run(ffmpeg_cmd, capture_output=True, check=True) | |
| extracted_files.append(output_filename) | |
| return extracted_files | |
| except subprocess.CalledProcessError as e: | |
| print(f"Error running FFmpeg: {e}") | |
| return [] | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| return [] | |
| def download_youtube_url_audio(url: str) -> str: | |
| """ | |
| Download a YouTube video using the url, extract the audio and return the path to the downloaded file. | |
| Args: | |
| url (str): The URL of the YouTube video to download. | |
| Returns: | |
| str: The path to the downloaded audio file. | |
| """ | |
| ydl_audio_opts = { | |
| 'format': 'bestaudio/best', | |
| 'postprocessors': [{ | |
| 'key': 'FFmpegExtractAudio', | |
| 'preferredcodec': 'mp3', | |
| 'preferredquality': '192', | |
| }], | |
| 'quiet': True, | |
| 'no_verbose_header': True, | |
| 'no_warnings': True, | |
| } | |
| with YoutubeDL(ydl_audio_opts) as ydl: | |
| file_path = ydl.extract_info(url) | |
| return file_path['requested_downloads'][0]['filepath'] | |
| def download_youtube_url_images(url: str, num_images: int = 3) -> str: | |
| """ | |
| Download a YouTube video using the url, extract the frames and return the path to the downloaded files. | |
| Args: | |
| url (str): The URL of the YouTube video to download. | |
| num_images (int): The number of images to download. The images are extracted from the video at regular intervals. | |
| Returns: | |
| str: The different paths to the downloaded frames, separated by newlines. | |
| """ | |
| # First, download the video | |
| ydl_images_opts = { | |
| 'format': 'best[height<=720]', # Download video in reasonable quality | |
| 'outtmpl': '%(title)s.%(ext)s', # Save with title as filename | |
| 'quiet': True, | |
| 'no_verbose_header': True, | |
| 'no_warnings': True, | |
| } | |
| with YoutubeDL(ydl_images_opts) as ydl: | |
| info = ydl.extract_info(url, download=True) | |
| video_filepath = ydl.prepare_filename(info) | |
| # Extract frames from the downloaded video | |
| if os.path.exists(video_filepath): | |
| extracted_frames = extract_frames_with_ffmpeg(video_filepath, num_images) | |
| return "\n".join(extracted_frames) | |
| return "" | |