generated from me/template-mit
pv-test, fix pv and pv2 outfile location if path in filename, test defaults for each option by keeping the skip, fix some spacing issues.
1161 lines
28 KiB
Bash
1161 lines
28 KiB
Bash
# Notes:
|
|
# - Please keep this file working for both BASH and ZSH. :)
|
|
|
|
## Variables ##
|
|
|
|
# Environment Usability #
|
|
|
|
export PATH="$PATH:~/bin-shared:~/.bin-shared"
|
|
|
|
# PS1 Colors #
|
|
|
|
colors=`tput colors`
|
|
if (( colors >= 256 )); then
|
|
export PURPLE="`tput setaf 55`"
|
|
export ORANGE="`tput setaf 208`"
|
|
export GREEN="`tput setaf 34`"
|
|
|
|
export RED="`tput setaf 196`"
|
|
export SCARLET="`tput setaf 160`"
|
|
export YELLOW="`tput setaf 226`"
|
|
|
|
export GRAY="`tput setaf 243`"
|
|
elif (( colors == 16 )); then
|
|
export PURPLE="`tput setaf 13`"
|
|
export ORANGE="`tput setaf 11`"
|
|
export GREEN="`tput setaf 02`"
|
|
|
|
export RED="`tput setaf 09`"
|
|
export SCARLET="`tput setaf 01`"
|
|
export YELLOW="`tput setaf 11`"
|
|
|
|
export GRAY="`tput setaf 08`"
|
|
else
|
|
export PURPLE="`tput setaf 05`"
|
|
export ORANGE="`tput setaf 03`"
|
|
export GREEN="`tput setaf 02`"
|
|
|
|
export RED="`tput setaf 05`"
|
|
export SCARLET="`tput setaf 01`"
|
|
export YELLOW="`tput setaf 03`"
|
|
|
|
export GRAY="`tput setaf 07`"
|
|
fi
|
|
|
|
|
|
export RESET="`tput sgr0`"
|
|
export BOLD="`tput bold`"
|
|
|
|
|
|
## Aliases ##
|
|
|
|
# Quickies #
|
|
|
|
alias reload-bash="source ~/.bashrc"
|
|
alias bash-reload="reload-bash"
|
|
alias shell-reload="reload-bash"
|
|
alias reload-shell="reload-bash"
|
|
alias reload="reload-bash"
|
|
|
|
alias l='ls '
|
|
alias ll='ls -alh '
|
|
alias lh='ls -ash '
|
|
|
|
function clones {
|
|
export CLONES_PATH="$HOME/Clones"
|
|
if [[ -d /sdcard ]]; then
|
|
export CLONES_PATH="/sdcard/Library/Clones"
|
|
fi
|
|
mkdir -pv "$CLONES_PATH"
|
|
cd "$CLONES_PATH"
|
|
}
|
|
alias cl="clones"
|
|
alias cdl="cl"
|
|
alias cdc="cl"
|
|
|
|
alias library="clones && cd .."
|
|
alias lib="library"
|
|
|
|
# Networking #
|
|
|
|
alias scan="nmap -A -p- --script=vuln "
|
|
|
|
# Trash Related #
|
|
|
|
export TRASH_ROOT="/"
|
|
if [[ -d "/sdcard" ]]; then
|
|
# Android / Termux
|
|
export TRASH_ROOT="/sdcard"
|
|
else
|
|
# Desktop
|
|
export TRASH_ROOT="$HOME"
|
|
fi
|
|
export TRASH="$TRASH_ROOT/TRASH"
|
|
|
|
alias trash="cd $TRASH"
|
|
|
|
alias clean-trash="bash -c 'rm -rfv "$TRASH"/*'; clean-trashed"
|
|
alias trash-clean="clean-trash"
|
|
|
|
alias check-trash='du -h $TRASH | sort -h; find "$TRASH_ROOT" -name .Trash"*" -exec du -h {} \; -exec mv -v {} "$TRASH"/ \;'
|
|
alias trash-check="check-trash"
|
|
|
|
alias check-trashed='find "$TRASH_ROOT" -name ".trashed*" -exec du -h {} \; -exec mv -v {} "$TRASH"/ \; | sort -h'
|
|
alias clean-trashed='find "$TRASH_ROOT" -name ".trashed*" -exec du -h {} \; -delete | sort -h'
|
|
|
|
|
|
## Functions ##
|
|
|
|
# Related specifically to this project. #
|
|
|
|
branch="$BRANCH"
|
|
if [[ -z "$branch" ]]; then
|
|
branch="$PROD_GIT_BRANCH"
|
|
fi
|
|
if [[ -z "$branch" ]]; then
|
|
branch="dev"
|
|
fi
|
|
|
|
function update-shared-old {
|
|
log "`date` - Reloading the '~/.rc_shared' file from env-shared.\n"
|
|
|
|
if [[ -n "$1" ]]; then
|
|
branch="$1"
|
|
fi
|
|
|
|
dir="shared-rc-deleteme"
|
|
|
|
git clone https://git.hyperling.com/me/env-shared \
|
|
$dir --branch=$branch
|
|
|
|
mv -v $dir/rc_shared.sh ~/.rc_shared
|
|
|
|
local_bin="$HOME/bin"
|
|
remote_bin="shared-rc-deleteme/bin-shared"
|
|
if [[ -d "$local_bin" ]]; then
|
|
log "\n`date` - Found '$local_bin', adding scripts.\n"
|
|
mv -v $remote_bin/*.sh "$local_bin"/
|
|
|
|
refactor_script="refactor_music_library.sh"
|
|
wget -O "$refactor_script" \
|
|
https://git.hyperling.com/me/shell-music-refactor-library/raw/branch/main/refactor_music_library.sh
|
|
mv -v $refactor_script "$local_bin"/
|
|
|
|
chmod 755 -Rc "$local_bin"
|
|
else
|
|
echo "Did not find '$local_bin', did not copy scripts."
|
|
fi
|
|
|
|
log "\n`date` - Done! Removing git clone.\n"
|
|
mv -v $dir ~/TRASH/"$dir-`date "+%Y%m%d-%H%M%S"`"
|
|
|
|
log "\n`date` - Complete!"
|
|
}
|
|
|
|
export PROJECT_SHARED="$HOME/.git-env-shared"
|
|
function update-shared2 {
|
|
# Refresh the local env-shared repo.
|
|
if [[ -d $PROJECT_SHARED ]]; then
|
|
log "`date` - Updating '$PROJECT_SHARED'.\n"
|
|
git -C "$PROJECT_SHARED" switch "$branch"
|
|
git -C "$PROJECT_SHARED" pull --recurse-submodules || \
|
|
( echo "Failed to pull project, exiting." && return 1 )
|
|
else
|
|
log "`date` - Downloading '$PROJECT_SHARED'.\n"
|
|
git clone https://git.hyperling.com/me/env-shared \
|
|
"$PROJECT_SHARED" --branch=$branch
|
|
fi
|
|
|
|
# Tha main piece! Reload the shared RC file.
|
|
cp -v "$PROJECT_SHARED"/rc_shared.sh ~/.rc_shared
|
|
cp -v "$PROJECT_SHARED"/vimrc.vim ~/.vimrc
|
|
|
|
# Copy the scripts from the shared bin to the home bin.
|
|
local_bin="$HOME/bin"
|
|
remote_bin="$PROJECT_SHARED/bin-shared"
|
|
if [[ -d "$local_bin" ]]; then
|
|
log "\n`date` - Found '$local_bin', adding scripts.\n"
|
|
cp -v "$remote_bin"/*.sh "$local_bin"/
|
|
|
|
refactor_script="refactor_music_library.sh"
|
|
wget -O "$refactor_script" \
|
|
https://git.hyperling.com/me/shell-music-refactor-library/raw/branch/main/refactor_music_library.sh
|
|
mv -v $refactor_script "$local_bin"/
|
|
|
|
chmod 755 -Rc "$local_bin"
|
|
else
|
|
echo "Did not find '$local_bin', did not copy scripts."
|
|
fi
|
|
|
|
log "\n`date` - Complete!"
|
|
}
|
|
alias shared-update2="update-shared2"
|
|
alias reload-shared2="update-shared2"
|
|
alias shared-reload2="update-shared2"
|
|
|
|
alias update-shared="update-shared2"
|
|
alias shared-update="update-shared"
|
|
alias reload-shared="update-shared"
|
|
alias shared-reload="update-shared"
|
|
|
|
function reload-all {
|
|
log "`date` - Reloading BASH"
|
|
reload-bash
|
|
|
|
log "\n`date` - Reloading Main (Termux/Ansible)"
|
|
if [[ -d /sdcard ]]; then
|
|
reload-termux
|
|
else
|
|
scm.sh
|
|
fi
|
|
reload-bash
|
|
|
|
log "\n`date` - Reloading Shared"
|
|
reload-shared
|
|
reload-bash
|
|
}
|
|
alias all-reload="reload-all"
|
|
|
|
function update-all {
|
|
log "`date` - Updating env projects..."
|
|
reload-all
|
|
|
|
log "\n\n\n`date` - Running system updates..."
|
|
update -y
|
|
|
|
if [[ $(type -t update-sdk 2>/dev/null 1>&2) ]]; then
|
|
log "\n\n\n`date` - Updating SDKs..."
|
|
update-sdk
|
|
fi
|
|
|
|
log "\n\n\n`date` - Done with update-all!"
|
|
}
|
|
alias all-update="update-all"
|
|
|
|
PROJECT_SHARED_OLD01="$HOME/.env-shared"
|
|
if [[ -d "$PROJECT_SHARED_OLD01" ]]; then
|
|
log "`date` - Removing old project name '$PROJECT_SHARED_OLD01'."
|
|
mv -v "$PROJECT_SHARED_OLD01" "$TRASH"/env-shared-deleteme | grep -v ".git"
|
|
fi
|
|
|
|
# Shortcuts #
|
|
|
|
function send-master { send_master.sh; }
|
|
alias push-master="send-master"
|
|
alias sync-master="send-master"
|
|
|
|
function pull-clone { pull_clone.sh; }
|
|
alias get-clone="pull-clone"
|
|
alias sync-clone="pull-clone"
|
|
|
|
alias send-sync="send-master"
|
|
alias push-sync="send-master"
|
|
alias pull-sync="pull-clone"
|
|
alias get-sync="pull-clone"
|
|
function sync-sync {
|
|
cat <<- EOF
|
|
Command not implemented, too dangerous guessing the state of the folder.
|
|
|
|
Please use push-sync and pull-sync in the correct order for its current state.
|
|
EOF
|
|
}
|
|
|
|
function goodbye { update -y; bye; }
|
|
|
|
function clone {
|
|
rsync -auPhz --delete --exclude '.gradle' --exclude 'app/build' "$@"
|
|
}
|
|
|
|
function now { date "+%Y%m%d-%H%M%S"; }
|
|
function today { date "+%Y%m%d"; }
|
|
|
|
function log { echo -e "$1"; }
|
|
function blog { echo -e "\n\n$1\n\n"; }
|
|
|
|
function pull {
|
|
if [[ -d .git ]]; then
|
|
echo "Recognized git project, pulling latest changes."
|
|
git pull --recurse-submodules
|
|
else
|
|
echo "Not a git repo, attempting to sync with SFTP server."
|
|
pull-clone
|
|
fi
|
|
}
|
|
|
|
function push {
|
|
if [[ -d .git ]]; then
|
|
echo "Recognized git project, promoting branch to stage and prod."
|
|
git push && eval load-stage && eval load-prod
|
|
else
|
|
echo "Not a git repo, attempting to sync with SFTP server."
|
|
send-master
|
|
fi
|
|
}
|
|
|
|
function set-variable {
|
|
var="$1"
|
|
val="$2"
|
|
echo -n "export $var=\"$val\" - "
|
|
|
|
export $var="$val"
|
|
status="$?"
|
|
|
|
if [[ "$val" == "${!var}" ]]; then
|
|
echo "Success!"
|
|
return 0
|
|
fi
|
|
|
|
echo "Failed with status '$status', $var is '${!var}'."
|
|
return $status
|
|
}
|
|
alias set-var="set-variable "
|
|
|
|
# Enhance Bin Scripts #
|
|
|
|
# MASTER and CLONE folders.
|
|
|
|
function send-masters {
|
|
echo -e "`date` - Looping through MASTER directories."
|
|
ls | grep "\-MASTER" | while read dir; do
|
|
echo -e "\n`date` - Found '$dir'..."
|
|
cd $dir
|
|
send-master
|
|
cd ..
|
|
done
|
|
echo -e "\n`date` - Done checking for MASTER directories."
|
|
}
|
|
alias push-masters="send-masters"
|
|
alias sync-masters="send-masters"
|
|
|
|
function pull-clones {
|
|
echo -e "`date` - Looping through clone directories."
|
|
ls | grep "\-clone" | while read dir; do
|
|
echo -e "\n`date` - Found '$dir'..."
|
|
cd $dir
|
|
pull-clone
|
|
cd ..
|
|
done
|
|
echo -e "\n`date` - Done checking for clone directories."
|
|
}
|
|
alias get-clones="pull-clones"
|
|
alias sync-clones="pull-clones"
|
|
|
|
function sync-all {
|
|
push-masters
|
|
echo -e "\n"
|
|
pull-clones
|
|
|
|
echo -e "\n`date` - Skipping SYNC folders! Please do their loads separately."
|
|
ls | grep "\-SYNC" | while read dir; do
|
|
echo "- $dir"
|
|
done
|
|
|
|
echo -e "`date` - Done.\n"
|
|
}
|
|
function sync-all-loop {
|
|
typeset -i sleep_time count
|
|
if [[ "$1" ]]; then
|
|
sleep_time="$1"
|
|
fi
|
|
if [[ -z "$sleep_time" || "$sleep_time" == 0 ]]; then
|
|
sleep_time="300"
|
|
fi
|
|
log "`date` - Sleep timer set for '$sleep_time' seconds."
|
|
count=0
|
|
while true; do
|
|
sync-all
|
|
count=$(( count + 1 ))
|
|
echo -e "\n\n*** Sleeping for '$sleep_time' after run# '$count'! ***\n\n"
|
|
sleep $sleep_time
|
|
done
|
|
}
|
|
|
|
# SYNC folders.
|
|
|
|
function send-syncs {
|
|
echo -e "`date` - Looping through SYNC directories."
|
|
ls | grep "\-SYNC" | while read dir; do
|
|
echo -e "\n`date` - Found '$dir'..."
|
|
cd $dir
|
|
send-master
|
|
cd ..
|
|
done
|
|
echo -e "\n`date` - Done checking for SYNC directories."
|
|
}
|
|
alias push-syncs="send-syncs"
|
|
|
|
function pull-syncs {
|
|
echo -e "`date` - Looping through SYNC directories."
|
|
ls | grep "\-SYNC" | while read dir; do
|
|
echo -e "\n`date` - Found '$dir'..."
|
|
cd $dir
|
|
pull-clone
|
|
cd ..
|
|
done
|
|
echo -e "\n`date` - Done checking for SYNC directories."
|
|
}
|
|
alias get-syncs="pull-syncs"
|
|
|
|
function sync-syncs {
|
|
cat <<- EOF
|
|
Command not implemented, too dangerous guessing the state of the folder.
|
|
|
|
Please use push-syncs and pull-syncs in the correct order for its current state.
|
|
EOF
|
|
}
|
|
|
|
# Audio #
|
|
|
|
# Video #
|
|
|
|
# Optimize the bitrate and audio levels for an edited video.
|
|
function process-video-usage {
|
|
echo "USAGE: process-video oldFile newFile [videoBitrate] [audioBitrate] [sizeRating] [numPasses] [forceBitrate]"
|
|
echo -n "Purpose: Call ffmpeg with preferred video posting settings. "
|
|
echo -n "Bitrates default to 2000k and 192k, size is 720, passes is 1, and force is N."
|
|
echo "These work well on Odysee and are fairly small as backups."
|
|
echo "Examples:"
|
|
echo "- Create a small file for quick streaming."
|
|
echo " process-video youcut.mp4 20240210.mp4 1200k 128k 480"
|
|
echo "- Create a larger file for something like YouTube."
|
|
echo " process-video youcut.mp4 20240210_1080p.mp4 5000k 256k 1080"
|
|
}
|
|
function process-video {
|
|
# Parameters
|
|
file="$1"
|
|
newfile="$2"
|
|
video="$3"
|
|
audio="$4"
|
|
size="$5"
|
|
passes="$6"
|
|
force="$7"
|
|
|
|
# Validations
|
|
if [[ -z $file || ! -e $file ]]; then
|
|
echo "ERROR: Original file '$file' does not exist." >&2
|
|
process-video-usage
|
|
return 1
|
|
fi
|
|
|
|
if [[ -z $newfile ]]; then
|
|
echo "ERROR: New file's name must be provided." >&2
|
|
process-video-usage
|
|
return 1
|
|
elif [[ -e $newfile ]]; then
|
|
echo "ERROR: New file '$newfile' already exists." >&2
|
|
du -h "$newfile"
|
|
process-video-usage
|
|
return 1
|
|
fi
|
|
|
|
echo "`date` - Converting '$file' to '$newfile'."
|
|
|
|
if [[ -z $video ]]; then
|
|
video="2000k"
|
|
fi
|
|
if [[ $force == "Y" ]]; then
|
|
video="-b:v $video"
|
|
else
|
|
video="-b:v $video -minrate 0 -maxrate $video -bufsize $video"
|
|
fi
|
|
|
|
if [[ -z $audio ]]; then
|
|
audio="192k"
|
|
fi
|
|
audio="-b:a $audio"
|
|
|
|
if [[ -z $size ]]; then
|
|
size="720"
|
|
fi
|
|
# Lanczos is good for upscaling, but this is usually used for downscaling.
|
|
if [[ ! -z "$PV_VERTICAL_ASPECT_RATIO" ]]; then
|
|
size="-filter:v scale=$size:-1" #:flags=lanczos"
|
|
else
|
|
size="-filter:v scale=-1:$size" #:flags=lanczos"
|
|
fi
|
|
|
|
if [[ -z $passes ]]; then
|
|
passes=1
|
|
fi
|
|
pass=""
|
|
if [[ $passes != 1 || ! -z "$PV_2PASS" ]]; then
|
|
passes=2
|
|
pass="-pass 2"
|
|
fi
|
|
|
|
v2=""
|
|
if [[ ! -z "$PV_V2" ]]; then
|
|
v2="-crf 18 -preset veryslow -c:a aac -ar 48000"
|
|
#-profile:v high - Letting ffmpeg use the default profile.
|
|
fi
|
|
|
|
time=""
|
|
if [[ ! -z "$PV_TIME" ]]; then
|
|
time="`which time`"
|
|
fi
|
|
|
|
quiet="-hide_banner -loglevel level+warning"
|
|
if [[ ! -z "$PV_PROGRESS" ]]; then
|
|
quiet="-hide_banner -loglevel level+info"
|
|
fi
|
|
if [[ ! -z "$PV_VERBOSE" ]]; then
|
|
quiet="-loglevel level+verbose"
|
|
fi
|
|
|
|
## Main ##
|
|
# More information on two-pass processing with ffmpeg
|
|
# https://cinelerra-gg.org/download/CinelerraGG_Manual/Two_pass_Encoding_with_FFmp.html
|
|
if [[ $passes == 2 ]]; then
|
|
set -x
|
|
$time ffmpeg -nostdin $quiet \
|
|
-i "$file" $size $video $audio \
|
|
-filter:a "dynaudnorm=f=33:g=65:p=0.66:m=33.3" \
|
|
-vcodec libx264 -movflags +faststart \
|
|
$v2 \
|
|
-pass 1 -f mp4 /dev/null -y
|
|
status=$?
|
|
set +x
|
|
echo "`date` - Done with the first pass."
|
|
if [[ $status != 0 ]]; then
|
|
echo "Received unsuccessful status, exiting."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
set -x &&
|
|
$time ffmpeg -nostdin $quiet \
|
|
-i "$file" $size $video $audio \
|
|
-filter:a "dynaudnorm=f=33:g=65:p=0.66:m=33.3" \
|
|
-vcodec libx264 -movflags +faststart \
|
|
$v2 \
|
|
$pass "$newfile"
|
|
status="$?"
|
|
set +x
|
|
echo "`date` - Done with the final pass."
|
|
|
|
if [[ $passes == 2 && $status == 0 ]]; then
|
|
mv -v ffmpeg2pass*.log* ~/TRASH/
|
|
fi
|
|
|
|
echo "`date` - Syncing data."
|
|
sync
|
|
sleep 10
|
|
sync
|
|
|
|
if [[ -s $newfile ]]; then
|
|
echo "`date` - Getting file sizes."
|
|
du -h "$file"
|
|
du -h "$newfile"
|
|
else
|
|
echo "ERROR: New file not created or has a 0 size." >&2
|
|
fi
|
|
|
|
unset PV_VERTICAL_ASPECT_RATIO
|
|
unset PV_V2
|
|
unset PV_TIME
|
|
unset PV_PROGRESS
|
|
unset PV_VERBOSE
|
|
unset PV_2PASS
|
|
|
|
echo -e "\n`date` - Finished with status '$status'."
|
|
return $status
|
|
}
|
|
alias pv="process-video"
|
|
alias fn='basename `pwd`' # Folder Name
|
|
alias qpv='pv ./raw/YouCut*.mp4 `fn`.mp4' # Quick Process Video
|
|
|
|
alias set-pv-vertical='set-var PV_VERTICAL_ASPECT_RATIO "y" '
|
|
alias set-pv-time='set-var PV_TIME "y" '
|
|
alias set-pv-progress='set-var PV_PROGRESS "y" '
|
|
alias set-pv-verbose='set-var PV_VERBOSE "y" '
|
|
alias set-pv-2pass='set-var PV_2PASS "y" '
|
|
alias set-pv-v2='set-var PV_V2 "y" '
|
|
alias set-pv-v2='set-var PV_YIFY "y" '
|
|
|
|
alias set-pv-vert='set-pv-vertical '
|
|
alias set-pv2='set-pv-v2; set-pv-2pass; set-pv-progress '
|
|
|
|
alias pvs='set-pv-vert; pv '
|
|
alias pv2='set-pv2; pv '
|
|
|
|
alias pv2s='set-pv2; set-pv-vert; pv '
|
|
alias pvs2='pv2s '
|
|
|
|
alias qpv2='set-pv2; qpv '
|
|
|
|
# 20260713 - Attempt at compressing videos as well as done for torrented movies.
|
|
function pv-yify {
|
|
# ffmpeg -i input.mkv -c:v libx264 -crf 27 -x264-params cabac=1:ref=5:analyse=0x133:me=umh:subme=9:chroma-me=1:deadzone-inter=21:deadzone-intra=11:b-adapt=2:rc-lookahead=60:vbv-maxrate=10000:vbv-bufsize=10000:qpmax=69:bframes=5:direct=auto:crf-max=51:weightp=2:merange=24:chroma-qp-offset=-1:sync-lookahead=2:psy-rd=1.00,0.15:trellis=2:min-keyint=23:partitions=all -c:a aac -ar 44100 -b:a 128k -map 0 output.mp4
|
|
input="$1"
|
|
output="$2"
|
|
ratio="$3"
|
|
audio="$4"
|
|
|
|
if [[ -z "$input" ]]; then
|
|
cat <<- EOF
|
|
Usage: pv-yify INPUT_FILE [OUTPUT_FILE] [ASPECT_RATIO]
|
|
|
|
Examples:
|
|
|
|
- Create file raw.mp4.pv-yify.mp4 without changing aspect ratio:
|
|
$ pv-yify raw.mp4
|
|
|
|
- Compress a video and ensures it is 720p:
|
|
$ pv-yify raw.mp4 compressed.mp4 1280:720
|
|
|
|
- Compress a video ensuring that it is 720 pixels tall:
|
|
$ pv-yify raw.mp4 vertical.mp4 720:-1
|
|
EOF
|
|
fi
|
|
|
|
if [[ -z "$output" ]]; then
|
|
output="$input.pv-yify.mp4"
|
|
fi
|
|
|
|
echo -e "\n`date` - Converting '$input' with YIFY-like compression to '$output'."
|
|
|
|
if [[ -f "$output" ]]; then
|
|
echo -e "\n`date` - Moving '$output' to TRASH."
|
|
mv -v "$output" ~/TRASH/
|
|
fi
|
|
|
|
if [[ -n "$ratio" ]]; then
|
|
if [[ "$ratio" != *":"* ]]; then
|
|
echo "ERROR: Optional ratio parameter needs to be like '-1:720' (horizontal) or '720:-1' (vertical)".
|
|
return 1
|
|
fi
|
|
size="-filter:v scale=$ratio"
|
|
fi
|
|
|
|
if [[ -z "$audio" ]]; then
|
|
audio="128k"
|
|
fi
|
|
|
|
echo -e "\n`date` - Starting FFMPEG...\n"
|
|
set -x
|
|
ffmpeg -i "$input" \
|
|
-hide_banner -loglevel level+warning \
|
|
-c:v libx264 -crf 27 -c:a aac -ar 44100 -b:a "$audio" -map 0 \
|
|
-x264-params cabac=1:ref=5:analyse=0x133:me=umh:subme=9:chroma-me=1:deadzone-inter=21:deadzone-intra=11:b-adapt=2:rc-lookahead=60:vbv-maxrate=10000:vbv-bufsize=10000:qpmax=69:bframes=5:direct=auto:crf-max=51:weightp=2:merange=24:chroma-qp-offset=-1:sync-lookahead=2:psy-rd=1.00,0.15:trellis=2:min-keyint=23:partitions=all \
|
|
$ratio \
|
|
"$output"
|
|
set +x
|
|
echo -e "\n`date` - Finished FFMPEG."
|
|
|
|
echo -e "\n`date` - Syncing and checking file sizes."
|
|
sync
|
|
sleep 5
|
|
ls -lh "$input" "$output"
|
|
|
|
echo -e "\n`date` - Done!"
|
|
}
|
|
alias yify="pv-yify "
|
|
alias yify-pv="pv-yify "
|
|
|
|
function set-pv-all {
|
|
#set-var PV_VERTICAL_ASPECT_RATIO "y"
|
|
set-var PV_V2 "y"
|
|
set-var PV_TIME "y"
|
|
set-var PV_PROGRESS "y"
|
|
set-var PV_VERBOSE "y"
|
|
set-var PV_2PASS "y"
|
|
}
|
|
alias set-pv-everything='set-pv-all '
|
|
|
|
function unset-pv-all {
|
|
unset PV_VERTICAL_ASPECT_RATIO
|
|
unset PV_V2
|
|
unset PV_TIME
|
|
unset PV_PROGRESS
|
|
unset PV_VERBOSE
|
|
unset PV_2PASS
|
|
}
|
|
alias unset-pv-everything='unset-pv-all '
|
|
|
|
# Allow converting video to audio and other smaller
|
|
# tasks than what process-video is intended to do.
|
|
function basic-process-usage {
|
|
echo "basic-process INPUT OUTPUT NORMALIZE [EXTRA]"
|
|
echo -n "Pass a file through ffmpeg with the option"
|
|
echo "to easily normalize the audio with a Y."
|
|
echo "Examples:"
|
|
echo "- Normalize audio on a video."
|
|
echo " basic-process video.mp4 normalized.mp4 Y"
|
|
echo "- Convert a video to audio at 192k."
|
|
echo " basic-process video.mp4 audio.mp3 N '-b:a 192k'"
|
|
}
|
|
function basic-process {
|
|
# Parameters
|
|
input="$1"
|
|
output="$2"
|
|
typeset -u normalize
|
|
normalize="$3"
|
|
extra="$4"
|
|
|
|
echo "`date` - Starting basic-process"
|
|
|
|
# Validations
|
|
if [[ -z $input || ! -e $input ]]; then
|
|
echo "ERROR: Input file '$input' does not exist." >&2
|
|
basic-process-usage
|
|
return 1
|
|
fi
|
|
|
|
if [[ -z $output ]]; then
|
|
echo "ERROR: Output file's name must be provided." >&2
|
|
basic-process-usage
|
|
return 1
|
|
elif [[ -e $output ]]; then
|
|
echo "ERROR: Output file '$output' already exists." >&2
|
|
du -h "$output"
|
|
basic-process-usage
|
|
return 1
|
|
fi
|
|
|
|
if [[ $normalize == "Y" ]]; then
|
|
echo "Normalize set to TRUE."
|
|
normal="-filter:a dynaudnorm=f=33:g=65:p=0.66:m=33.3"
|
|
else
|
|
echo "No audio normalization is being done."
|
|
fi
|
|
|
|
# Main
|
|
echo "`date` - Converting '$input' to '$output'."
|
|
set -x
|
|
ffmpeg -nostdin -hide_banner -loglevel quiet \
|
|
-i "$input" $extra $normal "$output"
|
|
status=$?
|
|
set +x
|
|
|
|
if [[ $status != 0 ]]; then
|
|
echo "`date` - WARNING: ffmpeg exited with status '$status'." >&2
|
|
fi
|
|
|
|
# Finish
|
|
if [[ ! -s $output ]]; then
|
|
echo "`date` - ERROR: Output '$output' not created or has 0 size." >&2
|
|
return 1
|
|
fi
|
|
|
|
sync
|
|
echo "`date` - '$output' has been created successfully."
|
|
sleep 3
|
|
du -h "$input"
|
|
du -h "$output"
|
|
|
|
echo "`date` - Finished basic-process"
|
|
return 0
|
|
}
|
|
alias bp="basic-process"
|
|
alias bv="bp"
|
|
|
|
# Function to automatically append the Y.
|
|
function fix-audio { basic-process "$1" "$2" Y; }
|
|
function eq { fix-audio "$1" "$2"; }
|
|
|
|
# Function to easily turn a video to audio without typing the audio name.
|
|
function convert-to-audio {
|
|
video="$1"
|
|
audio="$2"
|
|
if [[ -z "$2" || "$2" == "Y" ]]; then
|
|
audio="${1//mp4/mp3}"
|
|
fi
|
|
volume=""
|
|
if [[ ( "$2" == "Y" && -z "$3" ) || "$3" == "Y" ]]; then
|
|
$volume="Y"
|
|
fi
|
|
basic-process "$video" "$audio" $volume
|
|
}
|
|
alias v2a="convert-to-audio"
|
|
alias vta="v2a"
|
|
alias pull-audio="v2a"
|
|
alias pa="v2a"
|
|
|
|
# Run all the different codecs, wrappers, bitrates, etc on a file.
|
|
function pv-test {
|
|
## Input ##
|
|
|
|
filename_in="$1"
|
|
while [[ -z "$filename_in" ]]; do
|
|
read -p "Please provide the filename: " filename_in
|
|
done
|
|
|
|
# Persistent Data #
|
|
|
|
normalize=""
|
|
typeset -u normalize_in
|
|
read -p "Would you like to normalize the audio? (Y/n) " normalize_in
|
|
if [[ $normalize_in != "N"* && $normalize_in != "F"* ]]; then
|
|
normalize="-filter:a dynaudnorm=f=33:g=65:p=0.66:m=33.3"
|
|
fi
|
|
echo " normalize: '$normalize'"
|
|
|
|
typeset -i size_in
|
|
read -p "What display ratio would you like to use? (720) " size_in
|
|
if (( $size_in == 0 )); then
|
|
size_in=720
|
|
fi
|
|
echo " size: '$size_in'"
|
|
|
|
# Loop Data #
|
|
|
|
echo "Setting some defaults..."
|
|
vcodecs="libx264 libsvtav1 libx265" && echo " video codecs: '$vcodecs'"
|
|
acodecs="aac libopus" && echo " audio codecs: '$acodecs'"
|
|
exts="mkv" && echo " extensions: '$exts'" # mp4
|
|
|
|
declare -l {vpreset,crf,vbr,abr}s="skip"
|
|
echo "$vpresets $crfs" #deleteme
|
|
|
|
read -p "Test presets? (y/N) " test_vpresets
|
|
if [[ "$test_vpresets" == "y"* ]]; then
|
|
vpresets="$vpresets slo fst med"
|
|
fi
|
|
echo " presets: '$vpresets'"
|
|
|
|
read -p "Test CRFs? (y/N) " test_crfs
|
|
if [[ "$test_crfs" == "y"* ]]; then
|
|
crfs="$crfs 24 26 28 30 32"
|
|
fi
|
|
echo " CRFs: '$crfs'"
|
|
|
|
read -p "Test video bitrates? (y/N) " test_vbrs
|
|
if [[ "$test_vbrs" == "y"* ]]; then
|
|
vbrs="$vbrs 1500k 2000k 2500k"
|
|
fi
|
|
echo " video bitrates: '$vbrs'"
|
|
|
|
read -p "Test audio bitrates? (y/N) " test_abrs
|
|
if [[ "$test_abrs" == "y"* ]]; then
|
|
abrs="$abrs 128k 192k"
|
|
fi
|
|
echo " audio bitrates: '$abrs'"
|
|
|
|
# Existing Functions #
|
|
|
|
declare -l pv{,2}="n"
|
|
typeset -l test_pv{,2}
|
|
|
|
read -p "Create a test with current 'pv' function? (Y/n) " test_pv
|
|
if [[ -z "$test_pv" || "$test_pv" == "y"* ]]; then
|
|
pv="y"
|
|
echo " great, will run pv"
|
|
else
|
|
echo " skipping"
|
|
fi
|
|
read -p "Create a test with current 'pv2' function? (Y/n) " test_pv2
|
|
if [[ -z "$test_pv2" || "$test_pv2" == "y"* ]]; then
|
|
pv2="y"
|
|
echo " great, will run pv2"
|
|
else
|
|
echo " skipping"
|
|
fi
|
|
|
|
# Final Check #
|
|
|
|
typeset -u okay
|
|
echo "Testing all this with '$filename_in'"
|
|
read -p "Look okay? (Y/n) " okay
|
|
if [[ "$okay" == "N" || "$okay" == "F"* ]]; then
|
|
echo "* Not okay, aborting."
|
|
return 1
|
|
fi
|
|
|
|
## Main ##
|
|
|
|
echo -e "Here we go!\n"
|
|
|
|
if [[ "$pv" == "y" ]]; then
|
|
echo "Starting pv..."
|
|
filename_pv="$(basename "${filename_in}-pv.mkv")"
|
|
if [[ -e "$filename_pv" ]]; then
|
|
mv -v "$filename_pv" ~/TRASH
|
|
fi
|
|
pv "$filename_in" "$filename_pv"
|
|
echo -e "Testing with 'pv' complete!\n"
|
|
fi
|
|
if [[ "$pv2" == "y" ]]; then
|
|
echo "Starting pv2..."
|
|
filename_pv2="$(basename "${filename_in}-pv2.mkv")"
|
|
if [[ -e "$filename_pv2" ]]; then
|
|
mv -v "$filename_pv2" ~/TRASH
|
|
fi
|
|
pv "$filename_in" "$filename_pv2"
|
|
echo -e "Testing with 'pv2' complete!\n"
|
|
fi
|
|
|
|
echo -e "\nStarting the loop...\n"
|
|
|
|
unset vcodec vpreset crf vbr acodec abr ext
|
|
for vcodec in $vcodecs; do
|
|
for vpreset in $vpresets; do
|
|
for crf in $crfs; do
|
|
for vbr in $vbrs; do
|
|
for acodec in $acodecs; do
|
|
for abr in $abrs; do
|
|
for ext in $exts; do
|
|
|
|
preset=""
|
|
if [[ "$vpreset" != "skip" ]]; then
|
|
if [[ "$vcodec" == "libsvtav1" ]]; then
|
|
case $vpreset in
|
|
slo) preset="0" ;;
|
|
med) preset="6" ;;
|
|
fst) preset="13" ;;
|
|
esac
|
|
else
|
|
case $vpreset in
|
|
slo) preset="veryslow" ;;
|
|
med) preset="medium" ;;
|
|
fst) preset="ultrafast" ;;
|
|
esac
|
|
fi
|
|
if [[ -n "$preset" ]]; then
|
|
preset="-preset $preset"
|
|
fi
|
|
fi
|
|
|
|
bitrate=""
|
|
if [[ "$crf" != "skip" ]]; then
|
|
bitrate="-crf $crf"
|
|
fi
|
|
if [[ "$vbr" != "skip" ]]; then
|
|
if [[ "$vcodec" == "libsvtav1" ]]; then
|
|
bitrate="$bitrate -svtav1-params rc=1:tbr=$vbr:overshoot-pct=0:undershoot-pct=100"
|
|
else
|
|
bitrate="$bitrate -b:v $vbr -minrate 0 -maxrate $vbr -bufsize $vbr"
|
|
fi
|
|
fi
|
|
|
|
fidelity=""
|
|
if [[ "$abr" != "skip" ]]; then
|
|
fidelity="-b:a $abr"
|
|
fi
|
|
|
|
newfile="_${size_in}p_${vcodec}-${vpreset}-${vbr}${crf}_${acodec}-${abr}.${ext}"
|
|
if [[ -e "$newfile" ]]; then
|
|
mv -v "$newfile" ~/TRASH/
|
|
fi
|
|
|
|
echo -e "\n* Starting new run...\n"
|
|
echo -e "Parameters for this run: $newfile\n"
|
|
|
|
start=$SECONDS
|
|
set -x
|
|
ffmpeg -nostdin -hide_banner -loglevel level+warning \
|
|
-i "$filename_in" \
|
|
-filter:v scale=-1:$size_in \
|
|
-c:v $vcodec \
|
|
$preset \
|
|
$bitrate \
|
|
-c:a $acodec \
|
|
$fidelity \
|
|
$normalize \
|
|
-movflags +faststart \
|
|
"$newfile"
|
|
set +x
|
|
finish=$SECONDS
|
|
|
|
minutes=$(( (finish - start) / 60 ))
|
|
seconds=$(( (finish - start) % 60 ))
|
|
printf -v padded_mins "%03d" "$minutes"
|
|
printf -v padded_secs "%02d" "$seconds"
|
|
|
|
mv -v "$newfile" "${filename_in}_${padded_mins}m${padded_secs}s${newfile}"
|
|
|
|
echo -e "\n* Finished in ${minutes}m${seconds}s!\n"
|
|
done
|
|
done
|
|
done
|
|
done
|
|
done
|
|
done
|
|
done
|
|
|
|
## Finish ##
|
|
|
|
echo "Done! :)"
|
|
}
|
|
|
|
|
|
### Web ###
|
|
|
|
function download-website {
|
|
website="$1"
|
|
if [[ -z "$website" ]]; then
|
|
echo "ERROR: Website not provided. $website"
|
|
return
|
|
fi
|
|
if [[ "$website" != "http"* ]]; then
|
|
website="http://$website"
|
|
fi
|
|
# https://simpleit.rocks/linux/how-to-download-a-website-with-wget-the-right-way/
|
|
# Does not simplify the links for offline usage.
|
|
# wget --wait=2 \
|
|
# --level=inf \
|
|
# --limit-rate=20K \
|
|
# --recursive \
|
|
# --page-requisites \
|
|
# --user-agent=Mozilla \
|
|
# --no-parent \
|
|
# --convert-links \
|
|
# --adjust-extension \
|
|
# --no-clobber \
|
|
# -e robots=off \
|
|
# $website &&
|
|
|
|
# https://www.digitalcitizen.life/how-to-download-entire-website-for-offline-viewing/
|
|
# This one is supposed to work too and is much smaller.
|
|
# wget --mirror \
|
|
# --convert-links \
|
|
# --adjust-extension \
|
|
# --page-requisites \
|
|
# --no-parent \
|
|
# $website &&
|
|
|
|
# Combine the two by using mirow and removing the rate limit.
|
|
wget --mirror \
|
|
--wait=2 \
|
|
--level=inf \
|
|
--recursive \
|
|
--page-requisites \
|
|
--user-agent=Mozilla \
|
|
--no-parent \
|
|
--convert-links \
|
|
--adjust-extension \
|
|
--no-clobber \
|
|
-e robots=off \
|
|
--timeout=15 \
|
|
--tries=0 \
|
|
--continue \
|
|
--waitretry=5 \
|
|
--random-wait \
|
|
$website &&
|
|
{
|
|
echo -e "\nSuccess!"
|
|
} || {
|
|
echo -e "\nERROR: Command reported a failure. (Error code '$?')"
|
|
echo "This may mean that the URL was not converted to local links."
|
|
echo "Please check the error and contents and try again if needed."
|
|
}
|
|
}
|
|
alias website-download="download-website"
|
|
alias curl-site="download-website"
|
|
alias pull-site="download-website"
|
|
alias site-pull="download-website"
|
|
alias curl-www="download-website"
|
|
alias pull-www="download-website"
|
|
alias www-pull="download-website"
|
|
|
|
function run-site {
|
|
python3 -m http.server
|
|
}
|
|
alias run-html="run-site"
|
|
alias exec-site="run-site"
|
|
alias exec-html="run-site"
|
|
alias site-host="run-site"
|
|
alias host-site="run-site"
|
|
|
|
# TBD: Move this to a different section?
|
|
function git-check {
|
|
dir="`pwd`"
|
|
if [[ -n "$1" ]]; then
|
|
dir="$1"
|
|
fi
|
|
|
|
echo "Checking '$dir' for git changes."
|
|
ls -d "$dir"/* | while read project; do
|
|
if [[ ! -d $project ]]; then
|
|
continue
|
|
fi
|
|
echo -e "\n*** `basename $project` ***"
|
|
cd $project
|
|
if [[ -d .git ]]; then
|
|
git ls-remote --exit-code --heads origin dev
|
|
dev_exists="$?"
|
|
if [[ "$dev_exists" == 0 && "$dir" != *".wiki" ]]; then
|
|
git switch dev
|
|
elif [[ "$dev_exists" == 2 || "$dir" == *".wiki" ]]; then
|
|
git switch main
|
|
else
|
|
echo "ERROR: Unknown status for dev_exists, '$dev_exists'."
|
|
continue
|
|
fi
|
|
git pull
|
|
git push
|
|
else
|
|
echo "Not a Git project, skipping!"
|
|
fi
|
|
done
|
|
echo -e "\nDone!"
|
|
}
|
|
|
|
# TBD: Move this to a different section?
|
|
function check-colors {
|
|
min=0
|
|
max=256
|
|
unset i
|
|
echo "Current terminal supports '`tput colors`' colors."
|
|
echo "Displaying examples..."
|
|
for (( i = min; i <= max; i++ )); do
|
|
tput setaf $i
|
|
printf "%03d" "$i"
|
|
tput sgr0
|
|
if (( i < max )); then
|
|
printf " "
|
|
fi
|
|
done
|
|
printf "\n"
|
|
}
|
|
alias color-check="check-colors"
|
|
alias show-colors="check-colors"
|
|
alias test-colors="check-colors"
|
|
alias colors="check-colors"
|
|
alias term-colors="check-colors"
|
|
alias display-colors="check-colors"
|
|
|
|
|
|
## Finalize ##
|
|
|
|
# Export all functions! #
|
|
eval "$(declare -F | grep -v _ | sed 's/-f /-fx /')"
|
|
|
|
# Run update checker in background.
|
|
if [[ "$USER" != "root" ]]; then
|
|
(
|
|
if [[ -d "$PROJECT_SHARED" ]]; then
|
|
git -C "$PROJECT_SHARED" fetch >/dev/null 2>&1 \
|
|
&& git -C "$PROJECT_SHARED" status \
|
|
| grep "is behind" \
|
|
| while read status; do
|
|
title=TBD
|
|
message=TBD
|
|
success=0
|
|
reload-shared || success=1
|
|
if [[ "$success" == 0 ]]; then
|
|
title="env-shared Updated"
|
|
message="Reloaded automatically, please reload BASH. :)"
|
|
else
|
|
title="env-shared Updates Available"
|
|
message="Update with 'reload-shared'."
|
|
fi
|
|
if [[ -d /sdcard ]]; then
|
|
termux-notification \
|
|
-t "$title" \
|
|
-c "$message"
|
|
else
|
|
notify-send "$title" "$message"
|
|
fi
|
|
done
|
|
fi >> "$HOME"/Reports/env-shared.log.txt 2>&1 &
|
|
)
|
|
fi
|
|
|
|
|
|
## Complete! ##
|
|
|
|
[[ $(whoami) != "root" ]] &&
|
|
echo "`date` - Shared RC Config - Complete!"
|
|
|
|
export _LOADED_SHARED_RC=true
|