Compare commits

..

No commits in common. "cf550ef9cab77e6a8d0b66deb2a462b7f0f597a0" and "f109fbfcc35a66034e7e189683f8543223964394" have entirely different histories.

4 changed files with 66 additions and 166 deletions

View file

@ -6,8 +6,6 @@
| [[#ffconv][ffconv]] | Convert multiple media files from one format to another | | [[#ffconv][ffconv]] | Convert multiple media files from one format to another |
| [[#ffcut][ffcut]] | Extract a part of a media file | | [[#ffcut][ffcut]] | Extract a part of a media file |
All are created with the [[https://github.com/Deleh/sf][sf]] script framework.
** Dependencies ** Dependencies
- [[https://ffmpeg.org/][FFmpeg]] - [[https://ffmpeg.org/][FFmpeg]]
@ -54,19 +52,19 @@
TO_FORMAT To format TO_FORMAT To format
OPTIONS OPTIONS
-d, --directory DIRECTORY Convert files in DIRECTORY (default: current work -d, --directory DIRECTORY Convert files in DIRECTORY (default: current work d
directory) irectory)
-k, --keep Keep original files -k, --keep Keep original files
-l, --list List files which match the FROM_FORMAT -l, --list List files which match the FROM_FORMAT
-m, --move DIRECTORY Move old files to DIRECTORY (omits --keep) -m, --move DIRECTORY Move old files to DIRECTORY (omits --keep) (default
-h, --help Show this help message and exit : )
EXAMPLES EXAMPLES
ffconv mp3 opus Convert all mp3 files to opus ffconv mp3 opus Convert all mp3 files to opus
ffconv -m trash mp4 mkv Convert all mp4 to mkv and move the original ffconv -m trash mp4 mkv Convert all mp4 to mkv and move the original one
ones to './trash' s to './trash'
ffconv -d ~/music -l wma mp3 List all wma files from '~/music' and ask for ffconv -d ~/music -l wma mp3 List all wma files from '~/music' and ask for co
converting them to mp3 nverting them to mp3
#+end_example #+end_example
*** =ffcut= *** =ffcut=
@ -94,14 +92,13 @@
OPTIONS OPTIONS
-f, --from TIMESTAMP/SECONDS Extract from TIMESTAMP/SECONDS (default: 0) -f, --from TIMESTAMP/SECONDS Extract from TIMESTAMP/SECONDS (default: 0)
-o, --out FILE Save extracted part to FILE (default: -o, --out FILE Save extracted part to FILE (default: cutted_<fi
cutted_<filename>) lename>)
-t, --to TIMESTAMP/DURATION Extract to TIMESTAMP/DURATION (default: end) -t, --to TIMESTAMP/DURATION Extract to TIMESTAMP/DURATION (default: end)
-h, --help Show this help message and exit
EXAMPLES EXAMPLES
ffcut -t 5 video.mp4 -o cut.webm Extract the first five seconds of ffcut -t 5 video.mp4 -o cut.webm Extract the first five seconds of 'vi
'video.mp4' to 'cut.webm' deo.mp4' to 'cut.webm'
ffcut -f 00:10:30 -t 00:14:15 video.mp4 Extract the part from 00:10:30 to ffcut -f 00:10:30 -t 00:14:15 video.mp4 Extract the part from 00:10:30 to 00:
00:14:15 from 'video.mp4' 14:15 from 'video.mp4'
#+end_example #+end_example

View file

@ -11,7 +11,6 @@ sfargs+=("move;m;DIRECTORY;;Move old files to DIRECTORY (omits --keep)")
sfexamples+=("ffconv mp3 opus;Convert all mp3 files to opus") sfexamples+=("ffconv mp3 opus;Convert all mp3 files to opus")
sfexamples+=("ffconv -m trash mp4 mkv;Convert all mp4 to mkv and move the original ones to './trash'") sfexamples+=("ffconv -m trash mp4 mkv;Convert all mp4 to mkv and move the original ones to './trash'")
sfexamples+=("ffconv -d ~/music -l wma mp3;List all wma files from '~/music' and ask for converting them to mp3") sfexamples+=("ffconv -d ~/music -l wma mp3;List all wma files from '~/music' and ask for converting them to mp3")
sfdeps=("ffmpeg")
source "$(dirname $0)/../lib/sf" source "$(dirname $0)/../lib/sf"

View file

@ -8,23 +8,23 @@ sfargs+=("out;o;FILE;cutted_<filename>;Save extracted part to FILE")
sfargs+=("to;t;TIMESTAMP/DURATION;end;Extract to TIMESTAMP/DURATION") sfargs+=("to;t;TIMESTAMP/DURATION;end;Extract to TIMESTAMP/DURATION")
sfexamples+=("ffcut -t 5 video.mp4 -o cut.webm;Extract the first five seconds of 'video.mp4' to 'cut.webm'") sfexamples+=("ffcut -t 5 video.mp4 -o cut.webm;Extract the first five seconds of 'video.mp4' to 'cut.webm'")
sfexamples+=("ffcut -f 00:10:30 -t 00:14:15 video.mp4;Extract the part from 00:10:30 to 00:14:15 from 'video.mp4'") sfexamples+=("ffcut -f 00:10:30 -t 00:14:15 video.mp4;Extract the part from 00:10:30 to 00:14:15 from 'video.mp4'")
sfdeps=("ffmpeg")
source "$(dirname $0)/../lib/sf" source "$(dirname $0)/../lib/sf"
# Handle missing parameters # Handle missing parameters
[ "$from" == 0 ] && [ "$to" == "end" ] && sferr "Set at least ${sftbf}--from${sftrs} or ${sftbf}--to${sftrs}" [ "$from" == 0 ] && [ "$to" == "end" ] && sferr "Set at least '--from' or '--to'"
# Set default value for output file # Set default value for output file
[ "$out" == "cutted_<filename>" ] && out="$(dirname "$FILE")/cutted_$(basename "$FILE")" [ "$out" == "cutted_<filename>" ] && out="$(dirname "$FILE")/cutted_$(basename "$FILE")"
echo "Cutting file ${sftbf}$(basename "$FILE")${sftrs}"
# Set additional ffmpeg arguments # Set additional ffmpeg arguments
args=() ffmpeg_args=()
[ "$to" != "end" ] && args+=("-to" "$to") [ "$to" != "end" ] && ffmpeg_args+=("-t" "$to")
[ "${FILE##*.}" == "${out##*.}" ] && args+=("-c" "copy") [ "${FILE##*.}" == "${out##*.}" ] && ffmpeg_args+=("-c" "copy")
# Execute ffmpeg # Execute ffmpeg
echo "Cutting file ${sftbf}$(basename "$FILE")${sftrs}" ffmpeg -hide_banner -loglevel error -ss "$from" -i "$FILE" -ss "$from" "${ffmpeg_args[@]}" "$out"
ffmpeg -hide_banner -loglevel error -i "$FILE" -ss "$from" "${args[@]}" "$out"
[ "$?" == "0" ] && echo "The extracted part was saved to ${sftbf}$out${sftrs}" [ "$?" == "0" ] && echo "The extracted part was saved to ${sftbf}$out${sftrs}"

180
lib/sf
View file

@ -32,21 +32,17 @@ function sfwarn {
# Public input functions # Public input functions
function sfask { function sfask {
if [ -n "$2" ]; then if [ "$2" == "" ]; then
read -r -p "$1? [${sftbf}y${sftrs}/${sftbf}N${sftrs}] " sfin read -p "$1? [${sftbf}Y${sftrs}/${sftbf}n${sftrs}] " sfin
[[ "$sfin" =~ n|N|^$ ]] && sfin=false || sfin=true
else
read -r -p "$1? [${sftbf}Y${sftrs}/${sftbf}n${sftrs}] " sfin
[[ "$sfin" =~ y|Y|^$ ]] && sfin=true || sfin=false [[ "$sfin" =~ y|Y|^$ ]] && sfin=true || sfin=false
else
read -p "$1? [${sftbf}y${sftrs}/${sftbf}N${sftrs}] " sfin
[[ "$sfin" =~ n|N|^$ ]] && sfin=false || sfin=true
fi fi
} }
function sfget { function sfget {
if [ -n "$2" ]; then [ "$2" != "" ] && read -p "$1 [${sftbf}$2${sftrs}]: " sfin || read -p "$1: " sfin
read -r -p "$1 [${sftbf}$2${sftrs}]: " sfin
else
read -r -p "$1: " sfin
fi
[ "$sfin" == "" ] && [ "$2" != "" ] && sfin="$2" [ "$sfin" == "" ] && [ "$2" != "" ] && sfin="$2"
} }
@ -59,82 +55,64 @@ function _sferr {
# Declare variables for parsing # Declare variables for parsing
OLDIFS=$IFS OLDIFS=$IFS
IFS=";" IFS=";"
_sfphead=""
_sfpdesc=""
_sfodesc=""
_sfexamples=""
_sfpargs=() _sfpargs=()
_sfpheads=()
_sfpoffset=0
_sfptails=()
_sfpusage=""
_sfoheads=()
_sfooffset=0
_sfotails=()
declare -A _sfflags declare -A _sfflags
declare -A _sfargs declare -A _sfargs
# Parse sf arguments # Parse sf arguments
sfargs=("${sfargs[@]}" "help;h;Show this help message and exit")
for a in "${sfargs[@]}"; do for a in "${sfargs[@]}"; do
# Get amount of ; # Get amount of ;
_sfsubst=${a//";"} _sfsubst=${a//";"}
_sfcount="$(((${#a} - ${#_sfsubst})))" _sfcount="$(((${#a} - ${#_sfsubst})))"
if [ "$_sfcount" -eq 1 ]; then if [ $_sfcount -eq 1 ]; then
# Read positional argument declaration # Read positional argument declaration
read -r -a _sfparsearr <<< "${a}" read -r -a _sfparsearr <<< "${a}"
# Add to positional argument arry # Add to positional argument arry
[[ " ${_sfpargs[*]} " =~ " ${_sfparsearr[0]} " ]] && _sferr "'${_sfparsearr[0]}' is already set: $a"
_sfpargs+=("${_sfparsearr[0]}") _sfpargs+=("${_sfparsearr[0]}")
# Set usage header and append description arrays # Set usage header and description
_sfpusage="$_sfpusage ${_sfparsearr[0]}" _sfphead="$_sfphead ${_sfparsearr[0]}"
_sfphead="${_sfparsearr[0]}" _sfpdesc="$_sfpdesc ${_sfparsearr[0]};${_sfparsearr[1]}\n"
[ "${#_sfphead}" -gt "${_sfpoffset}" ] && _sfpoffset="${#_sfphead}"
_sfpheads+=("$_sfphead")
_sfptails+=("${_sfparsearr[1]}")
# Flags # Flags
elif [ "$_sfcount" -eq 2 ]; then elif [ $_sfcount -eq 2 ]; then
# Read flag declaration # Read flag declaration
read -r -a _sfparsearr <<< "${a}" read -r -a _sfparsearr <<< "${a}"
# Set mappings # Set mappings
[ -n "${_sfflags["--${_sfparsearr[0]}"]}" ] && _sferr "'${_sfparsearr[0]}' is already set: $a"
_sfflags["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
[ -n "${_sfflags["-${_sfparsearr[1]}"]}" ] && _sferr "'${_sfparsearr[1]}' is already set: $a"
_sfflags["-${_sfparsearr[1]}"]="${_sfparsearr[0]}" _sfflags["-${_sfparsearr[1]}"]="${_sfparsearr[0]}"
_sfflags["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
# Set default value # Set default value
declare "${_sfparsearr[0]//-/_}"=false declare ${_sfparsearr[0]}=false
# Append description arrays # Set description
_sfohead="-${_sfparsearr[1]}, --${_sfparsearr[0]}" _sfodesc="$_sfodesc -${_sfparsearr[1]}, --${_sfparsearr[0]};${_sfparsearr[2]}\n"
[ "${#_sfohead}" -gt "${_sfooffset}" ] && _sfooffset="${#_sfohead}"
_sfoheads+=("$_sfohead")
_sfotails+=("${_sfparsearr[2]}")
# Arguments # Arguments
elif [ "$_sfcount" -eq 4 ]; then elif [ $_sfcount -eq 4 ]; then
# Read argument declaration # Read argument declaration
read -r -a _sfparsearr <<< "${a}" read -r -a _sfparsearr <<< "${a}"
# Set mappings # Set mappings
[ -n "${_sfargs["--${_sfparsearr[0]}"]}" ] && _sferr "'${_sfparsearr[0]}' is already set: $a"
_sfargs["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
[ -n "${_sfargs["-${_sfparsearr[1]}"]}" ] && _sferr "'${_sfparsearr[1]}' is already set: $a"
_sfargs["-${_sfparsearr[1]}"]="${_sfparsearr[0]}" _sfargs["-${_sfparsearr[1]}"]="${_sfparsearr[0]}"
_sfargs["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
# Set default value # Set default value
declare "${_sfparsearr[0]//-/_}"="${_sfparsearr[3]}" declare ${_sfparsearr[0]}="${_sfparsearr[3]}"
# Append description arrays # Set description
_sfohead="-${_sfparsearr[1]}, --${_sfparsearr[0]} ${_sfparsearr[2]}" _sfodesc="$_sfodesc -${_sfparsearr[1]}, --${_sfparsearr[0]} ${_sfparsearr[2]};${_sfparsearr[4]} (default: ${_sfparsearr[3]})\n"
[ "${#_sfohead}" -gt "${_sfooffset}" ] && _sfooffset="${#_sfohead}"
_sfoheads+=("$_sfohead")
[ "${_sfparsearr[3]}" != "" ] && _sfotails+=("${_sfparsearr[4]} (default: ${_sfparsearr[3]})") || _sfotails+=("${_sfparsearr[4]}")
else else
_sferr "Wrong argument declaration: $a" _sferr "Wrong argument declaration: $a"
@ -142,26 +120,18 @@ for a in "${sfargs[@]}"; do
done done
# Parse examples # Parse examples
_sfeheads=()
_sfetails=()
_sfeoffset=0
for e in "${sfexamples[@]}"; do for e in "${sfexamples[@]}"; do
# Get amount of ; # Get amount of ;
_sfsubst=${e//";"} _sfsubst=${e//";"}
_sfcount="$(((${#e} - ${#_sfsubst})))" _sfcount="$(((${#e} - ${#_sfsubst})))"
if [ "$_sfcount" -eq 1 ]; then if [ $_sfcount -eq 1 ]; then
# Read example # Read example
read -r -a _sfparsearr <<< "${e}" read -r -a _sfparsearr <<< "${e}"
# Append example arrays _sfexamples="$_sfexamples ${_sfparsearr[0]};${_sfparsearr[1]}\n"
_sfehead="${_sfparsearr[0]}"
[ "${#_sfehead}" -gt "${_sfeoffset}" ] && _sfeoffset="${#_sfehead}"
_sfeheads+=("$_sfehead")
_sfetails+=("${_sfparsearr[1]}")
else else
_sferr "Wrong example declaration: $e" _sferr "Wrong example declaration: $e"
fi fi
@ -169,76 +139,25 @@ done
IFS=$OLDIFS IFS=$OLDIFS
# Check if at least one positional argument is set if 'sfparr' is used
[ "$sfparr" == true ] && [ "${#_sfpargs[@]}" == 0 ] && _sferr "At least one positional argument must be used with 'sfparr'"
# Correct offsets
_sfpoffset=$(( "_sfpoffset" + 3 ))
_sfooffset=$(( "_sfooffset" + 3 ))
_sfeoffset=$(( "_sfeoffset" + 3 ))
# Set _sfwidth to current terminal width
_sfwidth=$(stty size | cut -d ' ' -f 2)
# Create positional argument description with correct line breaks
_sfpdesc=""
for i in "${!_sfptails[@]}"; do
_sfptail="${_sfptails[$i]}"
if [ "$(( ${#_sfptail} + _sfpoffset ))" -gt "$_sfwidth" ]; then
_sftmpwidth="$(( _sfwidth - _sfpoffset ))"
_sftmpwidth=$(echo -e "${_sftmpwidth}\n1" | sort -nr | head -n 1)
_sfptail=$(echo "$_sfptail" | fold -s -w "$_sftmpwidth")
_sfptail="${_sfptail//$' \n'/$'\n;'}"
fi
_sfpdesc="${_sfpdesc} ${_sfpheads[$i]};${_sfptail}\n"
done
# Create option description with correct line breaks
_sfodesc=""
for i in "${!_sfotails[@]}"; do
_sfotail="${_sfotails[$i]}"
if [ "$(( ${#_sfotail} + _sfooffset ))" -gt "$_sfwidth" ]; then
_sftmpwidth="$(( _sfwidth - _sfooffset ))"
_sftmpwidth=$(echo -e "${_sftmpwidth}\n1" | sort -nr | head -n 1)
_sfotail=$(echo "$_sfotail" | fold -s -w "$_sftmpwidth")
_sfotail="${_sfotail//$' \n'/$'\n;'}"
fi
_sfodesc="${_sfodesc} ${_sfoheads[$i]};${_sfotail}\n"
done
# Create examples description with correct line breaks
_sfexamples=""
for i in "${!_sfetails[@]}"; do
_sfetail="${_sfetails[$i]}"
if [ "$(( ${#_sfetail} + _sfeoffset ))" -gt "$_sfwidth" ]; then
_sftmpwidth="$(( _sfwidth - _sfeoffset ))"
_sftmpwidth=$(echo -e "${_sftmpwidth}\n1" | sort -nr | head -n 1)
_sfetail=$(echo "$_sfetail" | fold -s -w "$_sftmpwidth")
_sfetail="${_sfetail//$' \n'/$'\n;'}"
fi
_sfexamples="${_sfexamples} ${_sfeheads[$i]};${_sfetail}\n"
done
# Usage function # Usage function
function _sfusage { function _sfusage {
echo -n "Usage: $(basename "$0") [OPTIONS]" echo -n "Usage: $(basename $0)"
echo -ne "$_sfpusage" [ "$_sfodesc" != "" ] && echo -n " [OPTIONS]"
[ "$sfparr" == true ] && echo -n " ..." echo -e "$_sfphead"
echo [ ! -z ${sfdesc+x} ] && echo -e "\n$sfdesc"
[ -n "${sfdesc}" ] && echo -e "\n$sfdesc" | fold -s -w "$_sfwidth"
if [ "$_sfpdesc" != "" ]; then if [ "$_sfpdesc" != "" ]; then
echo -e "\nPOSITIONAL ARGUMENTS" echo -e "\nPOSITIONAL ARGUMENTS"
echo -e "$_sfpdesc" | column -s ";" -t -W 2 echo -e "$_sfpdesc" | column -c 80 -s ";" -t -W 2
fi fi
if [ "$_sfodesc" != "" ]; then if [ "$_sfodesc" != "" ]; then
echo -e "\nOPTIONS" echo -e "\nOPTIONS"
echo -e "$_sfodesc" | column -s ";" -t -W 2 echo -e "$_sfodesc" | column -c 80 -s ";" -t -W 2
fi fi
if [ "$_sfexamples" != "" ]; then if [ "$_sfexamples" != "" ]; then
echo -e "\nEXAMPLES" echo -e "\nEXAMPLES"
echo -e "$_sfexamples" | column -s ";" -t -W 2 echo -e "$_sfexamples" | column -c 80 -s ";" -t -W 2
fi fi
if [ -n "${sfextra}" ]; then if [ ! -z ${sfextra+x} ]; then
echo -e "\n$sfextra" echo -e "\n$sfextra"
fi fi
exit 0 exit 0
@ -250,28 +169,19 @@ for a in "$@"; do
[ "$a" == "-h" ] || [ "$a" == "--help" ] && _sfusage [ "$a" == "-h" ] || [ "$a" == "--help" ] && _sfusage
done done
# Check if dependencies are available
for d in "${sfdeps[@]}"; do
if ! command -v "$d" &> /dev/null; then
sferr "Command ${sftbf}${d}${sftrs} not found" 0
_sfdeperr=true
fi
done
[ "$_sfdeperr" == true ] && exit 1
# Parse arguments # Parse arguments
while (( "$#" )); do while (( "$#" )); do
# Check if flag # Check if flag
if [ -n "${_sfflags["$1"]}" ]; then if [ ! -z ${_sfflags["$1"]} ]; then
declare "${_sfflags["$1"]//-/_}"=true declare ${_sfflags["$1"]}=true
# Check if argument # Check if argument
elif [ -n "${_sfargs["$1"]}" ]; then elif [ ! -z ${_sfargs["$1"]} ]; then
# Check if argument has value # Check if argument has value
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
declare "${_sfargs["$1"]//-/_}"="$2" declare ${_sfargs["$1"]}="$2"
shift shift
else else
sferr "Argument for '$1' missing" sferr "Argument for '$1' missing"
@ -281,15 +191,12 @@ while (( "$#" )); do
else else
# Check if arg starts with - # Check if arg starts with -
if [ "${1:0:1}" == "-" ]; then if [ "${1:0:1}" == "-" ]; then
sferr "Unsupported argument/flag: $1" sferr "Unsupported argument: $1"
else else
# Set positional argument # Set positional argument
if [ "${#_sfpargs[@]}" != 0 ]; then if [ "${#_sfpargs[@]}" != 0 ]; then
declare "${_sfpargs[0]//-/_}"="$1" declare ${_sfpargs[0]}="$1"
[ "$sfparr" == true ] && _sfplast="${_sfpargs[0]//-/_}" && _sfparr=("$1")
_sfpargs=("${_sfpargs[@]:1}") _sfpargs=("${_sfpargs[@]:1}")
elif [ "$sfparr" == true ]; then
_sfparr+=("$1")
else else
sferr "Too many positional arguments" sferr "Too many positional arguments"
fi fi
@ -298,11 +205,8 @@ while (( "$#" )); do
shift shift
done done
# Parse additional arguments if 'sfparr' is set
[ "$sfparr" == true ] && [ "${#_sfparr[@]}" -gt 0 ] && read -r -a "${_sfplast?}" <<< "${_sfparr[@]}"
# Check if positional arguments left # Check if positional arguments left
if [ "${#_sfpargs[@]}" -gt 0 ]; then if [ ${#_sfpargs[@]} != 0 ]; then
for p in "${_sfpargs[@]}"; do for p in "${_sfpargs[@]}"; do
sferr "Positional argument '$p' missing" 0 sferr "Positional argument '$p' missing" 0
done done
@ -310,4 +214,4 @@ if [ "${#_sfpargs[@]}" -gt 0 ]; then
fi fi
# Unset all internal variables and functions # Unset all internal variables and functions
unset a d e i OLDIFS _sfargs _sfehead _sfeheads _sfeoffset _sferr _sfetails _sfexamples _sfflags _sfodesc _sfohead _sfoheads _sfooffset _sfotails _sfpargs _sfparr _sfpdesc _sfphead _sfpheads _sfplast _sfpoffset _sfptails _sfpusage _sftmpwidth _sfusage _sfwidth unset a e _sfphead _sfpdesc _sfodesc _sfexamples _sfpargs _sfflags _sfargs _sferr _sfusage