Detect video noise using FFMpeg
Hi Folks
I've been working on an autoconversion Bash script to pick up videos and convert them to AV1. Yes, I know converting a source to another source means degradation and yada yada yada, but it's something I can live with as most of my sources are of very high quality to begin with, and I'm going for space-saving. Plus, my eyes aren't what they once were.
The conversion into AV1 I'm mostly happy with. I'm currently going through some old 90s shows which are of lesser quality, so they would need a little help to look better with AV1 by adding some natural film grain, else AV1 makes them look a little bit too clean.
I can easily pop into the script and enable film grain in the variables, or add in a simple option, but that's boring and tedious. Why do that when we can automate the world :)
Where I have got to is using the signalstats filter. The issue I have is I don't know how to analyse it's output enough to work out whether I should or shouldn't enable film grain or not. I know it's subjective either way.
Does anyone have experience with this? The output per frame looks like:
frame:1438 pts:59977 pts_time:59.977
lavfi.signalstats.YMIN=0
lavfi.signalstats.YLOW=0
lavfi.signalstats.YAVG=60.6913
lavfi.signalstats.YHIGH=149
lavfi.signalstats.YMAX=239
lavfi.signalstats.UMIN=91
lavfi.signalstats.ULOW=108
lavfi.signalstats.UAVG=121.955
lavfi.signalstats.UHIGH=131
lavfi.signalstats.UMAX=148
lavfi.signalstats.VMIN=124
lavfi.signalstats.VLOW=128
lavfi.signalstats.VAVG=134.535
lavfi.signalstats.VHIGH=146
lavfi.signalstats.VMAX=154
lavfi.signalstats.SATMIN=0
lavfi.signalstats.SATLOW=0
lavfi.signalstats.SATAVG=9.74682
lavfi.signalstats.SATHIGH=27
lavfi.signalstats.SATMAX=43
lavfi.signalstats.HUEMED=147
lavfi.signalstats.HUEAVG=162.949
lavfi.signalstats.YDIF=0.737433
lavfi.signalstats.UDIF=0.642897
lavfi.signalstats.VDIF=0.162755
lavfi.signalstats.YBITDEPTH=8
lavfi.signalstats.UBITDEPTH=8
lavfi.signalstats.VBITDEPTH=8
I'm happy to analyse a random 60-second segment and then grab an average from a couple of these outputs, but I'm not sure if this is a good method or not. I'm asked a couple of the biggest LLMs, they have come back with older ways that no longer exist in ffmpeg 7.1.
I'm trying not to use too many other pieces of software in this script. The dependencies are fairly simple with ffmpeg, awk, grep, etc., the kind of thing you get on nearly every distro of Linux. Any thoughts and/or ideas?
I think I have cured my issue already. I moved to use PSNR and found a half decent write up on values.
I do wonder if the grain levels are good, so let me know if you think those need a tweak.
One thing that it does seriously impact is encoding time. Shows that usually encode at 2-3x speed suddenly drop off to 0.886x-0.6x encode speed. This is all on the CPU and I only have an AMD Ryzen 5 5600X 6-Core Processor.