h264-Einstellungen für große flache Bereiche mit langsam wechselnder Farbe

Ich mache eine Animation für ein Projektionsmapping, das simuliert, wie die Sonne Schatten auf eine Struktur wirft, während sie sich durch den Himmel bewegt. Im Grunde sind es nur große, flache Farbbereiche, die sich etwa fünf Minuten lang ändern, wenn die „Sonne“ auf- und untergeht (in einer anderen Projektion). Es wird von einem Brightsign-Wiedergabe-Gizmo abgespielt, und ich verwende das h.264-Hauptprofil als Codec in einem mp4.

Das Problem, das ich habe, ist, dass die Codierung nicht sehr gut mit dem Inhalt umgeht. Obwohl die Farbe völlig flach ist, erscheinen Rauschbänder und Blöcke, wenn sich alle Pixel im Laufe der Zeit ändern. Sie sind subtil, aber sie sind nervig.

Gibt es eine Optimierung, die ich mit libx264 vornehmen kann, um sie für große, flache Farbbereiche zu optimieren, in denen sich alle Pixel gleichzeitig im Laufe der Zeit ändern? Es gibt absolut keine Bewegung im Rahmen, nur die Farbe des gesamten Bereichs ändert sich ziemlich langsam.

Mein aktueller ffmpeg-Befehl ist ziemlich generisch:

ffmpg -i input.mov -c:v libx264 -preset slow -profile main -crf 20 -pix_fmt yuv420p -an output.mp4
Bitte fügen Sie die vollständige ffmpegKonsolenausgabe bei. Können Sie ein kurzes Eingabebeispiel zur Verfügung stellen? -crfHilft es, auf ~18 zu reduzieren ? Macht -tune animationeinen Unterschied? Wenn nichts hilft, können Sie den gradfunVideofilter bei der Wiedergabe verwenden.

Antworten (3)

Die Bänder, auf die Sie sich beziehen, könnten durchaus nur eine Einschränkung des 8-Bit-Farbraums sein.

Theoretisch lässt sich dies lösen, indem in jeder Phase vom Rendering über die Bearbeitung und das Mastering bis hin zur Ausgabe und sogar auf dem Bildschirm oder Projektor der 10- oder 12-Bit-Farbraum verwendet wird. Ihre endgültige Ausgabe wird jedoch wahrscheinlich in einem Bereich von 8 Bit pro Kanal angezeigt, ob Sie dies mögen oder nicht.

Der praktische Weg, dies zu tun, besteht also darin, mit 10- oder 12-Bit-Farbe zu rendern und vom Master auf 8-Bit herunterzudithern. Das Dithering verhindert das sichtbare Auftreten von Banding, wenn es mit 8 Bit pro Kanal angezeigt wird.

Beachten Sie, dass dies keine Einschränkung von h.264 oder einem anderen Encoder ist, sondern vom verwendeten Farbraum und der rauschfreien Natur der gerenderten Animation; Wenn das wirkliche Leben so rauschfrei wäre, würde es diese Streifenbildung auch in 8-Bit-Farbräumen zeigen. Es ist unwahrscheinlich, dass Sie in Ihrem Encoder eine Einstellung auswählen können, um dieses Problem zu lösen. Rendern Sie zur Bestätigung in ein unkomprimiertes Format, und Sie werden wahrscheinlich immer noch die Streifenbildung sehen.

Hinweis: Das Dithering von einem 10- oder 12-Bit-Rendering ist nicht dasselbe wie das Hinzufügen von Rauschen zu einem vorhandenen 8-Bit-Dithering - obwohl dies das Banding ein wenig verschleiern kann, indem es einfach weniger deutlich wird, löst es es nicht . Aber zur Not könnte man das machen.

danke, aber es liegt wahrscheinlich nicht an den Einschränkungen der 8-Bit-Ausgabe. Streifenbildung tritt bei Farbverläufen auf. Dies sind flache Farbbereiche, bei denen jedes Pixel den gleichen Wert hat. Die Komprimierung führt die Streifenbildung ein, wenn sich die Pixel mit der Zeit ändern.
Haben Sie in diesem Fall mit niedrigeren CRF-Werten gespielt? 20 kann in überwiegend flachen Farbbereichen mit Animation nicht transparent sein. Bei gerenderten Animationen sollten Sie mit viel niedrigeren CRF-Werten (z. B. 16) auskommen. Sie können mit etwas sehr hoher Qualität wie 10 oder sogar verlustfrei testen, nur um zu sehen, ob die Quantisierung überhaupt ein Faktor ist.

Je nachdem, wie der Inhalt erstellt wurde, kann die Streifenbildung eingeführt werden, wenn Sie Ihren Inhalt vom RGB-Farbraum in YUV konvertieren. Sie können versuchen, ein h264 zu erstellen und dabei den RGB-Farbraum beizubehalten, obwohl ich gelesen habe, dass dies nicht einfach ist. Kannst du einen anderen Codec verwenden?

Das erste, was ich versuchen würde, ist, Ihrem ursprünglichen Befehl hinzuzufügen -force_key_frames, die Voreinstellung zu löschen und den -crfWert zu verringern. Das folgende Beispiel setzt jede Sekunde einen Keyframe.

ffmpg -i input.mov -c:v libx264 -profile main \
    -force_key_frames expr:gte(t,n_forced*1) \
    -crf 15 -pix_fmt yuv420p -an output.mp4

Als zweiten Ausweg würde ich eine Reihe von PNG-Bildern (anstelle von MOV) als Eingabe verwenden und einen sehr niedrigen CRF verwenden. Auf diese Weise können Sie wirklich sicherstellen, dass Ihr Input keine Streifenbildung aufweist und das Endmaterial von höchster Qualität ist. Wenn Sie nicht direkt in PNG rendern können, konvertieren Sie das Originalmaterial.

Hier ist ein Beispiel:

# turn the original into pngs
ffmpeg -i input.mov -f image2 -threads 0 /tmp/%05d.png

# turn the pngs back into mp4 (assuming 25 fps)
ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -r 25/1 -f image2 \
  -i /tmp/%05d.png -c:a libfdk_aac -c:v libx264 \ 
  -profile main -vf "fps=fps=25" -force_key_frames expr:gte(t,n_forced*1) \
  -crf 10 -threads 0 -pix_fmt yuv420p output.mp4

p.s. Aufgrund von Synchronisierungsproblemen sollten Sie sich angewöhnen, eine stumme Audiospur für die Wiedergabe von Mediengeräten einzuschließen.