Realistvik0 commited on
Commit
a9e8b4e
·
verified ·
1 Parent(s): dafaa11

Create youtube_transcript.py

Browse files
Files changed (1) hide show
  1. tools/youtube_transcript.py +91 -0
tools/youtube_transcript.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from smolagents.tools import Tool
3
+
4
+
5
+ class YouTubeTranscriptTool(Tool):
6
+ name = "youtube_transcript"
7
+ description = (
8
+ "Fetches the spoken transcript of a YouTube video. "
9
+ "Use this for ANY question about the content of a YouTube video — "
10
+ "what is said, shown, demonstrated, or described in it. "
11
+ "Pass the full YouTube URL or just the video ID."
12
+ )
13
+ inputs = {
14
+ "url": {
15
+ "type": "string",
16
+ "description": (
17
+ "The YouTube video URL (e.g. https://www.youtube.com/watch?v=XXXXXXXXXXX) "
18
+ "or bare video ID (e.g. XXXXXXXXXXX)."
19
+ ),
20
+ }
21
+ }
22
+ output_type = "string"
23
+
24
+ def __init__(self, *args, **kwargs):
25
+ self.is_initialized = False
26
+
27
+ def forward(self, url: str) -> str:
28
+ try:
29
+ from youtube_transcript_api import YouTubeTranscriptApi
30
+ from youtube_transcript_api._errors import (
31
+ TranscriptsDisabled,
32
+ NoTranscriptFound,
33
+ VideoUnavailable,
34
+ )
35
+ except ImportError:
36
+ return (
37
+ "youtube-transcript-api is not installed. "
38
+ "Add 'youtube-transcript-api' to requirements.txt and rebuild."
39
+ )
40
+
41
+ # Extract video ID from a full URL or accept a bare ID
42
+ video_id = self._extract_video_id(url.strip())
43
+ if not video_id:
44
+ return f"Could not extract a YouTube video ID from: {url}"
45
+
46
+ try:
47
+ # Prefer English; fall back to any available language
48
+ transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
49
+
50
+ try:
51
+ transcript = transcript_list.find_transcript(["en", "en-US", "en-GB"])
52
+ except NoTranscriptFound:
53
+ # Take whatever is available
54
+ transcript = next(iter(transcript_list))
55
+
56
+ entries = transcript.fetch()
57
+ text = " ".join(entry["text"] for entry in entries)
58
+
59
+ # Truncate to a reasonable size for the agent's context window
60
+ if len(text) > 12000:
61
+ text = text[:12000] + "\n\n[Transcript truncated at 12,000 characters]"
62
+
63
+ return text
64
+
65
+ except TranscriptsDisabled:
66
+ return (
67
+ f"Transcripts are disabled for video {video_id}. "
68
+ "Try searching for the video title or description instead."
69
+ )
70
+ except VideoUnavailable:
71
+ return f"Video {video_id} is unavailable or does not exist."
72
+ except NoTranscriptFound:
73
+ return (
74
+ f"No transcript found for video {video_id}. "
75
+ "The video may not have captions."
76
+ )
77
+ except Exception as e:
78
+ return f"Could not retrieve transcript for {video_id}: {e}"
79
+
80
+ @staticmethod
81
+ def _extract_video_id(url: str) -> str:
82
+ """Return the 11-character YouTube video ID from a URL or bare ID."""
83
+ patterns = [
84
+ r"(?:v=|youtu\.be/|embed/|shorts/)([A-Za-z0-9_-]{11})",
85
+ r"^([A-Za-z0-9_-]{11})$", # bare ID
86
+ ]
87
+ for pattern in patterns:
88
+ match = re.search(pattern, url)
89
+ if match:
90
+ return match.group(1)
91
+ return ""