Tag: AV1

  • Low Resolution AV1 Encoding

    Low Resolution AV1 Encoding

    AV1 encoding allows for video files to be stored and streamed at much higher quality for the same file size or at a much smaller file size with the same quality compared to older codecs such as H.264, HEVC, and VP9. A lot has been written about its potential for streaming HD and higher-resolution video, but as a fan of both self-hosting and offline files, I also see use cases for lower resolutions. For example, I am interested in how much less storage I need to take a number of movies offline with me on my phone.

    After some experimentation, I have settled on good-quality 480p as the minimum resolution for an enjoyable movie-watching experience on a 6-inch phone display—that is about DVD resolution. The next challenge was to find the optimal parameters for encoding the video files to ensure sufficient quality at the smallest possible file size.

    The Experiment

    For my experiment, I decided to use my RTX 40-series graphics card’s NVENC encoder at the default “p4,” fast “p1,” and highest quality “p7” presets. This should be representative of what I would do for real-world low-resolution AV1 encoding of movies to take with me. CPU encoding might yield even higher quality, but it would likely be dramatically slower (although I haven’t yet tested the exact difference).

    As a test sample, I’m using a snippet of one of my favorite movies, Children of Men. The input file is H.264-encoded, 1080p24 resolution, and the video bitrate hovers between 3 and 5 Mbit/s—so the quality is “fine” but not great. My goal is to achieve comparable subjective quality at a lower resolution and on a smaller screen with the lowest possible bitrate in AV1.

    I’m using variations of the following script to crop out a scene from the input file, re-encode it with AV1, and then extract a screenshot at every CQ value. I’m running it once with each preset.

    #!/bin/bash
    
    ffmpeg -hwaccel cuda -ss 570 -i "Children of Men.mp4" -t 60 -c:v copy -c:a copy temp_snippet.mp4
    
    for cq in {0..51}; do
        ffmpeg -hwaccel cuda -i temp_snippet.mp4 -vf "scale=-2:480" -c:v av1_nvenc -b:v 0 -map 0:v:0 -preset p4 -cq ${cq} output4_cq${cq}.mkv
        ffmpeg -hwaccel cuda -i output4_cq${cq}.mkv -ss 00:00:30 -vframes 1 screenshot4_cq${cq}.png
    done
    
    rm temp_snippet.mp4

    Since encoding quality is subjective and the ideal settings vary based on the content of the video, you should use this as a guideline for your own tests. I’m trying to address the lack of data specifically for low-resolution AV1 encoding. Adjust the variables to your needs and preferences.

    The Results

    The input file is 2.9GB for 110 minutes of runtime, averaging 26MB per minute of video. 480p has only 14% of the number of pixels per frame compared to 1080p. Thus, I’m excluding all results where the output file of the one-minute clip is larger than 14% of 26MB. That is 3.6MB—anything larger is completely pointless. I will address the p1 and p4 results here; p7 is still fast with NVENC and will yield the best results.

    Fastest Preset Results

    At preset 1, the highest quality file that just barely stays under this threshold was encoded at CQ37:

    Unsurprisingly, it looks basically as good as the source, minus the resolution.
    Unsurprisingly, it looks basically as good as the source, minus the resolution.

    You can save 50% of the original storage at CQ44:

    The result is noticeably softer—look at Jasper's hair. To my taste, this is a bit too soft, even on a small screen.
    The result is noticeably softer—look at Jasper’s hair. To my taste, this is a bit too soft, even on a small screen.

    I found that at p1, I would only want to go down to about CQ39 before quality drops too much:

    In motion, this looks close enough to the source to be acceptable to me.
    In motion, this looks close enough to the source to be acceptable to me.

    At these settings, you only save about 23% of storage. That is not really enough for me to bother with re-encoding the movies I want to take with me. Even though the encode is extremely fast, I would only do this if I was in a hurry. In that case, I would just scale the source down, which is even faster.

    Default Preset Results

    At p4 and CQ37, quality looks about the same as the source—unsurprisingly:

    Basically perfect sharpness and motion.
    Basically perfect sharpness and motion.

    What’s much more interesting is the result for CQ44:

    Sharpness is way better than CQ44 at p1 and still just about good enough for me to use for low-quality AV1 encoding.
    Sharpness is way better than CQ44 at p1 and still just about good enough for me to use for low-quality AV1 encoding.

    Some blocking and banding become more visible at this bitrate since sharpness is so much better. It doesn’t show up too much in the screenshot but is slightly visible in motion on flat-colored surfaces. One example is Jasper’s black shirt.

    Still, at this setting, you save about 50% of storage, which is significant. This looks almost as good to me as CQ39 at p1.

    Going any further with the CQ setting results in a rapid loss of quality.

    Slowest Preset Results

    The p7 results will be the most interesting. In practice, I probably wouldn’t mind encoding at this preset since it’s still fast enough—that is, if it yields even better results than p4.

    Going right into CQ44, the result is only slightly sharper than at p4, but the blocking is also reduced. There is a little more detail in the dark shirt.
    Going right into CQ44, the result is only slightly sharper than at p4, but the blocking is also reduced. There is a little more detail in the dark shirt.
    Unfortunately, I found that while sharpness is preserved better at p7 at higher CQ values, the blocking increases quickly. Even at CQ45, it's visibly stronger.
    Unfortunately, I found that while sharpness is preserved better at p7 at higher CQ values, the blocking increases quickly. Even at CQ45, it’s visibly stronger.

    However! This blocking is only very noticeable in stills and when comparing side by side with lower CQ values. In motion, I found it to be much less of a distraction than a blurry picture.

    I found CQ47 to be tolerable in motion. Thus, this is the perfect balance for low-resolution AV1 encoding of movies. Using that as a baseline, I re-encoded the entire movie and tested if it held up in faster-paced scenes on my phone. And it did!
    I found CQ47 to be tolerable in motion. Thus, this is the perfect balance for low-resolution AV1 encoding of movies. Using that as a baseline, I re-encoded the entire movie and tested if it held up in faster-paced scenes on my phone. And it did!

    Conclusion: Low-Resolution AV1 Encoding

    The resulting movie is almost one-third the file size of the H.264-encoded source (but downscaled). In a direct comparison, it is noticeably, but acceptably, softer. I find the blocking to be basically unnoticeable in motion and on the small screen. The bitrate is a tiny 210 kbit/s on average. I also found that a modern GPU can comfortably encode AV1 at 480p at nearly 1000 FPS. That is fast enough that there is no justification to use anything but p7, even if the difference compared to p4 is fairly modest.