Hier sind zwei PowerShell-Skripte, mit denen Sie lange Videos nach schwarzen Szenen in kleinere Kapitel aufteilen können.
Speichern Sie sie als Detect_black.ps1 und Cut_black.ps1. Laden Sie ffmpeg für Windows herunter und teilen Sie dem Skript den Pfad zu Ihrer Datei ffmpeg.exe und Ihrem Videoordner im Optionsbereich mit.
Beide Skripte berühren vorhandene Videodateien nicht, sie bleiben unberührt.
Sie erhalten jedoch einige neue Dateien an derselben Stelle, an der sich Ihre Eingabevideos befinden
- Eine Protokolldatei pro Video mit der Konsolenausgabe für beide verwendeten ffmpeg-Befehle
- Eine CSV-Datei pro Video mit allen Zeitstempeln schwarzer Szenen zur manuellen Feinabstimmung
- Ein paar neue Videos, je nachdem, wie viele schwarze Szenen zuvor erkannt wurden
Erstes Skript, das ausgeführt wird: Detect_black.ps1
### Options __________________________________________________________________________________________________________
$ffmpeg = ".\ffmpeg.exe" # Set path to your ffmpeg.exe; Build Version: git-45581ed (2014-02-16)
$folder = ".\Videos\*" # Set path to your video folder; '\*' must be appended
$filter = @("*.mov","*.mp4") # Set which file extensions should be processed
$dur = 4 # Set the minimum detected black duration (in seconds)
$pic = 0.98 # Set the threshold for considering a picture as "black" (in percent)
$pix = 0.15 # Set the threshold for considering a pixel "black" (in luminance)
### Main Program ______________________________________________________________________________________________________
foreach ($video in dir $folder -include $filter -exclude "*_???.*" -r){
### Set path to logfile
$logfile = "$($video.FullName)_ffmpeg.log"
### analyse each video with ffmpeg and search for black scenes
& $ffmpeg -i $video -vf blackdetect=d=`"$dur`":pic_th=`"$pic`":pix_th=`"$pix`" -an -f null - 2> $logfile
### Use regex to extract timings from logfile
$report = @()
Select-String 'black_start:.*black_end:' $logfile | % {
$black = "" | Select start, end, cut
# extract start time of black scene
$start_s = $_.line -match '(?<=black_start:)\S*(?= black_end:)' | % {$matches[0]}
$start_ts = [timespan]::fromseconds($start_s)
$black.start = "{0:HH:mm:ss.fff}" -f ([datetime]$start_ts.Ticks)
# extract duration of black scene
$end_s = $_.line -match '(?<=black_end:)\S*(?= black_duration:)' | % {$matches[0]}
$end_ts = [timespan]::fromseconds($end_s)
$black.end = "{0:HH:mm:ss.fff}" -f ([datetime]$end_ts.Ticks)
# calculate cut point: black start time + black duration / 2
$cut_s = ([double]$start_s + [double]$end_s) / 2
$cut_ts = [timespan]::fromseconds($cut_s)
$black.cut = "{0:HH:mm:ss.fff}" -f ([datetime]$cut_ts.Ticks)
$report += $black
}
### Write start time, duration and the cut point for each black scene to a seperate CSV
$report | Export-Csv -path "$($video.FullName)_cutpoints.csv" –NoTypeInformation
}
Wie funktioniert es
Das erste Skript durchläuft alle Videodateien, die einer bestimmten Erweiterung entsprechen und nicht mit dem Muster übereinstimmen *_???.*
, da neue Videokapitel benannt wurden <filename>_###.<ext>
und wir sie ausschließen möchten.
Es durchsucht alle schwarzen Szenen und schreibt den Startzeitstempel und die Dauer der schwarzen Szene in eine neue CSV-Datei mit dem Namen <video_name>_cutpoints.txt
Außerdem werden Schnittpunkte wie folgt berechnet : cutpoint = black_start + black_duration / 2
. Später wird das Video zu diesen Zeitstempeln segmentiert.
Die Datei cutpoints.txt für Ihr Beispielvideo würde Folgendes anzeigen :
start end cut
00:03:56.908 00:04:02.247 00:03:59.578
00:08:02.525 00:08:10.233 00:08:06.379
Nach einem Lauf können Sie die Schnittpunkte bei Bedarf manuell bearbeiten. Wenn Sie das Skript erneut ausführen, werden alle alten Inhalte überschrieben. Seien Sie vorsichtig beim manuellen Bearbeiten und speichern Sie Ihre Arbeit an einem anderen Ort.
Für das Beispielvideo lautet der Befehl ffmpeg zum Erkennen schwarzer Szenen
$ffmpeg -i "Tape_10_3b.mp4" -vf blackdetect=d=4:pic_th=0.98:pix_th=0.15 -an -f null
Es gibt 3 wichtige Nummern, die im Optionsbereich des Skripts bearbeitet werden können
d=4
bedeutet, dass nur schwarze Szenen erkannt werden, die länger als 4 Sekunden sind
pic_th=0.98
ist die Schwelle für die Betrachtung eines Bildes als "schwarz" (in Prozent)
pix=0.15
Legt den Schwellenwert für die Betrachtung eines Pixels als "schwarz" (in Luminanz) fest. Da Sie alte VHS-Videos haben, haben Ihre Videos keine vollständig schwarzen Szenen. Der Standardwert 10 funktioniert nicht und ich musste den Schwellenwert leicht erhöhen
Wenn etwas schief geht, überprüfen Sie die entsprechende aufgerufene Protokolldatei <video_name>__ffmpeg.log
. Wenn die folgenden Zeilen fehlen, erhöhen Sie die oben genannten Zahlen, bis Sie alle schwarzen Szenen erkennen:
[blackdetect @ 0286ec80]
black_start:236.908 black_end:242.247 black_duration:5.33877
Zweites Skript, das ausgeführt werden soll: cut_black.ps1
### Options __________________________________________________________________________________________________________
$ffmpeg = ".\ffmpeg.exe" # Set path to your ffmpeg.exe; Build Version: git-45581ed (2014-02-16)
$folder = ".\Videos\*" # Set path to your video folder; '\*' must be appended
$filter = @("*.mov","*.mp4") # Set which file extensions should be processed
### Main Program ______________________________________________________________________________________________________
foreach ($video in dir $folder -include $filter -exclude "*_???.*" -r){
### Set path to logfile
$logfile = "$($video.FullName)_ffmpeg.log"
### Read in all cutpoints from *_cutpoints.csv; concat to string e.g "00:03:23.014,00:06:32.289,..."
$cuts = ( Import-Csv "$($video.FullName)_cutpoints.csv" | % {$_.cut} ) -join ","
### put together the correct new name, "%03d" is a generic number placeholder for ffmpeg
$output = $video.directory.Fullname + "\" + $video.basename + "_%03d" + $video.extension
### use ffmpeg to split current video in parts according to their cut points
& $ffmpeg -i $video -f segment -segment_times $cuts -c copy -map 0 $output 2> $logfile
}
Wie funktioniert es
Das zweite Skript durchläuft alle Videodateien auf dieselbe Weise wie das erste Skript. Es werden nur die ausgeschnittenen Zeitstempel aus dem entsprechenden cutpoints.txt
Video eingelesen .
Als nächstes wird ein geeigneter Dateiname für Kapiteldateien zusammengestellt und ffmpeg angewiesen, das Video zu segmentieren. Derzeit werden die Videos ohne Neucodierung geschnitten (superschnell und verlustfrei). Aus diesem Grund kann es bei Schnittpunkt-Zeitstempeln zu Ungenauigkeiten von 1 bis 2 Sekunden kommen, da ffmpeg nur bei key_frames schneiden kann. Da wir nur kopieren und nicht neu codieren, können wir key_frames nicht alleine einfügen.
Der Befehl für das Beispielvideo wäre
$ffmpeg -i "Tape_10_3b.mp4" -f segment -segment_times "00:03:59.578,00:08:06.379" -c copy -map 0 "Tape_10_3b_(%03d).mp4"
Wenn etwas schief geht, schauen Sie sich das entsprechende ffmpeg.log an
Verweise
Machen
Fragen Sie OP, ob das CSV-Format besser ist als eine Textdatei als Schnittpunktdatei, damit Sie sie mit Excel etwas einfacher bearbeiten können.
»Implementiert
Implementieren Sie eine Möglichkeit zum Formatieren von Zeitstempeln als [hh]: [mm]: [ss], [Millisekunden] und nicht nur als Sekunden
»Implementiert
Implementieren Sie einen Befehl ffmpeg, um Mosaik-PNG-Dateien für jedes Kapitel zu erstellen.
»Implementiert
Überlegen Sie, ob dies -c copy
für das OP-Szenario ausreicht oder ob wir es vollständig neu codieren müssen.
Scheint, als wäre Ryan schon dabei .
Hier ist der Bonus: Dieses 3. PowerShell-Skript generiert ein Mosaik-Miniaturbild
Sie erhalten ein Bild pro Kapitelvideo, die alle wie im folgenden Beispiel aussehen.
Die Hauptidee besteht darin, einen kontinuierlichen Bildstrom über das gesamte Video zu erhalten. Wir tun dies mit FFmpegs wählen Sie Option.
Zuerst rufen wir die Gesamtzahl der Frames mit einer ausgeklügelten Methode ab (z. B. 2000) und teilen sie durch unsere Standardanzahl der Miniaturansichten (z. B. 5 x 4 = 20). Wir wollen also seitdem alle 100 Frames ein Bild erzeugen
2000 / 20 = 100
Der resultierende Befehl ffmpeg zum Generieren der Miniaturansicht könnte folgendermaßen aussehen
Im obigen Code sehen Sie 9 verschiedene
-vf
Kombinationen bestehend ausselect=not(mod(n\,XXX))
Dabei ist XXX eine berechnete Frameratethumbnail
Dadurch werden die repräsentativsten Frames automatisch ausgewähltselect='gt(scene\,XXX)
+-vsync vfr
wobei XXX eine Schwelle ist, mit der Sie spielen müssenmpdecimate
- Entfernen Sie nahezu doppelte Frames. Gut gegen schwarze Szenenyadif
- Trennen Sie das Eingabebild. Ich weiß nicht warum, aber es funktioniertVersion 3 ist meiner Meinung nach die beste Wahl. Alle anderen sind auskommentiert, aber Sie können sie trotzdem ausprobieren. Ich war in der Lage die meisten der verschwommenen Thumbnails entfernen verwenden
mpdecimate
,yadif
undselect=not(mod(n\,XXX))
. Ja!Für dein Beispielvideo bekomme ich diese Vorschau
klicken um zu vergrößern
klicken um zu vergrößern
Ich habe alle von diesen Versionen erstellten Miniaturansichten hochgeladen . Schauen Sie sie sich für einen vollständigen Vergleich an.
quelle
select='gt(scene\,0.4)'
zur Arbeit zu kommen. Und ich konnte auch nichtfps="fps=1/600"
zur Arbeit kommen. Haben Sie übrigens eine Idee zu superuser.com/questions/725734 ? Vielen Dank für all Ihre Hilfe. Ich freue mich sehr darauf, meiner Familie zu helfen, unzählige alte Erinnerungen zu entdecken.Schätzen Sie beide Skripte, eine großartige Möglichkeit, Videos zu teilen.
Trotzdem hatte ich einige Probleme mit Videos, die danach nicht die richtige Zeit zeigten, und ich konnte nicht zu einer bestimmten Zeit springen. Eine Lösung bestand darin, die Streams mit Mp4Box zu demuxen und dann zu muxen.
Eine andere, einfachere Möglichkeit für mich war, mkvmerge zum Teilen zu verwenden. Daher mussten beide Skripte geändert werden. Für detect_black.ps1 musste nur die "* .mkv" zur Filteroption hinzugefügt werden, aber das ist nicht unbedingt so, wenn Sie nur mit mp4-Dateien beginnen.
Die Funktion ist die gleiche, aber bisher keine Probleme mit den Videozeiten. Danke für die Inspiration.
quelle
Ich hoffe, ich liege falsch, aber ich denke nicht, dass Ihre Frage möglich ist. Es mag möglich sein, Videos neu zu codieren, aber als "einfaches verlustfreies Stück" kenne ich keinen Weg.
Viele Videobearbeitungsprogramme verfügen über eine automatische Analysefunktion oder eine ähnliche Funktion, mit der Sie Ihre Videos möglicherweise in schwarze Rahmen aufteilen können. Dies erfordert jedoch eine Neukodierung des Videos.
Viel Glück!
quelle