Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
#!/usr/bin/env bash DEBUG=0 # set to 1 for dry running with stdout verbosity # will still populate INTERFOLDER ### README ## DEPENDENCIES # ffmpeg # libheif-examples # renrot # INSTALL VIA apt install ffmpeg libheif-examples renrot -y ################################################################# ### START OF CONFIG ############################################# ### CONFIG OF FOLDERS # tmp folder INTERFOLDER="~/.mediatmp" # drop folder, if not specified FULL PATH in SECOND parameter DROPFOLDER="~/Videos/transcode/in" # out folder, can be specified FULL PATH by FIRST parameter OUTFOLDER="~/Videos/transcode/out" ### CONFIG OF FFMPEG (OBLIGATORY) ## VIDEOS # minimum byte-size (not kB/MB/GB!) of file to process (smaller will be skipped) SMALLVID=0 # api for scaling. "scale" if on CPU, "scale_vaapi" if on GPU via VAAPI, check documentation for other apis scaling hook VIDSCALEAPI="scale_vaapi" # video target bitrate. you can use e.g. "512k" or "4M" VIDEOBITS="4M" # target size in pixels on LONGER side VIDEOSIZE=1920 # main function to tune VIDFFMPEG() { ffmpeg -hide_banner \ -hwaccel vaapi -hwaccel_output_format vaapi \ -i "$v" $VF \ -c:v hevc_vaapi \ -extbrc 1 -look_ahead_depth 40 \ -b:v "$VIDEOBITS" \ -c:a copy \ "$OUTFOLDER/$VIDNEWNAME.mp4" } ## IMAGES # api for scaling. "scale" if on CPU, "scale_vaapi" if on GPU via VAAPI, check documentation for other apis scaling hook PICSCALEAPI="scale" # quality factor - lower is better (i.e. bigger byte-size) IMAGECRF=22 # target size in pixels on SHORTER side IMAGESIZE=2000 # main function to tune PICFFMPEG() { ffmpeg -hide_banner -i "$i" $VF \ -c:v libaom-av1 -crf "$IMAGECRF" \ -cpu-used 0 "$OUTFOLDER/${i%.*}.avif" } ##### OPTIONAL config below ##################################### ### FILETYPE ARRAYS ## generally no need to change that. # "good" are usually well-compressed to begin with and will be COPIED goodVariant=( "avif" "AVIF" "webp" "WEBP" ) # ffmpeg chokes on HEIF, thus conversion out of that format heifVariant=( "heic" "heif" "HEIC" "HEIF" ) # jpegs, due to poor renrot compatibility jpegVariant=( "jpeg" "jpg" "JPEG" "JPG" ) # the rest, compatible with ffmpeg otherVariant=( "jxl" "JXL" "tif" "tiff" "TIF" "TIFF" "png" "PNG" "bmp" "BMP" ) # videos vidVariant=( "mov" "MOV" "mp4" "MP4" "mkv" "MKV" ) ### END OF CONFIG ############################################### ################################################################# # PREP if [[ ! -d "$INTERFOLDER" ]]; then mkdir -p "$INTERFOLDER" ; fi if [[ ! -z $1 ]]; then OUTFOLDER="$1" ; fi if [[ ! -z $2 ]]; then DROPFOLDER="$2" ; fi if [[ `ls "$DROPFOLDER" | wc -c` -eq 0 ]]; then echo "Drop folder empty or absent. (Be sure to use FULL PATHs, or tilde expansion.)" exit fi shopt -s extglob # DEFINE FUNCTIONS function IMAGETRANSCODE { VIDDATA=`ffprobe "$i" 2>&1 | grep Video:` if [[ $VIDDATA =~ ([0-9]{3,4})x([0-9]{3,4}) ]]; then width="${BASH_REMATCH[1]}" height="${BASH_REMATCH[2]}" # SET UP SIZING #check if vertical if [[ $width -le $IMAGESIZE ]] && [[ $height -le $IMAGESIZE ]]; then test $DEBUG = 1 && echo "# resizing $i not necessary" VF="" else if [[ $height -gt $width ]]; then # vertical aspect VF="-vf $PICSCALEAPI=$IMAGESIZE:-2" else # horizontal aspect VF="-vf $PICSCALEAPI=-2:$IMAGESIZE" fi fi if [[ $DEBUG = 1 ]]; then echo "FFMPEG $i with res '$VF'" else PICFFMPEG || echo "$i crashed ffmpeg!" >> "$DROPFOLDER/.errors.log" fi else # error logging if [[ ${i:0:1} -ne "*" ]]; then if [[ $DEBUG = 1 ]]; then echo "# resolution of $i failed to be established" else echo "$i couldn't be processed." >> "$DROPFOLDER/.errors.log" fi fi fi } function VIDEOTRANSCODE { VIDDATA=`ffprobe "$v" 2>&1 | grep Video:` # Read MOV metadata from iPhones if [[ ${v:0:4} -eq "IMG_" ]]; then test $DEBUG = 1 && echo "# renaming $v" VIDSTAMP=`ffprobe "$v" 2>&1 | grep com.apple.quicktime.creationdate | cut -c39-` if [[ -z $VIDSTAMP ]]; then test $DEBUG = 1 && echo "# unable to find creationdate" VIDNEWNAME="${v%.*}" else VIDNEWNAME="${VIDSTAMP:0:4}${VIDSTAMP:5:2}${VIDSTAMP:8:2}_${VIDSTAMP:11:2}${VIDSTAMP:14:2}${VIDSTAMP:17:2}" echo "Renaming $v to $VIDNEWNAME.mp4." fi else VIDNEWNAME="${v%.*}" fi # determine scale if [[ $VIDDATA =~ ([0-9]{3,4})x([0-9]{3,4}) ]]; then width="${BASH_REMATCH[1]}" height="${BASH_REMATCH[2]}" if [[ $width -le $VIDEOSIZE ]] && [[ $height -le $VIDEOSIZE ]]; then test $DEBUG = 1 && echo "# resizing $v not necessary" VF="" else if [[ $height -gt $width ]]; then # vertical aspect VF="-vf $VIDSCALEAPI=-2:$VIDEOSIZE" else # horizontal aspect VF="-vf $VIDSCALEAPI=$VIDEOSIZE:-2" fi fi if [[ $DEBUG = 1 ]]; then echo "FFMPEG $v with res '$VF' and new name $VIDNEWNAME" else VIDFFMPEG || echo "$v crashed ffmpeg!" >> "$DROPFOLDER/.errors.log" fi else # error logging if [[ ${v:0:1} -ne "*" ]]; then if [[ $DEBUG = 1 ]]; then echo "# resolution of $v failed to be established" else echo "$v couldn't be processed." >> "$DROPFOLDER/.errors.log" fi fi fi } cd "$DROPFOLDER" ### START ACTUAL WORK ## copy good images without processing test $DEBUG = 1 && echo "### START ###" for img in "${goodVariant[@]}" ; do test $DEBUG = 1 && echo "# copying $img files" cp *.$img "$OUTFOLDER/" done ## HEVC imgs convert for heimg in "${heifVariant[@]}"; do for h in *.$heimg ; do test $DEBUG = 1 && echo "# converting HEIC $h" heif-convert -q 100 "$h" "$INTERFOLDER/$h.jpg" done done ## copy images to actually transcode for jpimg in "${jpegVariant[@]}" "${otherVariant[@]}" ; do cp *.$jpimg "$INTERFOLDER/" done cd "$INTERFOLDER" ### WORK ON PICTURES ## rename files for n in !([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]*) ; do # jpegs via renrot if [[ ${jpegVariant[@]} =~ ${n##*.} ]]; then test $DEBUG = 1 && echo "# attempting renrot of $n" renrot -n %Y%m%d_%H%M%S "$n" fi # TODO: some universal FFPROBE®EX method of doing that not just for JPEGs done ## transcode all for i in * ; do test $DEBUG = 1 && echo "# function image transcode $i" IMAGETRANSCODE done ## cleanup rm "$INTERFOLDER/"* cd "$DROPFOLDER" ## VIDEOS for vid in "${vidVariant[@]}" ; do for v in *.$vid ; do # if small file then not worth it SIZE=`stat "$v" | grep Size: | cut -c9-19` if [[ $SIZE -le $SMALLVID ]]; then if [[ $DEBUG -eq 1 ]]; then echo "# just moving $v (small size)" else cp "$v" "$OUTFOLDER/" fi else test $DEBUG = 1 && echo "# function video transcode $v" VIDEOTRANSCODE fi done done echo "### FINISHED ###"
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)