it-swarm.com.de

Verwenden von FFMPEG: Wie führt man eine Szenenänderungserkennung durch? mit Timecode?

Basierend auf diesem Artikel scheint es möglich zu sein, FFMPEG zu verwenden, um Szenenänderungen in Videos zu erkennen: http://www.luckydinosaur.com/u/ffmpeg-scene-change-detector

Jetzt habe ich ein Video, das einen Buchtext anzeigt, und wenn der Text (Word oder Satz) gesprochen wird, wird er hervorgehoben. Etwas wie dieses Hörbuch: https://youtu.be/lA7L6ZNVKjc

Ich muss den Zeitstempel kennen, wenn der Text hervorgehoben wird (daher Szenenwechsel). Dies ermöglicht mir das Hinzufügen von Zeitstempel-Tags zu meinem Youtube-Video, sodass die Zuhörer leichter durch das Hörbuch navigieren können.

Was ist die Befehlszeile magic, die dies tun würde?

Vielen Dank!

14
Mozart

Durch die Kombination des scene - Filters (zur Erkennung von Szenenänderungen) und des showinfo - Filters sollten Sie erreichen, was Sie möchten:

ffmpeg -i input.flv  \
       -filter:v "select='gt(scene,0.4)',showinfo" \
       -f null \
       - 2> ffout

Dieser Befehl extrahiert alle Frames, die sich vom vorherigen Frame um mehr als (gt) 0.4 (auf einer Skala von 0 bis 1) unterscheiden. Für diese Frames werden Informationen wie folgt ausgedruckt (showinfo)

[Parsed_showinfo_1 @ 0x2d85e60] n:   0 pts:2537204 pts_time:2.5372  pos:  2998114 fmt:rgb24 sar:1/1 s:1920x1200 i:P iskey:1 type:I checksum:5616582E plane_checksum:[5616582E]

Jetzt müssen Sie nur noch den Zeitstempel extrahieren. Ich denke, Sie interessieren sich für pts_time. Du könntest es so machen:

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep [0-9.]* -o > timestamps

Dadurch erhalten Sie die Liste aller Zeitstempel:

2.5372
4.37799
6.65301
8.09344

Damit dieser Ansatz funktioniert, benötigen Sie eine Version von FFmpeg, die die Szenenerkennung implementiert. Außerdem müssen Sie einen geeigneten Wert für den Schwellenwert auswählen (0.4 im ersten Befehl). Sie können versuchen, einen optimalen Schwellenwert zu finden, indem Sie Frames für verschiedene Schwellenwerte extrahieren (und die Frames anschließend manuell untersuchen)

ffmpeg -i input.flv \
       -filter:v "select='gt(scene,0.1)',showinfo" \
       -vsync 0 frames/%05d.jpg

Nur zur Klarstellung: grep [0-9.]* schließt Ganzzahlen nicht aus, wie sie in einer anderen Antwort beansprucht werden. Es passt zu jeder Zeichenfolge, die aus Ziffern und Punkten besteht, würde jedoch auch Nicht-Nummern wie '4.4.4' entsprechen. Ffmpeg sollte jedoch nicht so schlecht geformte Zeitstempel ausgeben.

17
ckoehn

Ich habe nicht den Vertreter, um einen Kommentar zu der obigen Antwort zu posten, aber ich möchte darauf hinweisen, dass der von @ckoehn und @keypulsations gepostete grep nur Zeitstempel erfasst, die Fließkomma sind. Verwenden Sie den folgenden Regex, um sowohl Fließkomma- als auch Ganzzahl-Zeitstempel abzufragen

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep -E '[0-9]+(?:\.[0-9]*)?' -o > timestamps
7
Luke Harrison

Ich versuchte die @ckoehn-Antwort und es funktionierte, bis es aufhörte zu arbeiten, das Sternchen im letzten grep verursachte Probleme. Um dies zu vermeiden, empfehle ich in den grep-Sätzen doppelte Anführungszeichen wie:

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep "[0-9.]*" -o > timestamps
3

Sie können einfach den Befehl verwenden:

ffmpeg inputvideo.mp4 -filter_complex "select='gt(scene,0.3)',metadata=print:file=time.txt" -vsync vfr img%03d.png

Dadurch werden nur die relevanten Informationen in der Datei time.txt gespeichert (siehe unten).

frame:0    pts:108859  pts_time:1.20954
lavfi.scene_score=0.436456
frame:1    pts:285285  pts_time:3.16983
lavfi.scene_score=0.444537
frame:2    pts:487987  pts_time:5.42208
lavfi.scene_score=0.494256
frame:3    pts:904654  pts_time:10.0517
lavfi.scene_score=0.462327
frame:4    pts:2533781 pts_time:28.1531
lavfi.scene_score=0.460413
frame:5    pts:2668916 pts_time:29.6546
lavfi.scene_score=0.432326

Das Bild ist die Seriennummer der erkannten Schussänderung vom Start. Wählen Sie Ihren Schwellenwert (hier 0,3) entsprechend Ihrem Anwendungsfall aus, um korrekte Ausgaben zu erhalten

1
Abhijeet