-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformat_manager.py
More file actions
134 lines (111 loc) · 5.02 KB
/
format_manager.py
File metadata and controls
134 lines (111 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# ===============================================
# format_manager.py
# Handles format selection, audio-only, subtitles
# ===============================================
import yt_dlp
from rich.console import Console
from rich.table import Table
# Force colors even if stdout is not a tty
console = Console(force_terminal=True)
def choose_format_and_postprocessors(url):
try:
with console.status("[cyan]Fetching available formats... please wait[/cyan]", spinner="dots"):
with yt_dlp.YoutubeDL({"quiet": True, "no_warnings": True}) as ydl:
info = ydl.extract_info(url, download=False)
formats = info.get("formats", [])
except Exception as e:
console.print(f"[red]Failed to fetch formats: {e}[/red]")
return "bestvideo+bestaudio/best", []
# Split into video and audio
video_formats = [f for f in formats if f.get("vcodec") != "none"]
audio_formats = [f for f in formats if f.get("acodec") != "none" and f.get("vcodec") == "none"]
# Add conversion choices (mp3, m4a, opus)
conversion_options = [
{"format_id": "conv-mp3", "ext": "mp3", "acodec": "mp3", "abr": "192", "note": "Extract & Convert"},
{"format_id": "conv-m4a", "ext": "m4a", "acodec": "aac", "abr": "192", "note": "Extract & Convert"},
{"format_id": "conv-opus", "ext": "opus", "acodec": "opus", "abr": "192", "note": "Extract & Convert"},
]
audio_formats.extend(conversion_options)
# Unified formats table
all_formats = video_formats + audio_formats
table = Table(title="Available Formats (Video + Audio + Conversions)")
table.add_column("Idx", justify="right", width=4)
table.add_column("format_id", width=12)
table.add_column("ext", width=6)
table.add_column("res/note", width=12)
table.add_column("vcodec", width=10)
table.add_column("acodec", width=10)
table.add_column("abr/bitrate", width=12)
table.add_column("fps", width=6)
table.add_column("size", width=10)
for i, f in enumerate(all_formats, 1):
size = f.get("filesize") or f.get("filesize_approx")
size_str = f"{round(size/1024/1024,1)} MB" if size else "?"
table.add_row(
str(i),
str(f.get("format_id")),
f.get("ext", ""),
f.get("format_note") or (str(f.get("height")) + "p" if f.get("height") else f.get("note", "-")),
f.get("vcodec", "-"),
f.get("acodec", "-"),
str(f.get("abr") or f.get("tbr") or "-"),
str(f.get("fps") or "-"),
size_str,
)
console.print(table)
# Prompt
console.print("[cyan]Options:[/cyan] "
"[green]B[/green]=Best (video+audio) "
"[green]Index[/green]=Enter table index directly "
"[green]C[/green]=Custom code "
"[green]BACK[/green]=Go back")
while True:
choice = console.input("> ").strip().lower()
# Best
if choice == "b":
return "bestvideo+bestaudio/best", []
# Index direct (user typed number)
if choice.isdigit():
idxn = int(choice) - 1
if 0 <= idxn < len(all_formats):
fmt = all_formats[idxn]
fmtid = str(fmt.get("format_id"))
# Conversion entry
if fmtid.startswith("conv-"):
codec = fmt["ext"]
postp = [{"key": "FFmpegExtractAudio", "preferredcodec": codec, "preferredquality": "192"}]
return "bestaudio/best", postp
# Normal video → always merge with bestaudio
if fmt.get("vcodec") != "none":
return f"{fmtid}+bestaudio/best", []
# Pure audio
return fmtid, []
else:
console.print("[yellow]Index out of range.[/yellow]")
continue
# Custom code
if choice == "c":
code = console.input("Enter custom yt-dlp format code (or BACK): ").strip()
if code.lower() == "back" or not code:
continue
# Always merge with bestaudio
return f"{code}+bestaudio/best", []
# Back
if choice == "back":
return None, None
console.print("[yellow]Unknown option[/yellow]")
def ask_subtitles_options():
subs_opts = {}
ch = console.input("[cyan]Download subtitles? (Y/N/B=back): [/cyan]").strip().lower()
if ch == "y":
lang = console.input("[cyan]Enter subtitle language code(s), comma separated (default: en): [/cyan]").strip()
if not lang:
lang = "en"
langs = [l.strip() for l in lang.split(",") if l.strip()]
subs_opts["writesubtitles"] = True
subs_opts["writeautomaticsub"] = True
subs_opts["subtitleslangs"] = langs
subs_opts["subtitlesformat"] = "srt"
elif ch == "b":
return "back"
return subs_opts