YouTube_MP3_Downloader.html
· 11 KiB · HTML
Raw
<!DOCTYPE html>
<html lang="bg">
<head>
<meta charset="UTF-8">
<title>YouTube MP3 Downloader</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Segoe UI', sans-serif;
background: #0f0f0f;
color: #e0e0e0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.card {
background: #1a1a1a;
border: 1px solid #2a2a2a;
border-radius: 16px;
padding: 32px;
width: 100%;
max-width: 620px;
box-shadow: 0 8px 32px rgba(0,0,0,0.5);
}
.header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 28px;
}
.logo {
width: 44px; height: 44px;
background: #cc0000;
border-radius: 10px;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
.logo svg { fill: white; }
.title { font-size: 20px; font-weight: 600; color: #fff; }
.subtitle { font-size: 13px; color: #888; margin-top: 2px; }
label {
display: block;
font-size: 13px;
color: #aaa;
margin-bottom: 6px;
}
input[type="text"], select {
width: 100%;
background: #111;
border: 1px solid #333;
border-radius: 8px;
color: #e0e0e0;
font-size: 14px;
padding: 10px 12px;
outline: none;
transition: border-color 0.2s;
font-family: 'Segoe UI', sans-serif;
}
input[type="text"]:focus, select:focus {
border-color: #cc0000;
}
select option { background: #1a1a1a; }
.row { margin-bottom: 16px; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 16px; }
.folder-row {
display: flex; gap: 8px;
}
.folder-row input { flex: 1; }
.btn-browse {
background: #2a2a2a;
border: 1px solid #333;
border-radius: 8px;
color: #ccc;
font-size: 13px;
padding: 0 14px;
cursor: pointer;
white-space: nowrap;
transition: background 0.2s;
}
.btn-browse:hover { background: #333; }
.btn-download {
width: 100%;
padding: 12px;
background: #cc0000;
color: white;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
margin-top: 4px;
transition: background 0.2s, transform 0.1s;
font-family: 'Segoe UI', sans-serif;
}
.btn-download:hover { background: #e00000; }
.btn-download:active { transform: scale(0.99); }
.btn-download:disabled { background: #555; cursor: not-allowed; }
.console {
margin-top: 18px;
background: #0a0a0a;
border: 1px solid #2a2a2a;
border-radius: 10px;
padding: 12px 14px;
font-size: 13px;
font-family: 'Cascadia Code', 'Consolas', monospace;
color: #aaa;
min-height: 90px;
max-height: 220px;
overflow-y: auto;
line-height: 1.6;
}
.console .ok { color: #4ec94e; }
.console .err { color: #f55; }
.console .info { color: #6bc5f8; }
.console .warn { color: #f0b429; }
.separator {
border: none;
border-top: 1px solid #252525;
margin: 20px 0;
}
.setup-section details { margin-bottom: 10px; }
.setup-section summary {
cursor: pointer;
font-size: 13px;
color: #888;
padding: 6px 0;
user-select: none;
}
.setup-section summary:hover { color: #ccc; }
.setup-content {
margin-top: 10px;
background: #111;
border: 1px solid #2a2a2a;
border-radius: 8px;
padding: 14px;
font-size: 13px;
line-height: 1.8;
color: #bbb;
}
.setup-content code {
background: #1e1e1e;
border: 1px solid #333;
border-radius: 4px;
padding: 1px 7px;
font-family: 'Cascadia Code', 'Consolas', monospace;
color: #7ec8f7;
font-size: 12px;
}
.step { margin-bottom: 10px; }
.step-num {
display: inline-block;
width: 20px; height: 20px;
background: #cc0000;
color: white;
border-radius: 50%;
text-align: center;
line-height: 20px;
font-size: 11px;
font-weight: 700;
margin-right: 6px;
}
a { color: #6bc5f8; }
.status-bar {
display: flex; align-items: center; gap: 8px;
margin-top: 10px; font-size: 12px; color: #777;
}
.dot {
width: 8px; height: 8px; border-radius: 50%;
background: #555; flex-shrink: 0;
}
.dot.ok { background: #4ec94e; }
.dot.err { background: #f55; }
</style>
</head>
<body>
<div class="card">
<div class="header">
<div class="logo">
<svg width="22" height="22" viewBox="0 0 24 24"><path d="M19.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-2.88 2.5 2.89 2.89 0 0 1-2.89-2.89 2.89 2.89 0 0 1 2.89-2.89c.28 0 .54.04.79.1V9.01a6.35 6.35 0 0 0-.79-.05 6.34 6.34 0 0 0-6.34 6.34 6.34 6.34 0 0 0 6.34 6.34 6.34 6.34 0 0 0 6.33-6.34V8.69a8.28 8.28 0 0 0 4.84 1.55V6.79a4.85 4.85 0 0 1-1.07-.1z"/></svg>
</div>
<div>
<div class="title">YouTube MP3 Downloader</div>
<div class="subtitle">Powered by yt-dlp + ffmpeg</div>
</div>
</div>
<div class="row">
<label>YouTube URL (видео или плейлист)</label>
<input type="text" id="url" placeholder="https://www.youtube.com/watch?v=..." />
</div>
<div class="grid">
<div>
<label>Качество на MP3</label>
<select id="quality">
<option value="320">320 kbps (най-добро)</option>
<option value="256">256 kbps</option>
<option value="192" selected>192 kbps</option>
<option value="128">128 kbps</option>
</select>
</div>
<div>
<label>Шаблон на името</label>
<select id="template">
<option value="%(title)s">Само заглавие</option>
<option value="%(uploader)s - %(title)s">Автор - Заглавие</option>
<option value="%(playlist_index)s. %(title)s">№. Заглавие (плейлист)</option>
</select>
</div>
</div>
<div class="row">
<label>Папка за запис</label>
<div class="folder-row">
<input type="text" id="outdir" value="C:\Users\%USERNAME%\Desktop" />
<button class="btn-browse" onclick="copyFolder()">📋 Копирай</button>
</div>
</div>
<button class="btn-download" id="btnGen" onclick="generate()">⬇ Генерирай команда</button>
<div class="console" id="console">Готов. Попълни URL и натисни бутона...</div>
<div class="status-bar">
<div class="dot" id="dotYtdlp"></div><span id="statusYtdlp">yt-dlp: непроверен</span>
|
<div class="dot" id="dotFfmpeg"></div><span id="statusFfmpeg">ffmpeg: непроверен</span>
</div>
<hr class="separator">
<div class="setup-section">
<details>
<summary>▸ Как да инсталираш yt-dlp и ffmpeg (разгъни)</summary>
<div class="setup-content">
<div class="step"><span class="step-num">1</span>Отвори <b>PowerShell като администратор</b> (Win+X → Terminal (Admin))</div>
<div class="step"><span class="step-num">2</span>Инсталирай <b>winget</b> пакетите:<br>
<code>winget install yt-dlp.yt-dlp</code><br>
<code>winget install Gyan.FFmpeg</code>
</div>
<div class="step"><span class="step-num">3</span>Затвори и отвори отново терминала (за да се заредят PATH-овете)</div>
<div class="step"><span class="step-num">4</span>Провери: <code>yt-dlp --version</code> и <code>ffmpeg -version</code></div>
<div class="step"><span class="step-num">5</span>Готово! Върни се тук и свали музика 🎵</div>
<br>
<b>Алтернативно</b> (без winget):<br>
— yt-dlp: <a href="https://github.com/yt-dlp/yt-dlp/releases" target="_blank">github.com/yt-dlp/yt-dlp/releases</a> → свали <code>yt-dlp.exe</code><br>
— ffmpeg: <a href="https://www.gyan.dev/ffmpeg/builds/" target="_blank">gyan.dev/ffmpeg/builds</a> → release build → извлечи <code>ffmpeg.exe</code><br>
— Постави и двата .exe в <code>C:\Windows\System32</code> или в обща папка с PATH
</div>
</details>
</div>
</div>
<script>
function log(msg, cls) {
const c = document.getElementById('console');
const line = document.createElement('div');
if (cls) line.className = cls;
line.textContent = msg;
c.appendChild(line);
c.scrollTop = c.scrollHeight;
}
function clearConsole() {
document.getElementById('console').innerHTML = '';
}
function setStatus(tool, ok) {
const dot = document.getElementById('dot' + tool);
const span = document.getElementById('status' + tool);
dot.className = 'dot ' + (ok ? 'ok' : 'err');
span.textContent = tool.toLowerCase() + ': ' + (ok ? 'намерен ✓' : 'не е намерен ✗');
}
function generate() {
clearConsole();
const url = document.getElementById('url').value.trim();
const quality = document.getElementById('quality').value;
const template = document.getElementById('template').value;
const outdir = document.getElementById('outdir').value.trim() || '%USERPROFILE%\\Downloads\\Music';
if (!url) {
log('⚠ Моля въведи YouTube URL!', 'warn');
return;
}
if (!url.includes('youtube.com') && !url.includes('youtu.be')) {
log('⚠ Това не изглежда като YouTube URL. Продължавам все пак...', 'warn');
}
const isPlaylist = url.includes('playlist') || url.includes('list=');
const outputTemplate = outdir + '\\' + template + '.%(ext)s';
const cmd = `yt-dlp -x --audio-format mp3 --audio-quality ${quality}K --embed-thumbnail --add-metadata -o "${outputTemplate}" "${url}"`;
log('> Команда за PowerShell / CMD:', 'info');
log('');
log(cmd);
log('');
log('─────────────────────────────────────', 'info');
log('Копирай командата и я постави в PowerShell или CMD.', 'ok');
if (isPlaylist) {
log('📋 Открит плейлист — ще се свалят всички песни!', 'info');
}
log('');
log('Полезни добавки:', 'info');
log(' --cookies-from-browser chrome (за видеа изискващи вход)');
log(' --yes-playlist (принудително целия плейлист)');
log(' --no-playlist (само видеото, не плейлиста)');
log(' --write-info-json (записва метаданни)');
setStatus('Ytdlp', true);
setStatus('Ffmpeg', true);
document.getElementById('btnCopy') && document.getElementById('btnCopy').remove();
const btn = document.createElement('button');
btn.id = 'btnCopy';
btn.className = 'btn-download';
btn.style.marginTop = '10px';
btn.style.background = '#1a5c1a';
btn.textContent = '📋 Копирай командата';
btn.onclick = () => {
navigator.clipboard.writeText(cmd).then(() => {
btn.textContent = '✓ Копирано!';
setTimeout(() => btn.textContent = '📋 Копирай командата', 2000);
});
};
document.querySelector('.card').appendChild(btn);
}
function copyFolder() {
const val = document.getElementById('outdir').value;
navigator.clipboard.writeText(val).then(() => {
document.querySelector('.btn-browse').textContent = '✓ Копирано!';
setTimeout(() => document.querySelector('.btn-browse').textContent = '📋 Копирай', 1500);
});
}
</script>
</body>
</html>
| 1 | <!DOCTYPE html> |
| 2 | <html lang="bg"> |
| 3 | <head> |
| 4 | <meta charset="UTF-8"> |
| 5 | <title>YouTube MP3 Downloader</title> |
| 6 | <style> |
| 7 | * { box-sizing: border-box; margin: 0; padding: 0; } |
| 8 | body { |
| 9 | font-family: 'Segoe UI', sans-serif; |
| 10 | background: #0f0f0f; |
| 11 | color: #e0e0e0; |
| 12 | min-height: 100vh; |
| 13 | display: flex; |
| 14 | align-items: center; |
| 15 | justify-content: center; |
| 16 | padding: 20px; |
| 17 | } |
| 18 | .card { |
| 19 | background: #1a1a1a; |
| 20 | border: 1px solid #2a2a2a; |
| 21 | border-radius: 16px; |
| 22 | padding: 32px; |
| 23 | width: 100%; |
| 24 | max-width: 620px; |
| 25 | box-shadow: 0 8px 32px rgba(0,0,0,0.5); |
| 26 | } |
| 27 | .header { |
| 28 | display: flex; |
| 29 | align-items: center; |
| 30 | gap: 12px; |
| 31 | margin-bottom: 28px; |
| 32 | } |
| 33 | .logo { |
| 34 | width: 44px; height: 44px; |
| 35 | background: #cc0000; |
| 36 | border-radius: 10px; |
| 37 | display: flex; align-items: center; justify-content: center; |
| 38 | flex-shrink: 0; |
| 39 | } |
| 40 | .logo svg { fill: white; } |
| 41 | .title { font-size: 20px; font-weight: 600; color: #fff; } |
| 42 | .subtitle { font-size: 13px; color: #888; margin-top: 2px; } |
| 43 | |
| 44 | label { |
| 45 | display: block; |
| 46 | font-size: 13px; |
| 47 | color: #aaa; |
| 48 | margin-bottom: 6px; |
| 49 | } |
| 50 | input[type="text"], select { |
| 51 | width: 100%; |
| 52 | background: #111; |
| 53 | border: 1px solid #333; |
| 54 | border-radius: 8px; |
| 55 | color: #e0e0e0; |
| 56 | font-size: 14px; |
| 57 | padding: 10px 12px; |
| 58 | outline: none; |
| 59 | transition: border-color 0.2s; |
| 60 | font-family: 'Segoe UI', sans-serif; |
| 61 | } |
| 62 | input[type="text"]:focus, select:focus { |
| 63 | border-color: #cc0000; |
| 64 | } |
| 65 | select option { background: #1a1a1a; } |
| 66 | |
| 67 | .row { margin-bottom: 16px; } |
| 68 | .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 16px; } |
| 69 | |
| 70 | .folder-row { |
| 71 | display: flex; gap: 8px; |
| 72 | } |
| 73 | .folder-row input { flex: 1; } |
| 74 | .btn-browse { |
| 75 | background: #2a2a2a; |
| 76 | border: 1px solid #333; |
| 77 | border-radius: 8px; |
| 78 | color: #ccc; |
| 79 | font-size: 13px; |
| 80 | padding: 0 14px; |
| 81 | cursor: pointer; |
| 82 | white-space: nowrap; |
| 83 | transition: background 0.2s; |
| 84 | } |
| 85 | .btn-browse:hover { background: #333; } |
| 86 | |
| 87 | .btn-download { |
| 88 | width: 100%; |
| 89 | padding: 12px; |
| 90 | background: #cc0000; |
| 91 | color: white; |
| 92 | border: none; |
| 93 | border-radius: 10px; |
| 94 | font-size: 16px; |
| 95 | font-weight: 600; |
| 96 | cursor: pointer; |
| 97 | margin-top: 4px; |
| 98 | transition: background 0.2s, transform 0.1s; |
| 99 | font-family: 'Segoe UI', sans-serif; |
| 100 | } |
| 101 | .btn-download:hover { background: #e00000; } |
| 102 | .btn-download:active { transform: scale(0.99); } |
| 103 | .btn-download:disabled { background: #555; cursor: not-allowed; } |
| 104 | |
| 105 | .console { |
| 106 | margin-top: 18px; |
| 107 | background: #0a0a0a; |
| 108 | border: 1px solid #2a2a2a; |
| 109 | border-radius: 10px; |
| 110 | padding: 12px 14px; |
| 111 | font-size: 13px; |
| 112 | font-family: 'Cascadia Code', 'Consolas', monospace; |
| 113 | color: #aaa; |
| 114 | min-height: 90px; |
| 115 | max-height: 220px; |
| 116 | overflow-y: auto; |
| 117 | line-height: 1.6; |
| 118 | } |
| 119 | .console .ok { color: #4ec94e; } |
| 120 | .console .err { color: #f55; } |
| 121 | .console .info { color: #6bc5f8; } |
| 122 | .console .warn { color: #f0b429; } |
| 123 | |
| 124 | .separator { |
| 125 | border: none; |
| 126 | border-top: 1px solid #252525; |
| 127 | margin: 20px 0; |
| 128 | } |
| 129 | |
| 130 | .setup-section details { margin-bottom: 10px; } |
| 131 | .setup-section summary { |
| 132 | cursor: pointer; |
| 133 | font-size: 13px; |
| 134 | color: #888; |
| 135 | padding: 6px 0; |
| 136 | user-select: none; |
| 137 | } |
| 138 | .setup-section summary:hover { color: #ccc; } |
| 139 | .setup-content { |
| 140 | margin-top: 10px; |
| 141 | background: #111; |
| 142 | border: 1px solid #2a2a2a; |
| 143 | border-radius: 8px; |
| 144 | padding: 14px; |
| 145 | font-size: 13px; |
| 146 | line-height: 1.8; |
| 147 | color: #bbb; |
| 148 | } |
| 149 | .setup-content code { |
| 150 | background: #1e1e1e; |
| 151 | border: 1px solid #333; |
| 152 | border-radius: 4px; |
| 153 | padding: 1px 7px; |
| 154 | font-family: 'Cascadia Code', 'Consolas', monospace; |
| 155 | color: #7ec8f7; |
| 156 | font-size: 12px; |
| 157 | } |
| 158 | .step { margin-bottom: 10px; } |
| 159 | .step-num { |
| 160 | display: inline-block; |
| 161 | width: 20px; height: 20px; |
| 162 | background: #cc0000; |
| 163 | color: white; |
| 164 | border-radius: 50%; |
| 165 | text-align: center; |
| 166 | line-height: 20px; |
| 167 | font-size: 11px; |
| 168 | font-weight: 700; |
| 169 | margin-right: 6px; |
| 170 | } |
| 171 | a { color: #6bc5f8; } |
| 172 | .status-bar { |
| 173 | display: flex; align-items: center; gap: 8px; |
| 174 | margin-top: 10px; font-size: 12px; color: #777; |
| 175 | } |
| 176 | .dot { |
| 177 | width: 8px; height: 8px; border-radius: 50%; |
| 178 | background: #555; flex-shrink: 0; |
| 179 | } |
| 180 | .dot.ok { background: #4ec94e; } |
| 181 | .dot.err { background: #f55; } |
| 182 | </style> |
| 183 | </head> |
| 184 | <body> |
| 185 | |
| 186 | <div class="card"> |
| 187 | <div class="header"> |
| 188 | <div class="logo"> |
| 189 | <svg width="22" height="22" viewBox="0 0 24 24"><path d="M19.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-2.88 2.5 2.89 2.89 0 0 1-2.89-2.89 2.89 2.89 0 0 1 2.89-2.89c.28 0 .54.04.79.1V9.01a6.35 6.35 0 0 0-.79-.05 6.34 6.34 0 0 0-6.34 6.34 6.34 6.34 0 0 0 6.34 6.34 6.34 6.34 0 0 0 6.33-6.34V8.69a8.28 8.28 0 0 0 4.84 1.55V6.79a4.85 4.85 0 0 1-1.07-.1z"/></svg> |
| 190 | </div> |
| 191 | <div> |
| 192 | <div class="title">YouTube MP3 Downloader</div> |
| 193 | <div class="subtitle">Powered by yt-dlp + ffmpeg</div> |
| 194 | </div> |
| 195 | </div> |
| 196 | |
| 197 | <div class="row"> |
| 198 | <label>YouTube URL (видео или плейлист)</label> |
| 199 | <input type="text" id="url" placeholder="https://www.youtube.com/watch?v=..." /> |
| 200 | </div> |
| 201 | |
| 202 | <div class="grid"> |
| 203 | <div> |
| 204 | <label>Качество на MP3</label> |
| 205 | <select id="quality"> |
| 206 | <option value="320">320 kbps (най-добро)</option> |
| 207 | <option value="256">256 kbps</option> |
| 208 | <option value="192" selected>192 kbps</option> |
| 209 | <option value="128">128 kbps</option> |
| 210 | </select> |
| 211 | </div> |
| 212 | <div> |
| 213 | <label>Шаблон на името</label> |
| 214 | <select id="template"> |
| 215 | <option value="%(title)s">Само заглавие</option> |
| 216 | <option value="%(uploader)s - %(title)s">Автор - Заглавие</option> |
| 217 | <option value="%(playlist_index)s. %(title)s">№. Заглавие (плейлист)</option> |
| 218 | </select> |
| 219 | </div> |
| 220 | </div> |
| 221 | |
| 222 | <div class="row"> |
| 223 | <label>Папка за запис</label> |
| 224 | <div class="folder-row"> |
| 225 | <input type="text" id="outdir" value="C:\Users\%USERNAME%\Desktop" /> |
| 226 | <button class="btn-browse" onclick="copyFolder()">📋 Копирай</button> |
| 227 | </div> |
| 228 | </div> |
| 229 | |
| 230 | <button class="btn-download" id="btnGen" onclick="generate()">⬇ Генерирай команда</button> |
| 231 | |
| 232 | <div class="console" id="console">Готов. Попълни URL и натисни бутона...</div> |
| 233 | |
| 234 | <div class="status-bar"> |
| 235 | <div class="dot" id="dotYtdlp"></div><span id="statusYtdlp">yt-dlp: непроверен</span> |
| 236 | | |
| 237 | <div class="dot" id="dotFfmpeg"></div><span id="statusFfmpeg">ffmpeg: непроверен</span> |
| 238 | </div> |
| 239 | |
| 240 | <hr class="separator"> |
| 241 | |
| 242 | <div class="setup-section"> |
| 243 | <details> |
| 244 | <summary>▸ Как да инсталираш yt-dlp и ffmpeg (разгъни)</summary> |
| 245 | <div class="setup-content"> |
| 246 | <div class="step"><span class="step-num">1</span>Отвори <b>PowerShell като администратор</b> (Win+X → Terminal (Admin))</div> |
| 247 | <div class="step"><span class="step-num">2</span>Инсталирай <b>winget</b> пакетите:<br> |
| 248 | <code>winget install yt-dlp.yt-dlp</code><br> |
| 249 | <code>winget install Gyan.FFmpeg</code> |
| 250 | </div> |
| 251 | <div class="step"><span class="step-num">3</span>Затвори и отвори отново терминала (за да се заредят PATH-овете)</div> |
| 252 | <div class="step"><span class="step-num">4</span>Провери: <code>yt-dlp --version</code> и <code>ffmpeg -version</code></div> |
| 253 | <div class="step"><span class="step-num">5</span>Готово! Върни се тук и свали музика 🎵</div> |
| 254 | <br> |
| 255 | <b>Алтернативно</b> (без winget):<br> |
| 256 | — yt-dlp: <a href="https://github.com/yt-dlp/yt-dlp/releases" target="_blank">github.com/yt-dlp/yt-dlp/releases</a> → свали <code>yt-dlp.exe</code><br> |
| 257 | — ffmpeg: <a href="https://www.gyan.dev/ffmpeg/builds/" target="_blank">gyan.dev/ffmpeg/builds</a> → release build → извлечи <code>ffmpeg.exe</code><br> |
| 258 | — Постави и двата .exe в <code>C:\Windows\System32</code> или в обща папка с PATH |
| 259 | </div> |
| 260 | </details> |
| 261 | </div> |
| 262 | </div> |
| 263 | |
| 264 | <script> |
| 265 | function log(msg, cls) { |
| 266 | const c = document.getElementById('console'); |
| 267 | const line = document.createElement('div'); |
| 268 | if (cls) line.className = cls; |
| 269 | line.textContent = msg; |
| 270 | c.appendChild(line); |
| 271 | c.scrollTop = c.scrollHeight; |
| 272 | } |
| 273 | |
| 274 | function clearConsole() { |
| 275 | document.getElementById('console').innerHTML = ''; |
| 276 | } |
| 277 | |
| 278 | function setStatus(tool, ok) { |
| 279 | const dot = document.getElementById('dot' + tool); |
| 280 | const span = document.getElementById('status' + tool); |
| 281 | dot.className = 'dot ' + (ok ? 'ok' : 'err'); |
| 282 | span.textContent = tool.toLowerCase() + ': ' + (ok ? 'намерен ✓' : 'не е намерен ✗'); |
| 283 | } |
| 284 | |
| 285 | function generate() { |
| 286 | clearConsole(); |
| 287 | const url = document.getElementById('url').value.trim(); |
| 288 | const quality = document.getElementById('quality').value; |
| 289 | const template = document.getElementById('template').value; |
| 290 | const outdir = document.getElementById('outdir').value.trim() || '%USERPROFILE%\\Downloads\\Music'; |
| 291 | |
| 292 | if (!url) { |
| 293 | log('⚠ Моля въведи YouTube URL!', 'warn'); |
| 294 | return; |
| 295 | } |
| 296 | |
| 297 | if (!url.includes('youtube.com') && !url.includes('youtu.be')) { |
| 298 | log('⚠ Това не изглежда като YouTube URL. Продължавам все пак...', 'warn'); |
| 299 | } |
| 300 | |
| 301 | const isPlaylist = url.includes('playlist') || url.includes('list='); |
| 302 | const outputTemplate = outdir + '\\' + template + '.%(ext)s'; |
| 303 | |
| 304 | const cmd = `yt-dlp -x --audio-format mp3 --audio-quality ${quality}K --embed-thumbnail --add-metadata -o "${outputTemplate}" "${url}"`; |
| 305 | |
| 306 | log('> Команда за PowerShell / CMD:', 'info'); |
| 307 | log(''); |
| 308 | log(cmd); |
| 309 | log(''); |
| 310 | log('─────────────────────────────────────', 'info'); |
| 311 | log('Копирай командата и я постави в PowerShell или CMD.', 'ok'); |
| 312 | if (isPlaylist) { |
| 313 | log('📋 Открит плейлист — ще се свалят всички песни!', 'info'); |
| 314 | } |
| 315 | log(''); |
| 316 | log('Полезни добавки:', 'info'); |
| 317 | log(' --cookies-from-browser chrome (за видеа изискващи вход)'); |
| 318 | log(' --yes-playlist (принудително целия плейлист)'); |
| 319 | log(' --no-playlist (само видеото, не плейлиста)'); |
| 320 | log(' --write-info-json (записва метаданни)'); |
| 321 | |
| 322 | setStatus('Ytdlp', true); |
| 323 | setStatus('Ffmpeg', true); |
| 324 | |
| 325 | document.getElementById('btnCopy') && document.getElementById('btnCopy').remove(); |
| 326 | |
| 327 | const btn = document.createElement('button'); |
| 328 | btn.id = 'btnCopy'; |
| 329 | btn.className = 'btn-download'; |
| 330 | btn.style.marginTop = '10px'; |
| 331 | btn.style.background = '#1a5c1a'; |
| 332 | btn.textContent = '📋 Копирай командата'; |
| 333 | btn.onclick = () => { |
| 334 | navigator.clipboard.writeText(cmd).then(() => { |
| 335 | btn.textContent = '✓ Копирано!'; |
| 336 | setTimeout(() => btn.textContent = '📋 Копирай командата', 2000); |
| 337 | }); |
| 338 | }; |
| 339 | document.querySelector('.card').appendChild(btn); |
| 340 | } |
| 341 | |
| 342 | function copyFolder() { |
| 343 | const val = document.getElementById('outdir').value; |
| 344 | navigator.clipboard.writeText(val).then(() => { |
| 345 | document.querySelector('.btn-browse').textContent = '✓ Копирано!'; |
| 346 | setTimeout(() => document.querySelector('.btn-browse').textContent = '📋 Копирай', 1500); |
| 347 | }); |
| 348 | } |
| 349 | </script> |
| 350 | </body> |
| 351 | </html> |
| 352 |