Skip to content

Commit 41665bb

Browse files
Add yt_playlist_video_downloader Project
1 parent 0f1dcbe commit 41665bb

2 files changed

Lines changed: 381 additions & 0 deletions

File tree

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
# YOUTUBE PLAYLIST/VIDEO DOWNLOADER
2+
3+
A Python CLI tool that downloads entire YouTube playlists or single videos in the highest quality possible, with automatic merging of video and audio streams (if ffmpeg is installed). Built on yt-dlp -- fast, reliable, and actively maintained.
4+
5+
## FEATURES
6+
7+
* * * * *
8+
9+
- Download entire playlists or single videos with one command.
10+
11+
- Highest quality -- selects the best video + best audio streams and merges them into a single MP4 (requires ffmpeg).
12+
13+
- Fallback to H.264 -- force a lighter, widely‑compatible codec to avoid playback lag.
14+
15+
- Limit the number of videos downloaded from a playlist.
16+
17+
- Skip existing files -- no duplicate downloads.
18+
19+
- Progress bar during download.
20+
21+
- Works with private/unlisted playlists (as long as you have access).
22+
23+
## REQUIREMENTS
24+
25+
* * * * *
26+
27+
- Python 3.6+
28+
29+
- yt-dlp -- installed via pip
30+
31+
- ffmpeg (optional but highly recommended for best quality) -- installed separately
32+
33+
## INSTALLATION
34+
35+
* * * * *
36+
37+
1. Install Python dependencies:
38+
```bash
39+
pip install yt-dlp
40+
```
41+
42+
2. Install FFmpeg (for merging highest quality streams):
43+
44+
- Windows: Download from [gyan.dev](https://gyan.dev/) (choose correct architecture -- 64‑bit or 32‑bit). Extract, then add the bin folder to your system PATH. Verify with: `ffmpeg -version` in a new Command Prompt.
45+
46+
- macOS: `brew install ffmpeg`
47+
48+
- Linux (Debian/Ubuntu): `sudo apt update && sudo apt install ffmpeg`
49+
50+
- Linux (Fedora): `sudo dnf install ffmpeg`
51+
52+
Without ffmpeg, the script falls back to a single‑stream format (usually 720p or lower). For maximum quality, install it.
53+
54+
## USAGE
55+
56+
* * * * *
57+
58+
`python main.py <URL> [options]`
59+
60+
Required argument:
61+
URL -- YouTube video or playlist URL (must contain "list=" for playlists)
62+
63+
Optional arguments:
64+
-o, --output DIR -- Output directory (default: current folder)
65+
-n, --limit N -- Download only the first N videos (playlist only)
66+
-q, --quality Q -- Override format filter (see examples below)
67+
-v, --verbose -- Show detailed download logs
68+
69+
## EXAMPLES
70+
71+
* * * * *
72+
73+
1. Download an entire playlist (highest quality):
74+
```bash
75+
python main.py "[https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx](https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx)" -o ./videos
76+
```
77+
78+
2. Download only the first 5 videos from a playlist:
79+
```bash
80+
python main.py "[https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx](https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx)" -n 5 -o ./videos
81+
```
82+
83+
3. Download a single video:
84+
```bash
85+
python main.py "[https://www.youtube.com/watch?v=abc123](https://www.youtube.com/watch?v=abc123)" -o ./videos
86+
```
87+
88+
4. Force 1080p H.264 (smooth playback on any device):
89+
```bash
90+
python main.py "URL" -q "bestvideo[height<=1080][vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[height<=1080][vcodec^=avc1]" -o ./videos
91+
```
92+
93+
5. Force 720p H.264 (lightweight, fast download):
94+
```bash
95+
python main.py "URL" -q "bestvideo[height<=720][vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[height<=720][vcodec^=avc1]" -o ./videos
96+
```
97+
98+
6. Use verbose mode to debug:
99+
```bash
100+
python main.py "URL" -v
101+
```
102+
103+
## HOW IT WORKS
104+
105+
* * * * *
106+
107+
1. The script fetches the playlist or video metadata.
108+
109+
2. If ffmpeg is present, it downloads the best video and best audio streams separately, then merges them into an MP4.
110+
111+
3. If ffmpeg is missing, it falls back to the "best" single‑stream format (quality may be lower).
112+
113+
4. Videos are saved in a folder named after the playlist (or "Videos/" for single videos) inside your output directory.
114+
115+
## TROUBLESHOOTING
116+
117+
* * * * *
118+
119+
- Only 1 video downloads: Make sure your URL contains "&list=" or is the "/playlist?list=" page -- you are probably pointing to a single video.
120+
121+
- Error: 'list' is not recognized: You forgot to put the URL in double quotes. Always wrap the URL in quotes on Windows.
122+
123+
- Video lags in VLC: You are likely playing a VP9 or HEVC (H.265) video that your hardware can't decode. Fix: Force H.264 with the -q filter (see examples above) or enable hardware acceleration in VLC (Tools -> Preferences -> Input/Codecs -> Video codecs -> FFmpeg -> Hardware decoding -> DirectX/D3D11).
124+
125+
- ffmpeg not found: Install FFmpeg and add it to your system PATH. Restart your terminal after installation.
126+
127+
- Can't delete downloaded videos: Close VLC and any other media player. Then use the command: `rmdir /s /q "folder_path"` (Windows) or `rm -rf folder_path` (macOS/Linux).
128+
129+
## LICENSE
130+
131+
* * * * *
132+
133+
This script is free to use and modify. No warranty -- use at your own risk.
134+
135+
## ACKNOWLEDGEMENTS
136+
137+
* * * * *
138+
139+
- yt-dlp (https://github.com/yt-dlp/yt-dlp) -- the powerhouse behind the downloads.
140+
141+
- FFmpeg (https://ffmpeg.org/) -- for merging streams.
142+
143+
This script and its documentation were created with the assistance of an AI tool (DeepSeek) to ensure clarity and completeness.
144+
145+
Happy downloading!
146+
147+
## REQUIREMENTS
148+
149+
* * * * *
150+
151+
- Python 3.6+
152+
153+
- yt-dlp -- installed via pip
154+
155+
- ffmpeg (optional but highly recommended for best quality) -- installed separately
156+
157+
## INSTALLATION
158+
159+
* * * * *
160+
161+
1. Install Python dependencies:\
162+
pip install yt-dlp
163+
164+
2. Install FFmpeg (for merging highest quality streams):
165+
166+
- Windows: Download from [gyan.dev](https://gyan.dev/) (choose correct architecture -- 64‑bit or 32‑bit). Extract, then add the bin folder to your system PATH. Verify with: ffmpeg -version in a new Command Prompt.
167+
168+
- macOS: brew install ffmpeg
169+
170+
- Linux (Debian/Ubuntu): sudo apt update && sudo apt install ffmpeg
171+
172+
- Linux (Fedora): sudo dnf install ffmpeg
173+
174+
Without ffmpeg, the script falls back to a single‑stream format (usually 720p or lower). For maximum quality, install it.
175+
176+
## USAGE
177+
178+
* * * * *
179+
180+
python main.py <URL> [options]
181+
182+
Required argument:\
183+
URL -- YouTube video or playlist URL (must contain "list=" for playlists)
184+
185+
Optional arguments:\
186+
-o, --output DIR -- Output directory (default: current folder)\
187+
-n, --limit N -- Download only the first N videos (playlist only)\
188+
-q, --quality Q -- Override format filter (see examples below)\
189+
-v, --verbose -- Show detailed download logs
190+
191+
## EXAMPLES
192+
193+
* * * * *
194+
195+
1. Download an entire playlist (highest quality):\
196+
```bash
197+
python main.py "<https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx>" -o ./videos
198+
```
199+
2. Download only the first 5 videos from a playlist:\
200+
```bash
201+
python main.py "<https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx>" -n 5 -o ./videos
202+
```
203+
3. Download a single video:\
204+
```bash
205+
python main.py "<https://www.youtube.com/watch?v=abc123>" -o ./videos
206+
```
207+
4. Force 1080p H.264 (smooth playback on any device):\
208+
```bash
209+
python main.py "URL" -q "bestvideo[height<=1080][vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[height<=1080][vcodec^=avc1]" -o ./videos
210+
```
211+
212+
5. Force 720p H.264 (lightweight, fast download):\
213+
```bash
214+
python main.py "URL" -q "bestvideo[height<=720][vcodec^=avc1]+bestaudio[acodec^=mp4a]/best[height<=720][vcodec^=avc1]" -o ./videos
215+
```
216+
217+
6. Use verbose mode to debug:\
218+
```bash
219+
python main.py "URL" -v
220+
```
221+
222+
## HOW IT WORKS
223+
224+
* * * * *
225+
226+
1. The script fetches the playlist or video metadata.
227+
228+
2. If ffmpeg is present, it downloads the best video and best audio streams separately, then merges them into an MP4.
229+
230+
3. If ffmpeg is missing, it falls back to the "best" single‑stream format (quality may be lower).
231+
232+
4. Videos are saved in a folder named after the playlist (or "Videos/" for single videos) inside your output directory.
233+
234+
## TROUBLESHOOTING
235+
236+
* * * * *
237+
238+
- Only 1 video downloads: Make sure your URL contains "&list=" or is the "/playlist?list=" page -- you are probably pointing to a single video.
239+
240+
- Error: 'list' is not recognized: You forgot to put the URL in double quotes. Always wrap the URL in quotes on Windows.
241+
242+
- Video lags in VLC: You are likely playing a VP9 or HEVC (H.265) video that your hardware can't decode. Fix: Force H.264 with the -q filter (see examples above) or enable hardware acceleration in VLC (Tools -> Preferences -> Input/Codecs -> Video codecs -> FFmpeg -> Hardware decoding -> DirectX/D3D11).
243+
244+
- ffmpeg not found: Install FFmpeg and add it to your system PATH. Restart your terminal after installation.
245+
246+
- Can't delete downloaded videos: Close VLC and any other media player. Then use the command: rmdir /s /q "folder_path" (Windows) or rm -rf folder_path (macOS/Linux).
247+
248+
## LICENSE
249+
250+
* * * * *
251+
252+
This script is free to use and modify. No warranty -- use at your own risk.
253+
254+
## ACKNOWLEDGEMENTS
255+
256+
* * * * *
257+
258+
- yt-dlp (<https://github.com/yt-dlp/yt-dlp>) -- the powerhouse behind the downloads.
259+
260+
- FFmpeg (<https://ffmpeg.org/>) -- for merging streams.
261+
262+
This script and its documentation were created with the assistance of an AI tool (DeepSeek) to ensure clarity and completeness.
263+
264+
Happy downloading!
265+
266+
* * * * *
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env python3
2+
"""
3+
YouTube Playlist/Video Downloader – Highest Quality with FFmpeg.
4+
"""
5+
6+
import os
7+
import sys
8+
import argparse
9+
import subprocess
10+
from pathlib import Path
11+
12+
try:
13+
import yt_dlp
14+
except ImportError:
15+
print("ERROR: yt-dlp is not installed. Run: pip install yt-dlp")
16+
sys.exit(1)
17+
18+
def check_ffmpeg():
19+
"""Return True if ffmpeg is available and working."""
20+
try:
21+
subprocess.run(["ffmpeg", "-version"], capture_output=True, check=True, timeout=5)
22+
return True
23+
except (subprocess.SubprocessError, FileNotFoundError, OSError, subprocess.TimeoutExpired):
24+
return False
25+
26+
def get_playlist_info(url):
27+
with yt_dlp.YoutubeDL({'quiet': True, 'extract_flat': True}) as ydl:
28+
try:
29+
info = ydl.extract_info(url, download=False)
30+
if 'entries' in info:
31+
return info.get('title', 'Playlist'), len(info['entries'])
32+
else:
33+
return None, 1
34+
except Exception as e:
35+
print(f"Could not fetch playlist info: {e}")
36+
return None, 1
37+
38+
def progress_hook(d):
39+
if d['status'] == 'downloading':
40+
p = d.get('_percent_str', '0%').strip()
41+
s = d.get('_speed_str', 'N/A').strip()
42+
e = d.get('_eta_str', 'N/A').strip()
43+
print(f"\rDownloading: {p} at {s}, ETA: {e}", end='')
44+
elif d['status'] == 'finished':
45+
print("\nDownload completed, now processing...")
46+
47+
def download_playlist(url, output_dir, limit=None, quality=None):
48+
Path(output_dir).mkdir(parents=True, exist_ok=True)
49+
50+
# Check for ffmpeg
51+
has_ffmpeg = check_ffmpeg()
52+
if not has_ffmpeg:
53+
print(" ffmpeg is not installed or not working properly!")
54+
print(" Without ffmpeg, we cannot merge separate video+audio streams.")
55+
print(" Falling back to 'best' format (a single stream, may be lower quality).")
56+
print(" For best quality, install ffmpeg from https://ffmpeg.org/ and add it to PATH.\n")
57+
if quality is None:
58+
quality = "best"
59+
else:
60+
print(" ffmpeg found – will merge best video and audio streams.\n")
61+
if quality is None:
62+
quality = "bestvideo+bestaudio/best"
63+
64+
# Get playlist info
65+
playlist_title, count = get_playlist_info(url)
66+
if playlist_title:
67+
safe_title = "".join(c for c in playlist_title if c.isalnum() or c in " -_").strip() or "Playlist"
68+
subfolder = safe_title
69+
outtmpl = os.path.join(output_dir, subfolder, '%(playlist_index)s - %(title)s.%(ext)s')
70+
print(f" Playlist: {playlist_title} ({count} videos)")
71+
else:
72+
subfolder = "Videos"
73+
outtmpl = os.path.join(output_dir, subfolder, '%(title)s.%(ext)s')
74+
print(" Single video download")
75+
76+
ydl_opts = {
77+
'format': quality,
78+
'outtmpl': outtmpl,
79+
'merge_output_format': 'mp4',
80+
'ignoreerrors': True,
81+
'nooverwrites': True,
82+
'quiet': False,
83+
'progress_hooks': [progress_hook],
84+
}
85+
86+
if limit and playlist_title:
87+
ydl_opts['playlistend'] = limit
88+
print(f" Limiting to first {limit} videos")
89+
90+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
91+
try:
92+
print(f"\n Fetching: {url}\n")
93+
ydl.download([url])
94+
print("\n All downloads completed!")
95+
except Exception as e:
96+
print(f"\n An error occurred: {e}")
97+
sys.exit(1)
98+
99+
def main():
100+
parser = argparse.ArgumentParser(description="Download YouTube playlist/video in highest quality.")
101+
parser.add_argument("url", help="Playlist or video URL (must include 'list=' for playlists)")
102+
parser.add_argument("-o", "--output", default=".", help="Output directory (default: current)")
103+
parser.add_argument("-n", "--limit", type=int, help="Max number of videos to download (playlist only)")
104+
parser.add_argument("-q", "--quality", default=None, help="Override format (e.g., 'bestvideo[height<=1080]+bestaudio')")
105+
parser.add_argument("-v", "--verbose", action="store_true", help="Show debug logs")
106+
args = parser.parse_args()
107+
108+
if args.verbose:
109+
import logging
110+
logging.basicConfig(level=logging.DEBUG)
111+
112+
download_playlist(args.url, args.output, args.limit, args.quality)
113+
114+
if __name__ == "__main__":
115+
main()

0 commit comments

Comments
 (0)