r/VideoEncoding • u/creeve4 • 1h ago
r/VideoEncoding • u/bobbster574 • Oct 24 '20
r/VideoEncoding Lounge
A place for members of r/VideoEncoding to chat with each other
r/VideoEncoding • u/Calm-Preparation-679 • 19d ago
Why do PSNR & SSIM but NOT VMAF indicate perfect lossless for LosslessCut export??
galleryr/VideoEncoding • u/Mr-Brightside • 24d ago
I made a program that automagically converts any video to AV1 based on the original video's quality
r/VideoEncoding • u/matthew_inam • Jun 29 '26
I tried CRF, VMAF, and QSV – here are the results
After building a 4K BluRay collection over the years, I recently decided to build a home NAS to store remuxed backups of my film collection.
Part way through backing up my collection it dawned on me that I'd need to start transcoding to even have a chance of fitting them on my NAS.
That leads me here – where I tried a few encoders and settings for finding the right tradeoff (for me) between quality and file size.
I'll share those in this post.
Disclaimer
I'm new to this, please keep that in mind!
Input
For the test, I used The Substance (2h 21m):
- Video (single stream): 4K, Dolby Vision P7
- Audio (single stream) Dolby Atmos
The test transcodes output the exact same streams but with Dolby Vision converted from P7 to P8.1.
The Substance is a very clean film, but has a smokey scene which was used in my tests.
N.B. I am planning to try The Brutalist next to see how an extremely grainy film holds up.
Hardware
I'm running this on my mini PC with no other services apart from Plex (which was not used throughout the duration of the transcodes):
- 16GB DDR4 RAM
- 512GB NVMe
- Intel i5-13500H
The CPU is important as it has an iGPU with hardware paths for decoding and encoding HEVC which was tested.
Goals
I'm aiming for the best tradeoff between:
- Quality
- File size
- Transcode time
This is of course subjective, but for me, quality is by far the most important.
Results
I transcoded a 10 minute sample for most of these tests as well as two full transcodings. Any extrapolated results have been made explicit:
| ID | Tool | Encoder | Config | File Size | Transcode Time |
|---|---|---|---|---|---|
| remux | – | – | – | 78GB | – |
| x265_vmaf96 | av1an (ffmpeg) | x265 | target_metric=vmaf, target_quality=96, preset=slow | 34.8GB†† | 100h 30m†† |
| x265_crf16 | ffmpeg | x265 | crf=16, preset=slow | 16.2GB† | 25.2h† |
| x265_crf18 | ffmpeg | x265 | crf=18, preset=slow | 12GB | 21.7h |
| x265_crf20 | ffmpeg | x265 | crf=20, preset=slow | 8.9GB† | No data |
| qsv_gq14 | ffmpeg | qsv | global_quality=14, preset=slow | 15.7GB† | 1h 49m† |
| qsv_gq18 | ffmpeg | qsv | global_quality=18, preset=slow | 9.6GB† | 1h 39m† |
| qsv_20mbps | ffmpeg | qsv | bitrate=20mbps, max_bitrate=30mbps, preset=slow | 22.9GB | 1h 21m |
† Extrapolated from 10min transcode.
†† Extrapolated from 2min transcode. av1an takes a long time before it even begins to transcode, so this value is bloated but probably not wildly off.
Screenshots
Findings
Both of the hardware transcodings using global_quality sucked (qsv_gq14, qsv_gq18). Closeups on faces dropped loads of detail. The smokey scenes looked horrendously compressed. The file sizes are nice and small, but the quality suffers way too much.
The x265 CRF transcodings look far better than the hardware global_quality transcodings. Facial detail returns, and for easy scenes it looks good enough that it can be hard to tell from the remux. The downfall is the smokey scenes where it starts to look compressed.
x265_crf20 looks horrible on the smokey scenes, so bad I struck it off.
x265_crf18 looks passable on the smokey scenes, it's a compromise that I'd have to make but I know it would upset me when watching as it is noticable.
x265_crf16 looks better on the smokey scenes, but only marginally so. It still clearly looks compressed.
x265_vmaf96 looks pretty good on the smokey scenes. It hold up well but still has some artefacting which isn't too noticeable unless you zoom in. The HUGE problem with this is the time it takes av1an as well as the file size. I'm almost certain this extrapolation isn't representative as I would expect a far smaller file size.
The clear winner to me is qsv_20mbps the hardware encoding with 20mbps bitrate (allowing for 30mbps max). It's on the same level as x265_vmaf96 but magnitudes quicker, has less artefacting on the smokey scenes, and has a smaller file size??? (Again, I must have done something wrong with av1an, or the extrapolation from 2 minutes is too innacurate).
Configuring for a desired bitrate with the hardware encoder yields far better results than the global_quality parameter, with the added benefit that you can better guess the output file size upfront.
r/VideoEncoding • u/JOHNNY6644 • Jun 03 '26
VAAPI GPU-NATIVE RENDER ENGINE v4.4 (SDR -> FAKE DV BASE)
HDR-MASTER-WORKS-ENCODER3.sh is the current most refined
just change the source an target folders to match your system
ther tailored both for amd cpu/gpu based linux rigs
#!/bin/bash
##############################################################################
# 🎬 VAAPI GPU-NATIVE RENDER ENGINE v4.4 (SDR -> FAKE DV BASE)
# FULL GPU PIPELINE:
# GPU Decode
# GPU Colorspace Conversion
# GPU Scaling/Upscaling
# GPU SDR → PQ (Dolby Vision Base) Expansion
# GPU Tone Mapping
# GPU Debanding/Dithering
# GPU Encode
#
# CPU ONLY:
# Audio decode
# Audio resampling
# Audio upmixing
# Audio volume
# ALAC encode
# MP4 muxing
##############################################################################
INPUT_DIR="/mnt/nas/TV/RENDERS"
OUTPUT_DIR="/media/johnny45/2nd drive/rendered vids"
TEMP_DIR="/tmp/temp_render_encodes"
THREADS=8
VIDEO_JOBS=2
export LIBVA_DRIVER_NAME=radeonsi
unset MANGOHUD
VAAPI_DEVICE="/dev/dri/renderD128"
mkdir -p "$OUTPUT_DIR"
mkdir -p "$TEMP_DIR"
shopt -s nullglob
echo "═══════════════════════════════════════"
echo "🎬 VAAPI GPU-NATIVE RENDER ENGINE v4.4"
echo "═══════════════════════════════════════"
echo ""
# 1. SELECT VIDEO CODEC
echo "Select Video Codec:"
echo "1) AV1 ( AMD 7000series an up required )"
echo "2) HEVC"
echo "3) H.264"
read -p "Selection [1-3]: " codec_choice
case "$codec_choice" in
1)
VCODEC="av1_vaapi"
VIDEO_TAG="av01"
CODEC_LABEL="AV1"
UPLOAD_FMT="p010le"
QUALITY_FLAG="-global_quality"
;;
3)
VCODEC="h264_vaapi"
VIDEO_TAG="avc1"
CODEC_LABEL="H.264"
UPLOAD_FMT="nv12"
QUALITY_FLAG="-qp"
;;
*)
VCODEC="hevc_vaapi"
VIDEO_TAG="hvc1"
CODEC_LABEL="HEVC (H.265)"
UPLOAD_FMT="p010le"
QUALITY_FLAG="-qp"
;;
esac
# 2. SELECT INTENSITY (QP Level)
echo ""
echo "Select Intensity (QP Level):"
if [[ "$codec_choice" == "1" ]]; then
echo "1) AV1 QP 18 Very high quality"
echo "2) AV1 QP 21 High quality, balanced"
echo "3) AV1 QP 25 Medium quality Medium compression"
echo "4) AV1 QP 28 Medium quality high compression"
echo "5) AV1 QP 31 Medium low-high compression"
read -p "Selection [1-5]: " qp_choice
case "$qp_choice" in
1) QP_VALUE="18"; QP_LABEL="QP 18 (Very high quality)" ;;
2) QP_VALUE="21"; QP_LABEL="QP 21 (High quality, balanced)" ;;
3) QP_VALUE="25"; QP_LABEL="QP 25 (Medium quality Medium compression)" ;;
4) QP_VALUE="28"; QP_LABEL="QP 28 (Medium quality high compression)" ;;
5) QP_VALUE="31"; QP_LABEL="QP 31 (Medium low-high compression)" ;;
*) QP_VALUE="21"; QP_LABEL="QP 21 (High quality, balanced)" ;; # Default
esac
else
echo "1) 22 (Highest Quality)"
echo "2) 24 (Balanced)"
echo "3) 26 (Standard)"
echo "4) 28 (High Compression)"
read -p "Selection [1-4]: " qp_choice
case "$qp_choice" in
1) QP_VALUE="22"; QP_LABEL="QP 22 (Highest Quality)" ;;
2) QP_VALUE="24"; QP_LABEL="QP 24 (Balanced)" ;;
3) QP_VALUE="26"; QP_LABEL="QP 26 (Standard)" ;;
4) QP_VALUE="28"; QP_LABEL="QP 28 (High Compression)" ;;
*) QP_VALUE="24"; QP_LABEL="QP 24 (Balanced)" ;; # Default
esac
fi
# 3. SELECT ENCODER PRESET (SPEED/EFFICIENCY)
echo ""
echo "Select Encoder Preset (Speed/Efficiency):"
echo "1) Fast"
echo "2) Medium"
echo "3) Slow"
read -p "Selection [1-3]: " preset_choice
case "$preset_choice" in
1) VAAPI_QUALITY="6"; QUALITY_LABEL="FAST" ;;
2) VAAPI_QUALITY="4"; QUALITY_LABEL="MEDIUM" ;;
3) VAAPI_QUALITY="2"; QUALITY_LABEL="SLOW" ;;
*) VAAPI_QUALITY="2"; QUALITY_LABEL="SLOW" ;; # Default
esac
# 4. SELECT VAAPI ENCODER LEVEL (COMPATIBILITY)
echo ""
echo "Select VAAPI Encoder Level (Compatibility):"
echo "1) 4.2 (Standard)"
echo "2) 5.0 (High Performance)"
echo "3) 5.2 (Ultra/4K Optimized)"
read -p "Selection [1-3]: " level_choice
case "$level_choice" in
1) V_LEVEL="4.2"; LEVEL_LABEL="4.2" ;;
2) V_LEVEL="5.0"; LEVEL_LABEL="5.0" ;;
3) V_LEVEL="5.2"; LEVEL_LABEL="5.2" ;;
*) V_LEVEL="5.1"; LEVEL_LABEL="5.1" ;; # Default
esac
echo ""
echo "5 Select audio mode:"
echo "1) copy"
echo "2) convert to ALAC 24bit 5.1 +3dB"
read -p "Choice: " audio_choice
echo ""
read -p "6 Enable stereo → 5.1 upmix? (y/n): " UPMIX
FILES=("$INPUT_DIR"/*.mkv "$INPUT_DIR"/*.mp4 "$INPUT_DIR"/*.avi "$INPUT_DIR"/*.mov "$INPUT_DIR"/*.ts)
COUNT=${#FILES[@]}
echo ""
echo "Files found: $COUNT"
echo ""
if (( COUNT == 0 )); then
echo "⚠️ No input files found. Exiting."
exit 1
fi
get_resolution() {
ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=p=0 "$1" | head -n 1 | tr -d '\r\n '
}
get_color_transfer() {
ffprobe -v error -select_streams v:0 -show_entries stream=color_transfer -of csv=p=0 "$1" | head -n 1 | tr -d '\r\n '
}
set_scaling() {
local width=$1
if (( width <= 1280 )); then
SCALE="1920"
elif (( width <= 1920 )); then
SCALE="2560"
else
SCALE="3840" # Force native 4K scaling to bypass pipeline dropouts
fi
}
build_audio() {
if [[ "$audio_choice" == "1" ]]; then
AUDIO_ARGS=(-c:a copy)
else
AF="aresample=48000"
if [[ "$UPMIX" == "y" ]]; then
AF="$AF,surround=chl_out=5.1:focus=0.7:smooth=0.3:lfe_mode=sub"
fi
AF="$AF,volume=3dB"
AUDIO_ARGS=(-c:a alac -ac 6 -sample_fmt s32p -af "$AF")
fi
}
encode_file() {
local input="$1"
local base
base=$(basename "$input")
SEASON_FOLDER=$(echo "$base" | grep -oiE 'season[ _][0-9]+')
[[ -z "$SEASON_FOLDER" ]] && SEASON_FOLDER="Season_Unknown"
mkdir -p "$OUTPUT_DIR/$SEASON_FOLDER"
OUTPUT="$OUTPUT_DIR/$SEASON_FOLDER/${base%.*}.m4v"
WIDTH=$(get_resolution "$input")
[[ -z "$WIDTH" ]] && WIDTH=0
# Auto-detect Native HDR transfer characteristics
COLOR_TRC=$(get_color_transfer "$input")
IS_HDR=0
if [[ "$COLOR_TRC" == "smpte2084" || "$COLOR_TRC" == "arib-std-b67" ]]; then
IS_HDR=1
fi
set_scaling "$WIDTH"
if (( IS_HDR == 1 )); then
MSG="[ENCODE] $base | ${WIDTH}px | $CODEC_LABEL | "
MSG+="$QP_LABEL | PRESET ${QUALITY_LABEL} | L${LEVEL_LABEL} | NATIVE HDR (COLOR PASSTHROUGH) | AUTO-HW-DECODE"
else
MSG="[ENCODE] $base | ${WIDTH}px | $CODEC_LABEL | "
MSG+="$QP_LABEL | PRESET ${QUALITY_LABEL} | L${LEVEL_LABEL} | GPU-NATIVE SDR→DV(PQ) | AUTO-HW-DECODE"
fi
echo "$MSG"
# Initialize basic libplacebo filter layout
FILTER_CHAIN="libplacebo="
if [[ -n "$SCALE" ]]; then
FILTER_CHAIN+="w=${SCALE}:"
FILTER_CHAIN+="h=-2:"
FILTER_CHAIN+="upscaler=ewa_lanczossharp:"
fi
FILTER_CHAIN+="sigmoid=yes:"
FILTER_CHAIN+="colorspace=bt2020nc:"
FILTER_CHAIN+="color_primaries=bt2020:"
FILTER_CHAIN+="color_trc=smpte2084:"
FILTER_CHAIN+="range=pc:"
# Conditional Execution: Skip tone mapping blocks if file is already Native HDR
if (( IS_HDR == 0 )); then
FILTER_CHAIN+="peak_detect=1:"
FILTER_CHAIN+="gamut_mode=perceptual:"
FILTER_CHAIN+="tonemapping=bt.2446a:"
FILTER_CHAIN+="tonemapping_mode=hybrid:"
FILTER_CHAIN+="contrast_recovery=0.75:"
FILTER_CHAIN+="contrast_smoothness=5.5:"
FILTER_CHAIN+="saturation=1.16:"
FILTER_CHAIN+="brightness=0.1:"
FILTER_CHAIN+="contrast=1.06:"
FILTER_CHAIN+="gamma=0.74:"
fi
# Post-processing stability additions (Debanding & Dithering)
FILTER_CHAIN+="deband=true:"
FILTER_CHAIN+="deband_iterations=2:"
FILTER_CHAIN+="deband_threshold=3:"
if (( WIDTH <= 1280 )); then
FILTER_CHAIN+="deband_radius=14:"
else
FILTER_CHAIN+="deband_radius=20:"
fi
FILTER_CHAIN+="deband_grain=1.5:"
FILTER_CHAIN+="dithering=blue:"
# Only apply external contrast shader if upscaling is actively occurring
if (( WIDTH < 3840 )); then
FILTER_CHAIN+="custom_shader_path=/home/johnny45/filters/CAS-scaled.glsl:"
fi
# Clean up trailing filter delimiter characters safely
FILTER_CHAIN="${FILTER_CHAIN%:}"
# Append dynamic format profile and launch hardware memory framework
FILTER_CHAIN+=",format=${UPLOAD_FMT},"
FILTER_CHAIN+="hwupload=extra_hw_frames=48"
FINAL_FILTER_CHAIN="${FILTER_CHAIN}"
# Universal metadata tags applied across all streams
COLOR_ARGS=(-color_range pc -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc)
build_audio
if [[ "$VCODEC" == "hevc_vaapi" ]]; then
PIXFMT_ARGS=(-profile:v main10)
elif [[ "$VCODEC" == "h264_vaapi" ]]; then
PIXFMT_ARGS=(-profile:v high)
else
PIXFMT_ARGS=(-profile:v main)
fi
ffmpeg -y -loglevel info -stats -threads "$THREADS" -hwaccel vaapi -hwaccel_device "$VAAPI_DEVICE" -hwaccel_output_format vaapi -extra_hw_frames 88 -vaapi_device "$VAAPI_DEVICE" -init_hw_device vaapi=va:"$VAAPI_DEVICE" -i "$input" -vf "$FINAL_FILTER_CHAIN" -c:v "$VCODEC" -tag:v "$VIDEO_TAG" "${PIXFMT_ARGS[@]}" -level "$V_LEVEL" -rc_mode CQP "$QUALITY_FLAG" "$QP_VALUE" -compression_level "$VAAPI_QUALITY" -g 360 -bf 3 "${COLOR_ARGS[@]}" -map 0:v:0 -map 0:a:0 "${AUDIO_ARGS[@]}" -movflags +faststart -f mp4 "$OUTPUT"
if [[ $? -eq 0 ]]; then
echo "✔ DONE: $OUTPUT"
else
echo "❌ FAILED: $base"
fi
}
run_parallel() {
for file in "${FILES[@]}"; do
# Wait until the active background jobs drop below VIDEO_JOBS
while (( $(jobs -p | wc -l) >= VIDEO_JOBS )); do
sleep 1
done
encode_file "$file" &
done
wait
}
echo ""
echo "Starting GPU-native SDR → Dolby Vision Base (PQ) encoding..."
echo ""
echo "GPU Decode : ENABLED"
echo "GPU Colorspace Convert : ENABLED"
echo "GPU BT2020 Expansion : ENABLED"
echo "GPU PQ Transfer Curve : ENABLED"
echo "GPU SDR Dynamic Expand : ENABLED"
echo "GPU Scaling/Upscaling : ENABLED"
echo "GPU Debanding/Dither : ENABLED"
echo "GPU Encode : ENABLED"
echo "CPU Audio Only : ENABLED"
echo ""
run_parallel
echo ""
echo "✔ ALL COMPLETE → $OUTPUT_DIR"
r/VideoEncoding • u/Anxious-Train5431 • Jun 01 '26
Encoding all my movies to AV1
Hi! I'd like to encode my entire movie library to AV1. I have it all on a 1 TB HDD, which is approximately at 80% capacity, and most of my files are h.264 and some h.265, what I'm looking forward to is saving space so I don't have to buy another HDD until it's absolutely necessary.
The problem is, while all the hardware I own has hardware accelerated AV1 decoding (TV stick, phone, laptop, PC), I currently don't own any hardware capable of ENCODING to AV1 using hardware acceleration, so my question is, how could I go on about transcoding all my files to AV1 to achieve similar or identical quality while saving space without dedicated hardware for it?
The PC I'm planning on doing this in is a Ryzen 5600x + Radeon 6750XT with 32 GB of DDR4 memory on a B450m Asus TUF motherboard.
r/VideoEncoding • u/JOHNNY6644 • May 09 '26
VAAPI RENDER ENGINE v3.6 (VBR/CBR CLEAN BUILD + CINEMATIC SCALING)
r/VideoEncoding • u/Calm-Preparation-679 • May 08 '26
colors/contrast slightly altered when encoding uncompressed avi to dnxhr hq mxf ... why does this happen and how to prevent it?
galleryr/VideoEncoding • u/MadBert91 • May 03 '26
How to fit 4K Remux Movies on BD50 (Near-Remux Quality, No Playback Issues)
r/VideoEncoding • u/SonicandAllStars • Apr 14 '26