Multimedia: Alle Medien-Dateien umcodieren (inkl. webm und .webp)
Autor: Ralf v.d.Mark
eingetragen: Dienstag, 23. Dezember 2025 um 15:49 Uhr (52/2025 Kalenderwoche)
geändert: Mittwoch, 24. Dezember 2025 um 13:50 Uhr (52/2025 Kalenderwoche)
Keywords: Multimedia Medien Dateien umcodieren videos bilder
Kategorien: Windows,
Text:
Umcodieren aller Video- und Bildformate außer MP4!
(".flv",".mov",".mpg",".mpeg",".avi",".wmv",".mkv",".mts",".m2ts",".3gp",".vob",".ts",".webm",".webp")
Siehe weitere Umcodier-Scripte
Das PowerShell-Script "convert-allMediainkl-Unterordner2MP4uJPG.ps1" (Multithreading-fähig, JSON-loggend, deutsch, ASCII-sicher) macht Folgendes::
✔ alle Nicht-MP4-Videos verarbeitet
✔ zusätzlich WEBM --> MP4 und WEBP --> JPG umwandelt
✔ Multithreading nutzt (PowerShell-Jobs --> parallel, CPU-optimiert)
✔ Die Metadaten der Quelle werden in die neue Mediendatei übernommen
✔ eine Text-Logdatei mit Zeitstempel erzeugt
✔ Originaldateien in _Backup-Filme verschiebt
✔ MP4/JPG im Originalordner erzeugt
✔ farbige Konsolenausgabe hat
✔ ASCII-sicher ist (keine Umlaute, keine Unicode-Symbole)
✔ Backup-Ordner: _____Backup-Filme --> wird korrekt ignoriert
✔ Logdateien: Zeitstempel im Namen --> keine Überschreibung
✔ JSON-Log: wird fortgeschrieben --> perfekt für spätere Auswertung
✔ Dateisystem- und Video-Metadaten landen im Text-Log (Erstellungs-, Änderungs- und Zugriffsdatum sowie Dauer, Bitrate und Auflösung).
✔ WEBP/WEBM: Sonderbehandlung eingebaut --> läuft
✔ Remux/Reencode: Codec-Check mit ffprobe --> korrekt
✔ Job-Handling: Warteschleife + Cleanup --> stabil
✔ Multithreading: $MaxJobs = 8 --> sauber konfigurierbar
Wichtige Hinweise zum Multithreading:
- Ein Ryzen 9 kann 12–16 parallele Jobs locker stemmen
- Ein Ryzen 7 eher 6–8 Jobs
- Standardmäßig sind 8 Threads, aber anpassbar unter:
- --> $MaxJobs = 8
Kleine Anleitung, um das jeweilige Script zu starten:
1) FFmpeg muss installiert sein
(- ffmpeg\bin kopieren nach z. B. "C:\Programme\ffmpeg\bin"
- Windows-Suche --> „Umgebungsvariablen“
- „PATH“ bearbeiten --> neuen Eintrag hinzufügen:
- C:\Programme\ffmpeg\bin
- OK --> fertig.).
2a) Skript "convert-....ps1" in den Ordner mit den Mediendateien legen
2b) EMPFOHLEN: Skript "convert-allMediainkl-Unterordner2MP4uJPG.ps1" in den obersten Ordner mit den Mediendateien legen.
3) PowerShell öffnen
4) In den (obersten) Ordner wechseln, wo das Script liegt: "e:" und "cd ..."
5) Script ausführen: "./convert-allMediainkl-Unterordner2_MP4uJPG.ps1"
Falls PowerShell meckert wegen der Ausführungsrichtlinie:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
6a) Fertig — alle MP4s liegen daneben.
6b) Fertig - alle MP4s liegen im Originalordner und die veraltete Mediendatei im Backup-Ordner
Quellcode:
# ============================================
# Multithreaded Video Converter (ASCII-safe)
# ============================================
# Anzahl paralleler Jobs
$MaxJobs = 8
$CrfValue = 18
$Preset = "slow"
$BackupName = "_____Backup-Filme"
# Basisordner & Backup
$BaseDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$BackupDir = Join-Path $BaseDir $BackupName
New-Item -ItemType Directory -Force -Path $BackupDir | Out-Null
# Logdatei
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$LogFile = Join-Path $BackupDir "conversion_log_$timestamp.txt"
"=== Videokonvertierung gestartet: $(Get-Date) ===" | Out-File -FilePath $LogFile -Encoding ASCII
# Dateiformate
$extensions = "*.flv","*.mov","*.mpg","*.mpeg","*.avi","*.wmv","*.mkv","*.mts","*.m2ts","*.3gp","*.vob","*.ts","*.webm","*.webp","*.FLV","*.MOV","*.MPG","*.MPEG","*.AVI","*.WMV","*.MKV","*.MTS","*.M2TS","*.3GP","*.VOB","*.TS","*.WEBM","*.WEBP"
# Dateien sammeln (Backup ausschliessen)
$files = foreach ($ext in $extensions) {
Get-ChildItem -Path $BaseDir -Filter $ext -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notlike "$BackupDir*" }
}
# ============================================
# Job-Funktion
# ============================================
$ScriptBlock = {
param($file, $relativePath, $BackupDir, $LogFile, $CrfValue, $Preset)
$mp4Path = [System.IO.Path]::ChangeExtension($file, ".mp4")
$jpgPath = [System.IO.Path]::ChangeExtension($file, ".jpg")
# Falls MP4 schon existiert -> neuen Namen mit (doppelt)
if (Test-Path $mp4Path) {
$folder = Split-Path $mp4Path -Parent
$name = [System.IO.Path]::GetFileNameWithoutExtension($mp4Path)
$mp4Path = Join-Path $folder ($name + " (doppelt).mp4")
}
# Backup-Zielpfad
$backupTarget = Join-Path $BackupDir $relativePath
$backupFolder = Split-Path $backupTarget -Parent
New-Item -ItemType Directory -Force -Path $backupFolder | Out-Null
# Dateisystem-Metadaten
$fileInfo = Get-Item $file
$creationTime = $fileInfo.CreationTime
$lastWriteTime = $fileInfo.LastWriteTime
$lastAccessTime= $fileInfo.LastAccessTime
# WEBP -> JPG
if ($file.ToLower().EndsWith(".webp")) {
ffmpeg -y -i "$file" "$jpgPath"
Add-Content -Encoding ASCII $LogFile "Neue JPG-Datei erzeugt: $jpgPath"
Add-Content -Encoding ASCII $LogFile "Datum erstellt: $creationTime"
Add-Content -Encoding ASCII $LogFile "Datum geaendert: $lastWriteTime"
Add-Content -Encoding ASCII $LogFile "Datum letzter Zugriff: $lastAccessTime"
# Zeitstempel uebernehmen
Set-ItemProperty -Path $jpgPath -Name CreationTime -Value $creationTime
Set-ItemProperty -Path $jpgPath -Name LastWriteTime -Value $lastWriteTime
# relativen Pfad sauber berechnen
$relativePath = $file.Substring($using:BaseDir.Length).TrimStart('\','/')
$backupTarget = Join-Path $using:BackupDir $relativePath
# Datei im Backup mit gleichem Namen liegt -> löschen (falls vorhanden)
if (Test-Path -Path $backupTarget -PathType Leaf) {
Remove-Item -Path $backupTarget -Force -ErrorAction SilentlyContinue
}
# Originaldatei ins Backup verschieben
Move-Item -Force "$file" "$backupTarget"
return
}
# WEBM -> MP4
if ($file.ToLower().EndsWith(".webm")) {
ffmpeg -y -i "$file" -c:v libx264 -preset $Preset -crf $CrfValue -c:a aac "$mp4Path"
Add-Content -Encoding ASCII $LogFile "Neue MP4-Datei erzeugt: $mp4Path"
Add-Content -Encoding ASCII $LogFile "Datum erstellt: $creationTime"
Add-Content -Encoding ASCII $LogFile "Datum geaendert: $lastWriteTime"
Add-Content -Encoding ASCII $LogFile "Datum letzter Zugriff: $lastAccessTime"
# Zeitstempel uebernehmen
Set-ItemProperty -Path $mp4Path -Name CreationTime -Value $creationTime
Set-ItemProperty -Path $mp4Path -Name LastWriteTime -Value $lastWriteTime
# relativen Pfad sauber berechnen
$relativePath = $file.Substring($using:BaseDir.Length).TrimStart('\','/')
$backupTarget = Join-Path $using:BackupDir $relativePath
# Datei im Backup mit gleichem Namen liegt -> löschen (falls vorhanden)
if (Test-Path -Path $backupTarget -PathType Leaf) {
Remove-Item -Path $backupTarget -Force -ErrorAction SilentlyContinue
}
# Originaldatei ins Backup verschieben
Move-Item -Force "$file" "$backupTarget"
return
}
# Standardfall: andere Videoformate
ffmpeg -y -i "$file" -c:v libx264 -preset $Preset -crf $CrfValue -c:a aac "$mp4Path"
Add-Content -Encoding ASCII $LogFile "Neue MP4-Datei erzeugt: $mp4Path"
Add-Content -Encoding ASCII $LogFile "Datum erstellt: $creationTime"
Add-Content -Encoding ASCII $LogFile "Datum geaendert: $lastWriteTime"
Add-Content -Encoding ASCII $LogFile "Datum letzter Zugriff: $lastAccessTime"
# Zeitstempel uebernehmen
Set-ItemProperty -Path $mp4Path -Name CreationTime -Value $creationTime
Set-ItemProperty -Path $mp4Path -Name LastWriteTime -Value $lastWriteTime
# relativen Pfad sauber berechnen
$relativePath = $file.Substring($using:BaseDir.Length).TrimStart('\','/')
$backupTarget = Join-Path $using:BackupDir $relativePath
# Datei im Backup mit gleichem Namen liegt -> löschen (falls vorhanden)
if (Test-Path -Path $backupTarget -PathType Leaf) {
Remove-Item -Path $backupTarget -Force -ErrorAction SilentlyContinue
}
# Originaldatei ins Backup verschieben
Move-Item -Force "$file" "$backupTarget"
}
# ============================================
# Jobs starten
# ============================================
foreach ($fileObj in $files) {
while ((Get-Job -State Running).Count -ge $MaxJobs) {
Start-Sleep -Milliseconds 200
}
$file = $fileObj.FullName
$relativePath = Resolve-Path $file -Relative
Write-Host "Starte Job fuer: $file" -ForegroundColor Cyan
Start-Job -ScriptBlock $ScriptBlock -ArgumentList $file, $relativePath, $BackupDir, $LogFile, $CrfValue, $Preset | Out-Null
}
Get-Job | Wait-Job | Out-Null
Get-Job | Remove-Job | Out-Null
Add-Content -Encoding ASCII $LogFile "`n=== Videokonvertierung abgeschlossen: $(Get-Date) ==="