feat: implement automatic yt-dlp and ffmpeg dependency management and media downloading logic

This commit is contained in:
Ümit Tunç
2026-05-28 07:17:55 +03:00
parent 2b303cfc9b
commit c07d68fab1
5 changed files with 107 additions and 23 deletions
+16 -3
View File
@@ -3,11 +3,13 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VibeDownloader - Premium YouTube & MP3 Downloader</title>
<title>VibeDownloader - Premium Social Media & MP3 Downloader</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</head>
<body>
<!-- Custom Glassmorphic Titlebar -->
@@ -64,12 +66,12 @@
</svg>
</div>
<h1 class="glow-text">VibeDownloader</h1>
<p class="subtitle">YouTube videolarını saniyeler içinde yüksek kaliteli MP4 veya MP3 olarak indirin</p>
<p class="subtitle">YouTube, X/Twitter, Instagram, TikTok ve tüm popüler sitelerden video/ses indirin</p>
</header>
<section class="glass-card url-section">
<div class="input-group">
<input type="text" id="url-input" placeholder="YouTube video veya oynatma listesi bağlantısı yapıştırın..." autocomplete="off">
<input type="text" id="url-input" placeholder="Sosyal medya veya video platformu bağlantısı yapıştırın (YouTube, Instagram, TikTok, X/Twitter vb.)..." autocomplete="off">
<button id="analyze-btn" class="glow-button">
<span>Analiz Et</span>
<svg class="btn-icon animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display: none;">
@@ -83,6 +85,17 @@
<span id="output-path" class="folder-path">Yükleniyor...</span>
<button id="change-folder-btn" class="text-btn">Değiştir</button>
</div>
<div class="cookies-row" style="margin-top: 15px; display: flex; align-items: center; justify-content: center; gap: 8px; font-size: 0.85em; opacity: 0.85; border-top: 1px solid rgba(255,255,255,0.06); padding-top: 12px; flex-wrap: wrap;">
<input type="checkbox" id="use-cookies" style="cursor: pointer; accent-color: #7000ff; width: 15px; height: 15px;">
<label for="use-cookies" style="cursor: pointer; color: #fff; user-select: none;">Giriş gerektiren içerikler (Örn. Instagram Hikayeleri) için tarayıcı oturumunu kullan:</label>
<select id="cookie-browser" style="background: rgba(23, 20, 38, 0.8); color: #fff; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 4px; padding: 2px 8px; cursor: pointer; outline: none; font-family: inherit; font-size: 0.95em;">
<option value="chrome">Chrome</option>
<option value="edge">Edge</option>
<option value="firefox">Firefox</option>
<option value="brave">Brave</option>
<option value="opera">Opera</option>
</select>
</div>
</section>
<!-- Error Display in Step 1 -->
+39 -2
View File
@@ -9,6 +9,8 @@ const urlInput = document.getElementById('url-input');
const analyzeBtn = document.getElementById('analyze-btn');
const outputPath = document.getElementById('output-path');
const changeFolderBtn = document.getElementById('change-folder-btn');
const useCookiesCheckbox = document.getElementById('use-cookies');
const cookieBrowserSelect = document.getElementById('cookie-browser');
const errorCard = document.getElementById('error-card');
const errorMessage = document.getElementById('error-message');
@@ -167,7 +169,8 @@ analyzeBtn.addEventListener('click', async () => {
analyzeIcon.style.display = 'inline-block';
try {
const result = await window.api.getVideoInfo(url);
const browser = useCookiesCheckbox.checked ? cookieBrowserSelect.value : null;
const result = await window.api.getVideoInfo(url, browser);
if (result.success) {
analyzedUrl = url;
currentVideoData = result.info;
@@ -245,7 +248,8 @@ downloadBtn.addEventListener('click', async () => {
});
try {
const result = await window.api.downloadMedia(analyzedUrl, currentFormat, currentQuality);
const browser = useCookiesCheckbox.checked ? cookieBrowserSelect.value : null;
const result = await window.api.downloadMedia(analyzedUrl, currentFormat, currentQuality, browser);
if (result.success) {
downloadStatus.textContent = 'Tamamlandı!';
downloadPercent.textContent = '100%';
@@ -263,6 +267,39 @@ downloadBtn.addEventListener('click', async () => {
// Success gradient transitions
downloadProgressBar.style.background = 'linear-gradient(90deg, #00ff87 0%, #60efff 100%)';
downloadProgressBar.style.boxShadow = '0 0 15px rgba(0, 255, 135, 0.6)';
// Trigger premium SweetAlert2 modal
Swal.fire({
title: 'İndirme Tamamlandı! 🎉',
html: `
<div style="text-align: left; font-family: 'Outfit', sans-serif; color: #fff; line-height: 1.6; font-size: 14px;">
<p style="margin-bottom: 8px;"><strong>Dosya Adı:</strong> <span style="color: #60efff;">${currentVideoData.title}</span></p>
<p style="margin-bottom: 8px;"><strong>Platform / Paylaşan:</strong> <span style="color: #60efff;">${currentVideoData.uploader || 'Bilinmiyor'}</span></p>
<p style="margin-bottom: 8px;"><strong>Dosya Boyutu:</strong> <span style="color: #00ff87;">${result.stats.size}</span></p>
<p style="margin-bottom: 8px;"><strong>İndirme Süresi:</strong> <span style="color: #00ff87;">${result.stats.duration}</span></p>
<p style="margin-bottom: 8px;"><strong>Format ve Kalite:</strong> <span style="color: #ff4da6; text-transform: uppercase;">${currentFormat} (${currentQuality === '320' || currentQuality === '1080' ? 'En Yüksek' : currentQuality})</span></p>
<p style="margin-top: 15px; font-size: 12px; opacity: 0.8; word-break: break-all;"><strong>Kaydedilen Klasör:</strong> <br>${result.stats.outputDir}</p>
</div>
`,
icon: 'success',
background: 'rgba(23, 20, 38, 0.95)',
color: '#fff',
confirmButtonText: 'Klasörü Aç 📂',
showCancelButton: true,
cancelButtonText: 'Yeni İndirme 🔄',
confirmButtonColor: '#7000ff',
cancelButtonColor: 'rgba(255, 255, 255, 0.1)',
backdrop: 'rgba(0, 0, 0, 0.6)'
}).then((swalResult) => {
if (swalResult.isConfirmed) {
window.api.openPath(result.stats.outputDir);
} else {
// Go back to step 1
backBtn.click();
urlInput.value = '';
downloadProgressPanel.style.display = 'none';
}
});
} else {
showError(result.error);
downloadProgressPanel.style.display = 'none';