# --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- # YouTube Audio Downloader # # 1. Script als z. B. "download.ps1" mit Kodierung "UTF-8" anlegen. # 2. yt-dlp hier herunterladen und in den selben Ordner des Scripts kopieren: https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe # 3. Beim Ausführen des Scripts die Video- oder Kanal-URL angegeben. Das Script lädt alle Videos als MP3 herunter und passt das Datum zum Upload-Datum an. Bereits heruntergeladene Audios werden übersprungen. # 4. Es werden maximal 50 Videos wegen dem Rate-Limit von YouTube heruntergeladen. Nach Abschluss der Downloads wird das ursprüngliche Upload-Datum auf die Audio-Dateien gesetzt. # # Version 1.0.1 - 22.09.2025 - @nurjns # --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- # Pfade definieren und prüfen $outputDir = Join-Path $PSScriptRoot 'audios' $archiveFile = Join-Path $PSScriptRoot 'downloaded.txt' $ytDlp = Join-Path $PSScriptRoot 'yt-dlp.exe' if (!(Test-Path $ytDlp)) { Write-Host "Fehler: yt-dlp.exe wurde im Skriptordner nicht gefunden: $ytDlp" -ForegroundColor Red Write-Host "Hier herunterladen: https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe" Pause return } # Kanal-Link interaktiv abfragen $channelUrl = Read-Host "YouTube Video-URL oder Kanal-URL" # Sicherstellen, dass der Ausgabeordner existiert if (!(Test-Path $outputDir)) { New-Item -ItemType Directory -Force -Path $outputDir | Out-Null } # Download-Befehl mit yt-dlp (max. 50 Videos) $arguments = @( $channelUrl, "--download-archive", "`"$archiveFile`"", "-o", "`"$outputDir/%(title)s [%(id)s].%(ext)s`"", "-x", "--audio-format", "mp3", "--ffmpeg-location", "`"$PSScriptRoot`"", "--max-downloads", "50" ) Write-Host "Starte Download mit yt-dlp..." & $ytDlp @arguments if ($LASTEXITCODE -eq 101) { Write-Host "Limit von 50 Videos erreicht! Fuer weitere Downloads Script neu starten." -ForegroundColor Yellow } # Hole Liste aller Video-IDs, die im Archiv stehen (also schon geladen wurden) $downloadedIds = Get-Content $archiveFile | ForEach-Object { $_ -replace '^youtube ', '' } # Schleife durch YouTube-Kanal foreach ($id in $downloadedIds) { try { $json = & $ytDlp -j --skip-download -- "$id" 2>$null | ConvertFrom-Json if ($null -eq $json) { Write-Warning "Keine Metadaten fuer ID $id gefunden" continue } $uploadDate = $json.upload_date $title = $json.title # ungültige Zeichen durch "_" ersetzen $invalidChars = [System.IO.Path]::GetInvalidFileNameChars() -join '' $regex = "[{0}]" -f [Regex]::Escape($invalidChars) $safeTitle = $title -replace $regex, '_' $fileName = "$outputDir\$($safeTitle) [$id].mp3" $fileFound = $false $actualFileName = "" if (Test-Path $fileName) { $fileFound = $true $actualFileName = $fileName } else { $searchPattern = "*[$id].*" $matchingFiles = Get-ChildItem -Path $outputDir -Filter $searchPattern -ErrorAction SilentlyContinue if ($matchingFiles.Count -gt 0) { $actualFileName = $matchingFiles[0].FullName $fileFound = $true Write-Host "Datei gefunden als: $($matchingFiles[0].Name)" -ForegroundColor Yellow } } if (!$fileFound) { Write-Warning "Datei nicht gefunden fuer ID $id. Gesucht: $fileName" continue } if ($uploadDate -match '^\d{8}$') { $year = $uploadDate.Substring(0, 4) $month = $uploadDate.Substring(4, 2) $day = $uploadDate.Substring(6, 2) try { $dt = Get-Date -Year $year -Month $month -Day $day -Hour 0 -Minute 0 -Second 0 $file = Get-Item -LiteralPath $actualFileName if ($file -is [System.Array]) { $file = $file[0] } if ($file.CreationTime.Date -ne $dt.Date -or $file.LastWriteTime.Date -ne $dt.Date -or $file.LastAccessTime.Date -ne $dt.Date) { Set-ItemProperty -LiteralPath $actualFileName -Name CreationTime -Value $dt Set-ItemProperty -LiteralPath $actualFileName -Name LastWriteTime -Value $dt Set-ItemProperty -LiteralPath $actualFileName -Name LastAccessTime -Value $dt Write-Host "Metadaten gesetzt fuer: $($file.Name)" -ForegroundColor Green } else { Write-Host "Metadaten bereits korrekt fuer: $($file.Name)" -ForegroundColor DarkGray } } catch { Write-Error "Fehler beim Setzen der Zeitstempel fuer $actualFileName : $($_.Exception.Message)" } } else { Write-Warning "Ungueltiges Upload-Datum Format fuer $fileName : $uploadDate" } } catch { Write-Error "Fehler beim Verarbeiten von ID $id : $($_.Exception.Message)" } } Write-Host "Fertig!" -ForegroundColor Green pause