lucas-ventura commited on
Commit
68c9ac7
·
verified ·
1 Parent(s): 9ed896f

Create video.py

Browse files
Files changed (1) hide show
  1. tools/download/video.py +146 -0
tools/download/video.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ from contextlib import redirect_stderr
3
+ from tempfile import mkdtemp
4
+ from typing import List
5
+
6
+ import yt_dlp
7
+ from yt_dlp import YoutubeDL
8
+ from yt_dlp.postprocessor import PostProcessor
9
+
10
+
11
+ class FilenameCollectorPP(PostProcessor):
12
+ def __init__(self):
13
+ super(FilenameCollectorPP, self).__init__(None)
14
+ self.filenames = []
15
+
16
+ def run(self, information):
17
+ self.filenames.append(information["filepath"])
18
+ return [], information
19
+
20
+
21
+ def download_url(
22
+ url: str,
23
+ maxDuration: int = None,
24
+ destinationDirectory: str = None,
25
+ playlistItems: str = "1",
26
+ cookies_from_browser: str = None,
27
+ ) -> List[str]:
28
+ try:
29
+ return _perform_download(
30
+ url,
31
+ maxDuration=maxDuration,
32
+ outputTemplate=None,
33
+ destinationDirectory=destinationDirectory,
34
+ playlistItems=playlistItems,
35
+ cookies_from_browser=cookies_from_browser,
36
+ )
37
+ except yt_dlp.utils.DownloadError as e:
38
+ # In case of an OS error, try again with a different output template
39
+ if e.msg and e.msg.find("[Errno 36] File name too long") >= 0:
40
+ return _perform_download(
41
+ url,
42
+ maxDuration=maxDuration,
43
+ outputTemplate="%(title).10s %(id)s.%(ext)s",
44
+ cookies_from_browser=cookies_from_browser,
45
+ )
46
+ raise
47
+
48
+
49
+ def _perform_download(
50
+ url: str,
51
+ maxDuration: int = None,
52
+ outputTemplate: str = None,
53
+ destinationDirectory: str = None,
54
+ playlistItems: str = "1",
55
+ onlyAudio: bool = False,
56
+ cookies_from_browser: str = None,
57
+ ):
58
+ # Create a temporary directory to store the downloaded files
59
+ if destinationDirectory is None:
60
+ destinationDirectory = mkdtemp()
61
+
62
+ ydl_opts = {
63
+ "format": "bestaudio/best"
64
+ if onlyAudio
65
+ else "bestvideo[ext=mp4][vcodec^=avc1]+bestaudio[ext=m4a]/best",
66
+ "paths": {"home": destinationDirectory},
67
+ "ignoreerrors": True,
68
+ }
69
+
70
+ if playlistItems:
71
+ ydl_opts["playlist_items"] = playlistItems
72
+
73
+ if cookies_from_browser:
74
+ ydl_opts["cookies_from_browser"] = cookies_from_browser
75
+
76
+ # Add output template if specified
77
+ if outputTemplate:
78
+ ydl_opts["outtmpl"] = outputTemplate
79
+
80
+ errStrIO = EventStringIO(on_write=lambda text: print(f"\033[91m{text}\033[0m"))
81
+
82
+ filename_collector = FilenameCollectorPP()
83
+ with redirect_stderr(errStrIO):
84
+ for _ in (True,):
85
+ with YoutubeDL(ydl_opts) as ydl:
86
+ if maxDuration and maxDuration > 0:
87
+ info = ydl.extract_info(url, download=False)
88
+ if not info:
89
+ break
90
+
91
+ entries = "entries" in info and info["entries"] or [info]
92
+
93
+ total_duration = 0
94
+
95
+ # Compute total duration
96
+ for entry in entries:
97
+ if entry:
98
+ total_duration += float(entry["duration"])
99
+
100
+ if total_duration >= maxDuration:
101
+ raise ExceededMaximumDuration(
102
+ videoDuration=total_duration,
103
+ maxDuration=maxDuration,
104
+ message="Video is too long",
105
+ )
106
+
107
+ ydl.add_post_processor(filename_collector)
108
+ ydl.download([url])
109
+
110
+ errMsg = errStrIO.getvalue()
111
+ errMsg = (
112
+ [text for text in errMsg.split("\n") if text.startswith("ERROR")]
113
+ if errMsg
114
+ else ""
115
+ )
116
+
117
+ if len(filename_collector.filenames) <= 0:
118
+ raise Exception(
119
+ f"Cannot download {url}, " + "\n".join(errMsg) if errMsg else ""
120
+ )
121
+
122
+ result = []
123
+
124
+ for filename in filename_collector.filenames:
125
+ result.append(filename)
126
+ print("Downloaded " + filename)
127
+
128
+ return result
129
+
130
+
131
+ class ExceededMaximumDuration(Exception):
132
+ def __init__(self, videoDuration, maxDuration, message):
133
+ self.videoDuration = videoDuration
134
+ self.maxDuration = maxDuration
135
+ super().__init__(message)
136
+
137
+
138
+ class EventStringIO(io.StringIO):
139
+ def __init__(self, on_write=None, *args, **kwargs):
140
+ super().__init__(*args, **kwargs)
141
+ self.on_write = on_write
142
+
143
+ def write(self, text):
144
+ super().write(text)
145
+ if self.on_write:
146
+ self.on_write(text)