VP8M8

WebM Auto Audio Adjuster

Nov 23rd, 2016
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.91 KB | None | 0 0
  1. #!/bin/bash
  2. # v1.0.1 2016-11-25 VP8M8
  3. # Description: Increases/decreases the audio bitrate of WebMs in steps to satisfy the target file size
  4. # Note: All files are handled in MiB (based on 2^10, not 10^3) and the target file size must be in MiB
  5. # Depenencies: ffmpeg, ffprobe, bc, sed, grep, cut
  6. # Usage: script.sh ["source video" or "source audio"] ["webm video"] [webm audio bitrate] [target file size]
  7.  
  8. # Check for dependencies
  9. for depencency in ffmpeg ffprobe bc sed grep cut; do
  10.     if [[ $(command -v $depencency >/dev/null 2>&1) -ne 0 ]]; then
  11.         echo "This script requires \"$depencency\" but it's not installed."
  12.         echo "Install it."
  13.         exit 1
  14.     fi
  15. done
  16.  
  17. # Displays help if first argument is -h or --help
  18. if [[ "$1" = "-h" || "$1" = "--help" ]]; then
  19.     echo "Usage: "$0" [\"source video\" or \"source audio\"] [\"webm video\"] [webm audio bitrate] [target file size]"
  20.     echo "Example: "$0" \"original video.mkv\" \"encoded video.webm\" 64k 12M"
  21.     exit 0
  22. fi
  23.  
  24. source_video="$1"
  25. webm_video="$2"
  26. audio_bitrate="$3"
  27. target_filesize="$4"
  28.  
  29. # Set default values
  30. overshoot_percent=104
  31. undershoot_percent=92
  32. bitrate_step=4
  33.  
  34. # In case the user puts 'M' or 'MB' after the target file size it is discarded
  35. # I do the same thing later on for the audio bitrate in case there is a 'k' at the end
  36. target_filesize=$(echo "$target_filesize" | sed 's/M$//')
  37. target_filesize=$(echo "$target_filesize" | sed 's/MB$//')
  38. overshoot_filesize=$(echo "scale=3;$target_filesize*($overshoot_percent)/100" | bc)
  39. undershoot_filesize=$(echo "scale=3;$target_filesize*($undershoot_percent)/100" | bc)
  40. times_increased=0
  41. times_decreased=0
  42. webm_filesize_bytes=$(ffprobe "$webm_video" -loglevel quiet -show_format | grep size | cut -f2 -d=)
  43. webm_filesize=$(echo "scale=8;$webm_filesize_bytes/1024/1024" | bc)
  44. file_ratio=$(echo "scale=8;$webm_filesize/$target_filesize*100" | bc)
  45.  
  46. # If webm file size is equal to target file size
  47. if [[ $(echo "$file_ratio == 100" | bc) -eq 1 ]]; then
  48.     echo "The webm is exactly the target file size."
  49.     echo "There is no more work to be done."
  50.     exit 0
  51. fi
  52.  
  53. # If webm file size is over/under the overshoot/undershoot percent
  54. if [[ $(echo "$file_ratio > $overshoot_percent" | bc) -eq 1 || $(echo "$file_ratio < $undershoot_percent" | bc) -eq 1 ]]; then
  55.     echo "The webm file size is $(echo "$webm_filesize" | sed 's/.\{5\}$//')MB which is $(echo "$file_ratio" | sed 's/.\{5\}$//')% of the target size of "$target_filesize"MB."
  56.     echo "The webm should be within "$overshoot_percent"%-"$undershoot_percent"% of the target size."
  57.     echo "This means it should be within "$overshoot_filesize"MB-"$undershoot_filesize"MB to be used."
  58.     echo "Consider re-encoding with larger/smaller video bitrate for optimal quality."
  59.     exit 1
  60. fi
  61.  
  62. # Increases the audio bitrate until the webm is slightly over the target file size
  63. while [[ $(echo "$file_ratio < 100" | bc) -eq 1 && $(echo "$file_ratio >= $undershoot_percent" | bc) -eq 1 ]]; do
  64.     echo "The webm was too small so the audio bitrate is being increased..."
  65.     audio_bitrate_raw=$(echo "$audio_bitrate" | sed 's/k$//')
  66.     audio_bitrate_raw=$(echo "$audio_bitrate_raw+$bitrate_step" | bc)
  67.     audio_bitrate=$(echo "$audio_bitrate_raw" | sed 's/$/k/')
  68.     ((times_increased++))
  69.     ffmpeg -i "$source_video" -i "$webm_video" -map 1:v:0 -map 0:a:0 -loglevel quiet -c:v copy -c:a libopus -b:a "$audio_bitrate" "$webm_video"-increased#"$times_increased".webm
  70.     rm "$webm_video"
  71.     mv "$webm_video"-increased#"$times_increased".webm "$webm_video"
  72.     echo "Checking if more passes are needed..."
  73.     webm_filesize_bytes=$(ffprobe "$webm_video" -loglevel quiet -show_format | grep size | cut -f2 -d=)
  74.     webm_filesize=$(echo "scale=8;$webm_filesize_bytes/1024/1024" | bc)
  75.     file_ratio=$(echo "scale=8;$webm_filesize/$target_filesize*100" | bc)
  76. done
  77.  
  78. # Very rare case that the file size is initially increased above the overshoot percent threshold
  79. if [[ $(echo "$file_ratio >= $overshoot_percent" | bc) -eq 1 ]]; then
  80.     echo "*** Warning! The webm is over the overshoot percent threshold! ***"
  81.     echo "Reverting all changes..."
  82.     overshoot_percent=1000
  83. fi
  84.  
  85. # Decreases the audio bitrate until the webm is slightly under the target file size
  86. while [[ $(echo "$file_ratio > 100" | bc) -eq 1 && $(echo "$file_ratio <= $overshoot_percent" | bc) -eq 1 ]]; do
  87.     echo "The webm was too big so the audio bitrate is being decreased..."
  88.     audio_bitrate_raw=$(echo "$audio_bitrate" | sed 's/k$//')
  89.     audio_bitrate_raw=$(echo "$audio_bitrate_raw-$bitrate_step" | bc)
  90.     audio_bitrate=$(echo "$audio_bitrate_raw" | sed 's/$/k/')
  91.     ((times_decreased++))
  92.     ffmpeg -i "$source_video" -i "$webm_video" -map 1:v:0 -map 0:a:0 -loglevel quiet -c:v copy -c:a libopus -b:a "$audio_bitrate" "$webm_video"-decreased#"$times_decreased".webm
  93.     rm "$webm_video"
  94.     mv "$webm_video"-decreased#"$times_decreased".webm "$webm_video"
  95.     if [[ $overshoot_percent = "1000" ]]; then
  96.         echo "Try again with a lower bitrate step."
  97.         exit 1
  98.     fi
  99.     echo "Checking if more passes are needed..."
  100.     webm_filesize_bytes=$(ffprobe "$webm_video" -loglevel quiet -show_format | grep size | cut -f2 -d=)
  101.     webm_filesize=$(echo "scale=8;$webm_filesize_bytes/1024/1024" | bc)
  102.     file_ratio=$(echo "scale=8;$webm_filesize/$target_filesize*100" | bc)
  103. done
  104.  
  105. webm_filesize=$(echo "$webm_filesize" | sed 's/.\{5\}$//')
  106. file_ratio=$(echo "scale=3;$webm_filesize/$target_filesize*100" | bc)
  107. audio_bitrate_raw=$(echo "$audio_bitrate" | sed 's/k$//')
  108. original_bitrate_raw=$(echo "$3" | sed 's/k$//')
  109.  
  110. echo "Finished! The webm should now be very close to the target file size."
  111. echo "[============ Stats ============]"
  112. echo "The webm file size is "$webm_filesize"MB which is "$file_ratio"% of the target size of "$target_filesize"MB."
  113. echo "The audio bitrate was increased "$times_increased" times and decreased "$times_decreased" times."
  114. echo "The initial audio bitrate was "$3" and the final bitrate is "$audio_bitrate","
  115. echo "which is a difference of $(echo "scale=3;$audio_bitrate_raw-$original_bitrate_raw" | bc)k."
  116. exit 0
Advertisement
Add Comment
Please, Sign In to add comment