Skip to content

Instantly share code, notes, and snippets.

@mattst
Created November 9, 2018 17:18
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mattst/9ffee93f5053ba59275af800f0dbd654 to your computer and use it in GitHub Desktop.
Save mattst/9ffee93f5053ba59275af800f0dbd654 to your computer and use it in GitHub Desktop.
Script to test encode speeds and file sizes for libx264 encodes with a range of CRF values and presets
#!/bin/bash
infile="TestClipTwoMin.mp4"
datafile="TestClipTwoMinData.csv"
crfs=("18" "19" "20" "21" "22" "23" "24" "25" "26" "27")
presets=("ultrafast" "superfast" "veryfast" "faster" "fast" "medium" "slow" "slower" "veryslow")
echo 'CRF,Preset,Time (Secs),Size (MB)' >> "$datafile"
for crf in "${crfs[@]}"; do
for preset in "${presets[@]}"; do
outfile=Out_CRF_"$crf"_Preset_"$preset".mp4
time_start=$(date +%s.%N)
ffmpeg -i "$infile" -c:a copy -c:v libx264 -crf "$crf" -preset "$preset" "$outfile"
time_end=$(date +%s.%N)
# Dividing by 1 forces the scale to be used.
time=$(echo "scale = 2; ($time_end - $time_start)/1" | bc)
size_bytes=$(ls -l "$outfile" | awk '{ print $5 }')
size_mb=$(echo "scale = 2; $size_bytes / 1000000" | bc)
echo $crf,$preset,$time,$size_mb >> "$datafile"
done
done
@mattlowe67
Copy link

mattlowe67 commented Feb 6, 2019

This is incredibly helpful! I gave it a shot, but it doesn't seem to be writing the time of encoding to the CSV file. Just leaves it blank. I tried with a 1 minute clip and a 2 minute clip

Edit 1: Forgot to add i'm on MacOS Mojave

Edit 2: Made some tweaks and got Second's to appear, albeit with a little less granularity

`#!/usr/local/bin/bash

infile="test3.mov"

datafile="TestClipTwoMinData.csv"

crfs=("18" "19" "20" "21" "22" "23" "24" "25" "26" "27")

presets=("ultrafast" "superfast" "veryfast" "faster" "fast" "medium" "slow" "slower" "veryslow")

echo 'CRF,Preset,Time (Secs),Size (MB)' >> "$datafile"

for crf in "${crfs[@]}"; do

for preset in "${presets[@]}"; do

    outfile=Out_CRF_"$crf"_Preset_"$preset".mp4

    time_start=$(date +%s)

    ffmpeg -i "$infile" -c:a aac -c:v libx264 -crf "$crf" -preset "$preset" -pix_fmt yuv420p "$outfile"

    time_end=$(date +%s)

    # Dividing by 1 forces the scale to be used.

time=$(((time_end-time_start) ))


    size_bytes=$(ls -l "$outfile" | awk '{ print $5 }')

    size_mb=$(echo "scale = 2; $size_bytes / 1000000" | bc)

    echo $crf,$preset,$time,$size_mb >> "$datafile"

done

done
`

@mattlowe67
Copy link

Last but not least, I think it was an issue with date in BASH on MacOS. So I wrote a work around that doesn't use date. I also added Bit Rate calculation based on putting the length in seconds of the input file at the top of the script. Pretty hackey but...

`#!/usr/local/bin/bash

infile="15s.mov"

datafile="TestClipTwoMinData.csv"

declare -i cliplength=15

crfs=("18" "19" "20" "21" "22" "23" "24" "25" "26" "27")

presets=("ultrafast" "superfast" "veryfast" "faster" "fast" "medium" "slow" "slower" "veryslow")

echo 'CRF,Preset,Time (Secs),Size (MB), Bitrate (KBps)' >> "$datafile"

for crf in "${crfs[@]}"; do

for preset in "${presets[@]}"; do

    outfile=Out_CRF_"$crf"_Preset_"$preset".mp4

SECONDS=0

    ffmpeg -i "$infile" -c:a aac -c:v libx264 -crf "$crf" -preset "$preset" -pix_fmt yuv420p "$outfile"


time=$SECONDS


    size_bytes=$(ls -l "$outfile" | awk '{ print $5 }')

    size_mb=$(echo "scale = 2; $size_bytes / 1000000" | bc)

bitrate=$(echo "scale = 2; ($size_bytes / $cliplength) / 1000"  | bc)

    echo $crf,$preset,$time,$size_mb,$bitrate >> "$datafile"

done

done
`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment