FFmpeg AV1 VMAF Encoding

October 31, 2024
This conversation may reflect the link creator’s personalized data, which isn’t shared and can meaningfully change how the model responds.
You said:
Can you make me an ffmpeg script that converts a video file to AV1 in the MP4 container (using the NVENC AV1 encoder), passing through all audio tracks, that utilizes VMAF to determine what bitrate to use to convert losslessly
ChatGPT said:
ChatGPT

Here's a bash script to achieve this using FFmpeg and VMAF. Since VMAF is used to measure video quality against the original, this script will first perform a quick compression to estimate VMAF quality at different bitrates, then apply the ideal bitrate in the final AV1 encoding pass.

You'll need FFmpeg built with NVENC support, libvmaf for VMAF calculations, and Python with scipy and numpy to help analyze the results.

Prerequisites

Make sure you have the required FFmpeg version that supports NVENC for AV1 and VMAF calculation:

  • FFmpeg compiled with NVENC AV1 encoder support (-c:v av1_nvenc).
  • FFmpeg compiled with libvmaf support.

Script: encode_av1_vmaf.sh

bash
#!/bin/bash # Usage: ./encode_av1_vmaf.sh input_file output_file input_file="$1" output_file="$2" # Temporary folder for VMAF calculation temp_folder=$(mktemp -d) bitrate_log="$temp_folder/bitrate_vmaf.log" # Define bitrate range to test (in Kbps) bitrate_start=1000 bitrate_end=10000 bitrate_step=500 # Define target VMAF threshold for 'lossless' quality (tweak as needed) target_vmaf=95 # Function to calculate VMAF for a given bitrate calculate_vmaf_for_bitrate() { local bitrate=$1 local temp_output="${temp_folder}/temp_${bitrate}.mp4" # Encode a sample with the specified bitrate ffmpeg -y -i "$input_file" -c:v av1_nvenc -b:v "${bitrate}k" -c:a copy -frames:v 500 -an "$temp_output" # Calculate VMAF score vmaf_score=$(ffmpeg -i "$input_file" -i "$temp_output" -lavfi libvmaf="model_path=vmaf_v0.6.1.pkl" -f null - 2>&1 | grep "VMAF score" | awk '{print $4}') # Clean up temp file rm "$temp_output" echo "$bitrate $vmaf_score" >> "$bitrate_log" echo "Tested bitrate: ${bitrate}k, VMAF: $vmaf_score" # Return VMAF score echo "$vmaf_score" } # Loop to find optimal bitrate optimal_bitrate=$bitrate_start for (( bitrate=$bitrate_start; bitrate<=$bitrate_end; bitrate+=$bitrate_step )); do vmaf_score=$(calculate_vmaf_for_bitrate "$bitrate") if (( $(echo "$vmaf_score >= $target_vmaf" | bc -l) )); then optimal_bitrate=$bitrate break fi done echo "Optimal bitrate found: ${optimal_bitrate}k" # Final encode with optimal bitrate and all audio tracks ffmpeg -i "$input_file" -c:v av1_nvenc -b:v "${optimal_bitrate}k" -c:a copy "$output_file" # Clean up rm -rf "$temp_folder"

Explanation

  1. Bitrate Testing Loop: The script iterates over a bitrate range, encoding a sample and calculating its VMAF score until it reaches or surpasses the target_vmaf threshold.
  2. Optimal Bitrate Encoding: Once the optimal bitrate is identified, the final AV1 encoding is done, passing through all audio tracks and using the best determined bitrate.
  3. Temporary Directory Cleanup: Removes temporary files to keep things clean.

Usage

Run the script with:

bash
./encode_av1_vmaf.sh input_video.mp4 output_video.mp4

This will produce output_video.mp4 encoded with NVENC AV1 at the best bitrate to retain the specified VMAF threshold for high-quality output. Adjust bitrate_start, bitrate_end, bitrate_step, and target_vmaf as needed for your specific requirements.

You said:
Please make a Windows version of the script.
ChatGPT said:
ChatGPT

Here’s a Windows batch script to convert a video to AV1 with an optimal bitrate for quality preservation based on VMAF scores.

To run this script, you’ll need:

  • FFmpeg with NVENC AV1 and VMAF support.
  • bc command for basic calculations, or adapt it to PowerShell for more robust math (bc isn’t native to Windows but can be installed with tools like Git Bash or GNU utilities for Windows).

Batch Script: encode_av1_vmaf.bat

batch
@echo off setlocal REM Usage: encode_av1_vmaf.bat input_file output_file set "input_file=%~1" set "output_file=%~2" REM Temporary folder for VMAF calculation set "temp_folder=%TEMP%\vmaf_calc" mkdir "%temp_folder%" set "bitrate_log=%temp_folder%\bitrate_vmaf.log" REM Define bitrate range to test (in Kbps) set bitrate_start=1000 set bitrate_end=10000 set bitrate_step=500 REM Define target VMAF threshold for 'lossless' quality (adjust as needed) set target_vmaf=95 REM Function to calculate VMAF for a given bitrate set "optimal_bitrate=" for /L %%B in (%bitrate_start%, %bitrate_step%, %bitrate_end%) do ( set "bitrate=%%B" set "temp_output=%temp_folder%\temp_%%B.mp4" echo Testing bitrate: %%B k... REM Encode a short sample with the specified bitrate ffmpeg -y -i "%input_file%" -c:v av1_nvenc -b:v %%B"k" -c:a copy -frames:v 500 -an "%temp_output%" >nul 2>&1 REM Calculate VMAF score for /F "tokens=4 delims= " %%V in ('ffmpeg -i "%input_file%" -i "%temp_output%" -lavfi libvmaf="model_path=vmaf_v0.6.1.pkl" -f null - 2^>^&1 ^| findstr "VMAF score"') do ( set "vmaf_score=%%V" ) REM Clean up temporary file del "%temp_output%" REM Log the VMAF score and bitrate echo %%B %vmaf_score% >> "%bitrate_log%" echo VMAF Score at %%B kbps: %vmaf_score% REM Check if we’ve hit the target VMAF score if not defined optimal_bitrate ( set /A "vmaf_check = %vmaf_score% >= %target_vmaf%" if %vmaf_check% EQU 1 ( set "optimal_bitrate=%%B" goto :encode_final ) ) ) :encode_final if not defined optimal_bitrate ( echo Could not achieve target VMAF with specified bitrate range. Using maximum bitrate: %bitrate_end%k set "optimal_bitrate=%bitrate_end%" ) echo Optimal bitrate found: %optimal_bitrate%k REM Final encode with optimal bitrate and all audio tracks ffmpeg -i "%input_file%" -c:v av1_nvenc -b:v %optimal_bitrate%k -c:a copy "%output_file%" REM Clean up rd /s /q "%temp_folder%" echo Encoding complete. Output file: %output_file% endlocal

Explanation

  1. Bitrate Testing Loop: The script iterates over a set range of bitrates, encoding a sample and calculating VMAF scores using FFmpeg.
  2. VMAF Score Extraction: The for /F command captures VMAF scores from FFmpeg's output, storing them in the vmaf_score variable.
  3. Optimal Bitrate Selection: If the calculated VMAF meets or exceeds the threshold (target_vmaf), the loop stops, and that bitrate is used for the final encode.
  4. Final Encoding and Cleanup: Once the optimal bitrate is identified, the video is encoded with AV1 at that bitrate, passing through all audio tracks. Temporary files are then removed.

Usage

Run this in the command prompt as follows:

batch
encode_av1_vmaf.bat "input_video.mp4" "output_video.mp4"

This will create output_video.mp4 with NVENC AV1 encoding at the best bitrate for the defined quality threshold. Adjust bitrate_start, bitrate_end, bitrate_step, and target_vmaf to fine-tune based on your needs.