Daniel's Derpy Ultracompressor

in Video Encoding and Archival | Posted by brothchild on Mar 22, 2026 10:14 PM

#!/usr/bin/env bash

# ========================================
# INTELLIGENT HEVC VIDEO COMPRESSION PIPELINE
# ----------------------------------------------------------------------------
# This script compresses video files to H.265 (HEVC) with Opus audio.
# It is designed for archival purposes where file size reduction is
# prioritized while maintaining perceptual quality.
#
# Features:
# - Two-pass or Single-pass libx265 encoding with smart bitrate targeting.
# - Automatic audio normalization (Peak detection -> Target dB).
# - Black bar detection and cropping.
# - Logarithmic bitrate targeting (soft compression for high bitrate sources)
# OR Manual scaling factor targeting (strict size reduction).
#
# Usage:
# ./script.sh [scale_factor] <input_file>
#
# Examples:
# ./script.sh video.mkv (Use auto bitrate curve)
# ./script.sh 2.0 video.mkv (Target 1/2 of original size)
# ./script.sh 1.5 video.mkv (Target 1/1.5 of original size)
#
# Author: Clort (clort81)
# Requires: ffmpeg, ffprobe, bc, coreutils
# ========================================

# Strict Mode:
# -e: Exit immediately if a command exits with a non-zero status.
# -u: Treat unset variables as an error.
# -o pipefail: Return value of a pipeline is the status of the last command to exit with a non-zero status.
set -euo pipefail

# ----------------------------
# GLOBAL CONSTANTS
# ----------------------------
readonly MAX_WIDTH=960 # Target Width (Quarter HD)
readonly MAX_HEIGHT=540 # Target Height
readonly VIDEO_CODEC="libx265" # HEVC Encoder
readonly AUDIO_BITRATE="12k" # Opus Bitrate (Speech optimized)
readonly ENCODING_PRESET="fast" # Speed/Efficiency tradeoff

# Audio Normalization Target (dBFS)
# The script detects the current maximum volume and calculates gain
# to reach this target level.
# Example: -20 targets -20dB. 0 targets 0dB (Maximum digital volume).
readonly TARGET_VOL="-18"

# Encoding Parameters for Single Pass
# ref=4: Decent reference frames for compression without killing speed.
# subme=6: High quality motion estimation.
# aq-mode=1: Adaptive Quantization (varies bitrate based on frame complexity).
readonly ENCODING_PARAMS="scc=2:weightp=1:weightb=1:ref=4:bframes=8:rc-lookahead=60:aq-mode=1:deblock=-3,-3:subme=6:rd=4"

# Scaling Filter
# force_original_aspect_ratio=decrease ensures we fit within the box without stretching.
readonly SCALE_FILTER="scale='min(${MAX_WIDTH},iw):min(${MAX_HEIGHT},ih)':force_original_aspect_ratio=decrease"

# Bitrate Mapping Constants (Auto-Mode only)
readonly MIN_TARGET_KBPS=110
readonly MAX_TARGET_KBPS=192

# ----------------------------
# HELPER FUNCTIONS
# ----------------------------

# Usage: die "Error message"
die() {
echo "ERROR: $*" >&2
exit 1
}

# Get duration in seconds (float)
# Relies on ffprobe returning standard format=duration
get_duration() {
local file="$1"
local dur
dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$file" 2>/dev/null) || return 1
case "$dur" in
""|"N/A") return 1 ;;
esac
printf '%s\n' "$dur"
}

# Get video stream bitrate (bps)
get_stream_bitrate_bps() {
local file="$1"
local br
# -select_streams v:0 selects only the first video stream
br=$(ffprobe -v quiet -select_streams v:0 -show_entries stream=bit_rate -of csv=p=0 "$file" 2>/dev/null) || return 1
[[ "$br" =~ ^[0-9]+$ ]] && (( br > 0 )) && echo "$br"
}

# Get global container bitrate (bps)
get_global_bitrate_bps() {
local file="$1"
local br
br=$(ffprobe -v quiet -show_entries format=bit_rate -of csv=p=0 "$file" 2>/dev/null) || return 1
[[ "$br" =~ ^[0-9]+$ ]] && (( br > 0 )) && echo "$br"
}

# Fallback: compute bitrate from file size / duration
compute_bitrate_from_filesize() {
local file="$1"
local dur
dur=$(get_duration "$file") || return 1

if ! printf '%s\n' "$dur" | grep -E '^[0-9]*\.?[0-9]+$' >/dev/null; then
return 1
fi
if (( $(bc -l <<< "$dur <= 0") )); then
return 1
fi

local size
# stat -c%s returns size in bytes (Linux standard)
size=$(stat -c%s "$file" 2>/dev/null) || return 1
(( size > 0 )) || return 1

local br_bps
br_bps=$(bc -l <<< "($size * 8) / $dur" 2>/dev/null) || return 1
br_bps=$(printf "%.0f" "$br_bps" 2>/dev/null)

[[ -n "$br_bps" ]] && (( br_bps > 0 )) && echo "$br_bps"
}

# Determine best estimate for input bitrate
get_effective_video_bitrate_bps() {
local file="$1"
echo " -> Attempting stream-level bitrate extraction..." >&2
if get_stream_bitrate_bps "$file"; then return 0; fi

echo " -> Falling back to global container bitrate..." >&2
if get_global_bitrate_bps "$file"; then return 0; fi

echo " -> Falling back to file size / duration calculation..." >&2
if compute_bitrate_from_filesize "$file"; then return 0; fi

die "All methods failed to determine input bitrate for $file"
}

# Log-curve calculation for Auto-Mode
# Formula: y = 488.4 * ln(x + 1000) - 3211
calculate_target_bitrate_kbps() {
local x="$1"
# Sanitize: ensure we only pass numbers to bc
x=$(printf '%s' "$x" | tr -cd '0-9.')
[[ -z "$x" || "$x" == "." ]] && x=800

local y
# bc logic: calculate y, then scale=0 to round to nearest integer
y=$(bc -l <<< "
scale = 10
x = $x
if (x + 1000 <= 0) { 0 } else {
y = 488.4 * l(x + 1000) - 3211
if (y < 0) 0 else y
}
scale = 0
(y + 0.5) / 1
" 2>/dev/null)

# Fallback if bc fails (math domain error or missing utility)
if ! [[ "$y" =~ ^[0-9]+$ ]]; then
y=280
fi

# Clamp values
if (( y < MIN_TARGET_KBPS )); then
y=$MIN_TARGET_KBPS
elif (( y > MAX_TARGET_KBPS )); then
y=$MAX_TARGET_KBPS
fi

echo "$y"
}

# Analyze audio volume to determine normalization gain.
# Uses the global TARGET_VOL to calculate the necessary adjustment.
# Avoids awk; uses grep, sed, sort, and bc.
detect_loudness_gain() {
local input_file="$1"
local duration
duration=$(ffprobe -v quiet -show_entries format=duration -of csv=p=0 "$input_file" 2>/dev/null)

if [[ -z "$duration" ]]; then
echo "0.0"
return
fi

local raw=""
local len=60 # Sample 1 minute chunks

# Check if file is short (< 15 mins = 900 seconds)
if (( $(echo "$duration < 900" | bc -l 2>/dev/null || echo 0) )); then
echo " -> File is short (< 15m), analyzing full volume..." >&2
# Note: We must use || true on the pipeline because grep returns 1 if no match found,
# which would crash the script due to set -e / pipefail.
raw=$(ffmpeg -i "$input_file" -af "volumedetect" -map 0:a -f null /dev/null 2>&1 |& grep 'max_volume' || true)
else
echo " -> File is long, sampling volume at 5 points..." >&2

local sample_positions=(0 0.25 0.5 0.75)
local i=1
local pos t

for pos in "${sample_positions[@]}"; do
t=$(printf "%.3f" "$(echo "$duration * $pos" | bc -l)")
raw+=$(ffmpeg -ss "$t" -t "$len" -i "$input_file" -af "volumedetect" -map 0:a -f null /dev/null 2>&1 |& grep 'max_volume' || true)
raw+=$'\n'
printf " %d" $i >&2
((i++))
done

# Final sample at end
t=$(printf "%.3f" "$(echo "$duration - $len" | bc -l)")
if (( $(echo "$t < 0" | bc -l 2>/dev/null || echo 0) )); then
t=0
fi
raw+=$(ffmpeg -ss "$t" -t "$len" -i "$input_file" -af "volumedetect" -map 0:a -f null /dev/null 2>&1 |& grep 'max_volume' || true)
printf " %d\n" $i >&2
fi

if [[ -z "$raw" ]]; then
echo "0.0"
return
fi

# Find loudest section (max_volume closest to 0)
# 1. Extract number (e.g., -12.3)
# 2. Sort numerically (-20, -15, -5)
# 3. Tail gets -5 (loudest)
local max_db
max_db=$(echo "$raw" | sed -n 's/.*max_volume: \(-[0-9.]*\) dB.*/\1/p' | sort -n | tail -n 1)

if [[ -z "$max_db" ]] || ! [[ "$max_db" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
echo "0.0"
return
fi

# Calculate gain: Gain = Target - Current_Max
# Example: Current=-10dB, Target=-20dB -> Gain = -10dB (Reduction)
# Example: Current=-30dB, Target=-20dB -> Gain = +10dB (Amplification)
local gain
gain=$(bc -l <<< "${TARGET_VOL} - ${max_db}")

printf "%.2f" "$gain"
}

# Detect black bars via cropdetect
# Samples frames at intervals to find consistent crop area
detect_crop_filter() {
local file="$1"
local duration
duration=$(get_duration "$file") || return 1

local dur_sec=${duration%.*}
if (( dur_sec < 3 )); then
return
fi

local num_samples=8
local interval=$(( dur_sec / (num_samples + 1) ))
(( interval = interval > 0 ? interval : 1 ))

local min_x1=99999 min_y1=99999 max_x2=-1 max_y2=-1
local found_any=0

for ((i = 1; i <= num_samples; i++)); do
local ss=$(( i * interval ))
local crop_line

# cropdetect=limit=24: Only crop if black level is below 24.
crop_line=$(ffmpeg -nostdin -hide_banner -ss "$ss" -i "$file" -t 1 -vf "cropdetect=limit=24:round=2:reset=0" -f null - 2>&1 |
grep "crop=" | tail -n1) || continue

if [[ -n "$crop_line" ]]; then
# Extract params: "crop=1920:1080:0:0" -> "1920:1080:0:0"
local crop_params="${crop_line#*crop=}"
local w h x y

IFS=':' read -r w h x y <<< "$crop_params"
[[ "$w" =~ ^[0-9]+$ ]] && [[ "$h" =~ ^[0-9]+$ ]] && [[ "$x" =~ ^[0-9]+$ ]] && [[ "$y" =~ ^[0-9]+$ ]] || continue

local x1=$((x))
local y1=$((y))
local x2=$((x + w))
local y2=$((y + h))

# Accumulate min/max for bounding box
(( min_x1 = x1 < min_x1 ? x1 : min_x1 ))
(( min_y1 = y1 < min_y1 ? y1 : min_y1 ))
(( max_x2 = x2 > max_x2 ? x2 : max_x2 ))
(( max_y2 = y2 > max_y2 ? y2 : max_y2 ))
found_any=1
fi
done

if (( !found_any )); then return; fi

local final_w=$(( max_x2 - min_x1 ))
local final_h=$(( max_y2 - min_y1 ))

local orig_w orig_h
orig_w=$(ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=p=0 "$file")
orig_h=$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=p=0 "$file")

# Only apply crop if it actually reduces dimensions
if (( final_w < orig_w || final_h < orig_h )); then
echo "crop=${final_w}:${final_h}:${min_x1}:${min_y1}"
fi
}

# ========================================
# MAIN SCRIPT
# ========================================

# --- Argument Parsing ---
SCALE_FACTOR=""
input_file=""

if [[ $# -eq 2 ]]; then
SCALE_FACTOR="$1"
input_file="$2"
elif [[ $# -eq 1 ]]; then
input_file="$1"
else
echo "Usage: $0 [scale_factor] <video_file>" >&2
echo " scale_factor: Optional. Divides target bitrate by this number." >&2
echo " e.g. 2.0 creates a file 1/2 the original size." >&2
exit 1
fi

# --- Validation ---
[[ -f "$input_file" ]] || die "Input file not found: $input_file"
[[ -r "$input_file" ]] || die "Input file not readable: $input_file"

filename=$(basename "$input_file")
outfile="${filename%.*}.mkv"
outdir="out"
origdir="orig"

mkdir -p "$outdir" "$origdir"

echo "======================================="
echo "ANALYZING: $filename"
echo "======================================="

# STEP 1: Extract Input Video Bitrate
input_bitrate_bps=$(get_effective_video_bitrate_bps "$input_file")
input_bitrate_kbps=$(( input_bitrate_bps / 1000 ))
echo " -> Input video bitrate: ${input_bitrate_kbps} kbps"

# STEP 1.5: Skip Check
if (( input_bitrate_kbps < 256 )); then
echo " -> SKIP: Input bitrate (${input_bitrate_kbps} kbps) is below threshold (256 kbps)."
echo " -> File considered already compressed or low quality."
exit 0
fi

# STEP 2: Compute Target Bitrate
if [[ -n "$SCALE_FACTOR" ]]; then
# Manual Scaling Mode
# Validate scale_factor is a positive number
if ! [[ "$SCALE_FACTOR" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
die "Scale factor must be a positive number (e.g., 1, 1.5, 2)."
fi
target_bitrate_kbps=$(echo "scale=0; $input_bitrate_kbps / $SCALE_FACTOR" | bc)
echo " -> MANUAL MODE: Scaling bitrate by 1/${SCALE_FACTOR}."
else
# Auto Curve Mode
target_bitrate_kbps=$(calculate_target_bitrate_kbps "$input_bitrate_kbps")
echo " -> AUTO MODE: Logarithmic targeting."
fi

target_bitrate_bps=$(( target_bitrate_kbps * 1000 ))
echo " -> Target video bitrate: ${target_bitrate_kbps} kbps"

# STEP 3: Estimate Output Size
duration_sec=$(get_duration "$input_file") || die "Cannot determine duration"
total_bitrate_kbps=$(( target_bitrate_kbps + 12 )) # +12k audio (approx)

estimated_size_bytes=$(bc -l <<< "($total_bitrate_kbps * 1000 * $duration_sec) / 8" 2>/dev/null)
estimated_size_bytes=${estimated_size_bytes%.*} # truncate float

input_size_mb=$(bc -l <<< "$(stat -c%s "$input_file") / (1024*1024)" 2>/dev/null)
input_size_mb=${input_size_mb%.*}

estimated_size_mb=$(bc -l <<< "scale=1; $estimated_size_bytes / (1024*1024)" 2>/dev/null)
[[ -z "$estimated_size_mb" ]] && estimated_size_mb="0.0"

echo " -> Input file size: ${input_size_mb} MB"
echo " -> Estimated output size: ${estimated_size_mb} MB"

# STEP 4: Audio & Crop Analysis
volume_gain=$(detect_loudness_gain "$input_file")
echo " -> Audio gain for ${TARGET_VOL} dB target: ${volume_gain}dB"

crop_filter=""
if crop_result=$(detect_crop_filter "$input_file"); then
crop_filter="$crop_result"
fi

if [[ -n "$crop_filter" ]]; then
echo " -> Crop filter: $crop_filter"
else
echo " -> No significant black bars detected."
fi

# STEP 5: Build Filter Chain
if [[ -n "$crop_filter" ]]; then
video_filter="${crop_filter},${SCALE_FILTER},mpdecimate"
else
video_filter="$SCALE_FILTER"
fi
audio_filter="volume=${volume_gain}dB"
passlogfile="${outdir}/${filename%.*}.log"

echo "--------------------------------------------------"
echo "ENCODING PLAN:"
echo " Video filter: $video_filter"
echo " Audio filter: $audio_filter"
echo " Output: ${outdir}/${outfile}"
echo "--------------------------------------------------"

# Prompt user before proceeding (Destructive action)
#read -r -p "Proceed with encoding and archiving original? (y/N): " confirm
#if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
# echo "Aborted by user."
# exit 0
#fi

#-c:v "$VIDEO_CODEC" -b:v "${target_bitrate_bps}" \
# ----------------------------
# SINGLE-PASS HEVC ENCODING
# ----------------------------
echo "ENCODE: Creating final output..."
if ! ffmpeg -y -hide_banner -i "$input_file" \
-filter:v "$video_filter" \
-filter:a "$audio_filter" \
-preset "$ENCODING_PRESET" \
-fps_mode vfr \
-c:v "$VIDEO_CODEC" -crf "32" \
-g 600 -keyint_min 600 \
-x265-params "$ENCODING_PARAMS" \
-c:a libopus -b:a "$AUDIO_BITRATE" -application voip -frame_duration 20 -compression_level 10 \
-movflags +faststart -tune fastdecode -metadata handler_name="spumco" \
"${outdir}/${outfile}"; then
echo "FAILURE: Encoding failed!" >&2
exit 1
fi

# Cleanup logs
rm -f "${passlogfile}"*

# ----------------------------
# POST-PROCESSING
# ----------------------------
echo "======================================="
echo "SUCCESS: Output written to ${outdir}/${outfile}"
echo "Archiving original to ${origdir}/..."
mv "$input_file" "$origdir/"
printf '\a'; sleep 0.5; printf '\a'; sleep 0.5; printf '\a'
echo "Done."
exit 0

Comments (5)

Anonymous Mar 22, 2026 10:15 PM

Who's Daniel?

brothchild Mar 22, 2026 10:18 PM

this has been a work of putzing around since about 2015, revised many times. One other note is it's optimized for static scenes, things with slides, or static backgrounds.

brothchild Mar 22, 2026 10:18 PM

Daniel alliterates with derpy.

Anonymous Mar 22, 2026 10:50 PM

It's pretty impressive. For reference this was one of the results: https://x0.at/mHyU.mkv

It's only 11 MB.

Anonymous Mar 22, 2026 10:52 PM

Oh and I also love how you described it on IRC so I will copy/paste that description here.

<brothchild> so ya it's my 'archival' thing
<brothchild> just good enough quality, min size
<brothchild> other people want to archive 'good quality' fuck that.
<brothchild> i want videos we can email
<brothchild> videos we can morse code with a shard of glass
<brothchild> videos that fit in an image header :P

Add a Comment

← Back to Video Encoding and Archival