# ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# 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
Comments
0 B
|👍
/👎