~voidraven/mp3me

mp3me/mp3me.sh -rwxr-xr-x 3.6 KiB
107e81f1voidraven updated version output format a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/bin/sh
# mp3me
# author: voidraven
# https://sr.ht/~voidraven/mp3me/
# license: BSD 3-clause
#
# A portable shell script for converting audio files to mp3.
# It works on directories of music in parallel.
#
# Dependencies: ffmpeg, gnu parallel
#
VERSION="0.3.1"

# default bitrate and jobs
BITRATE=320000
# Portable way to get the number of cores available to the system (Linux, BSD, and MacOS)
CORES_AVAIL=$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu || echo 2)
# Default number of threads to use (half available cores)
JOBS=$(( CORES_AVAIL / 2 ))

SHIFT=0


# check if the file provided is a has a valid music extension
# cuts off extension and compares it
fun_is_music () {
    L_FILE="$1"
    # ignore directories
    if [ -f "$L_FILE" ] ; then
	# get extension
	L_FILE_EXT="${L_FILE##*.}"
	# get lowercase version
	L_FILE_EXT=$(echo "$L_FILE_EXT" | tr '[:upper:]' '[:lower:]')
	if [ "$L_FILE_EXT" = "flac" ] || [ "$L_FILE_EXT" = "aac" ] || [ "$L_FILE_EXT" = "ogg" ] || [ "$L_FILE_EXT" = "wav" ] || [ "$L_FILE_EXT" = "m4a" ] ; then
	    unset L_FILE L_FILE_EXT
	    return 0    
	fi
	unset L_FILE_EXT
    fi
    unset L_FILE 
    return 1
}


# echoes out all the valid music files in a directory
fun_echo_files () {
    L_LWD=$(pwd)
    cd "$1" || fun_error "failed to enter directory: $1"
    for FILE in * ; do
	if fun_is_music "$FILE" ; then
	    echo "$FILE"
	fi
    done
    cd "$L_LWD" || fun_error "failed to enter directory: $1"
    unset L_LWD
}


# take user input as kbps and return bps
fun_get_bitrate () {
    L_BR="$1"
    if [ "$L_BR" -gt 0 ] && [ "$L_BR" -lt 321 ] ; then
	BITRATE=$((L_BR*1000))
	SHIFT=$((SHIFT+2))
    else
	unset L_BR
	fun_error "bad bitrate value passed in"
    fi
    unset L_BR
}


fun_check_jobs () {
    if [ "$1" -gt 0 ] && [ "$1" -lt 256 ] ; then
	JOBS="$1"
	SHIFT=$((SHIFT+2))
    else
	fun_error "bad number of jobs passed in (0 < j < 256)"
    fi
}


# call this function to start the script
fun_run () {
    echo "mp3me - beginning conversion $1 with $JOBS jobs."
    # SC2086 - yes, we want to split on spaces since we are building a command line
    # SC1083 - yes, the '{}' char are literal parallel uses them
    # shellcheck disable=SC2086,SC1083
    fun_echo_files "$1" | parallel -j $JOBS ffmpeg -hide_banner -nostats -loglevel fatal -i "'$1'"/{} -b:a $BITRATE "'$1'"/{.}.mp3
}


# run when ctrl-c is pressed
fun_cleanup () {
    echo "caught sigint, exiting.."
    exit 0
}


# print help/version info
fun_print_info () {
    echo "mp3me - parallel mp3 converter script"
    fun_print_ver
    echo "license: bsd 3-clause"
    echo "author: voidraven"
    fun_print_usage
    exit 0
}


# print usage info
fun_print_usage () {
    echo "-- usage: --------------------"
    echo "       mp3me ./musicdir          # just use defaults"
    echo "       mp3me -j 8 ./musicdir     # jobs (i.e. threads to start)"
    echo "       mp3me -b 192 ./musicdir   # bitrate - default is 320"
    echo "       mp3me -h                  # shows this help message"
    echo "       mp3me -v                  # show the version info"
}


# print version info
fun_print_ver () {
    echo "mp3me version: $VERSION"
}


# print error message
fun_error () {
    echo "mp3me - error detected"
    echo "$1"
    fun_print_usage
    exit 1
}


while getopts 'b:j:hvi:' OPT ; do
	case "$OPT" in
	b)	fun_get_bitrate "$OPTARG";;
	j)	fun_check_jobs "$OPTARG";;
	h)      fun_print_info;;
	v)      fun_print_ver && exit 0;;
	[?])	fun_error "invalid argument passed in by user";;
	esac
done

shift $SHIFT

DIR=$*
if [ -d "$DIR" ] ; then
    fun_run "$DIR"
else
   fun_error "directory not found: $DIR"
fi

exit 0