I have a collection of music in .wav format, and would like to convert it to .aac/.mp4 using neroAacEnc.
How do I do this? I am using Arch Linux x86_64 and Xterm.
I have a collection of music in .wav format, and would like to convert it to .aac/.mp4 using neroAacEnc.
How do I do this? I am using Arch Linux x86_64 and Xterm.
Here is a quick one-liner that you can type in a terminal:
find . -name "*.wav" -print0 | while read -d $'\0' file; do neroAacEnc -2pass -q 1 -if "$file" -of "${file%wav}m4a"; done
You can also use ffmpeg, as @slm suggests,
find . -name "*.wav" -print0 | while read -d $'\0' file; do ffmpeg -i "$file" -c:a libfdk_aac -vbr 3 output.m4a "${file%wav}m4a"; done
I'm not sure how neroAacEnc compares to ffmpeg, but I know ffmpeg is advanced quite popular with many Linux users.
Explanation
find
is a program that returns paths to files that match a certain file property, in this case the file's name. If all you wanted to know was what .wav files are in subdirectories of your current path, you would do find . -name "*.wav"
. Normally this outputs each file on a new line. The -print0
makes it separate the matches with a null character instead. This allows for proper handling of filenames with spaces when we pass the output to the next commands.
The |
character is known as a pipe. It tells the shell to take the output of the command on the left and pass it as the input to the command on the right, in this case, the read
command within the while
loop.
The read
command is used to take the output of find
and assign it to a variable, "file". Normally this would assign values to "file" each word at a time, but the -d $'\0'$
causes the assignments to be delimited by the null character (matching how we delimited the files in find
by using the -print0
flag).
The while loops causes read
to iteratively assign values to "file" for each matching filename. The do
and done
are part of the standard bash syntax for a while loop:
while <something is true>; do
<run some commands>
done
In this case, our "run some command" is either ffmpeg
or neroAacEnc
. In each of the cases, the input file (i.e., $file
) is specified with the "file" variable that we assigned with read
, and the output file (i.e., ${file%wav}w4a
) is a manipulation of this variable that allows us to specify a different name for the output. Normally $file
or ${file}
would evaluate to the name of the file, say some song.wav. The %
says to cut off from the right of the variable any sequence matching the characters[1] to the right of the %
(i.e., "wav"). So ${file%wav}
would evaluate to some song., and then the "m4a" is there to be the new end of the filename: some song.m4a.
[1] I say "characters" here for simplicity. The sequence to the right of the %
could be a regular expression. For example, if we said ${file%w*v}
and the variable was some song.w1234v, it would also evaluate to some song..
ffmpeg
replaced with avconv
http://askubuntu.com/questions/432542/is-ffmpeg-missing-from-the-official-repositories-in-14-04
– phillipsk
Jan 03 '16 at 04:30
Not sure about the command line switches to neroAacEnc but something like this:
% cd <dir where .wav files are>
% find . -type f -name '*.wav' -exec sh -c '
orgfile="$0"
newfile="$(echo "$0" | sed 's/.wav/.aac/')"
neroAacEnc $orgfile $newfile
' {} \;
Or you could use ffmpeg to do the conversion (untested):
% cd <dir where .wav files are>
% find . -type f -name '*.wav' -exec sh -c '
orgfile="$0"
newfile="$(echo "$0" | sed 's/.wav/.aac/')"
ffmpeg -i $orgfile -ab 256 $newfile
' {} \;
#!/bin/bash
# myscript.bash
cd <dir where .wav files are>
find . -type f -name '*.wav' -exec sh -c '
orgfile="$0"
newfile="$(echo "$0" | sed 's/.wav/.aac/')"
neroAacEnc -2pass -q 1 -if $orgfile -of $newfile
' {} \;
After making the file (myscript.bash) make it executable chmod +x myscript.bash
, run it ./myscript.bash
, and you're done.
-FFmpeg and AAC Encoding Guide
NOTE: There are additional "recipes" for converting .wav to .aac and getting different qualities, characteristics, etc.
bash -x myscript.bash > debug.log 2>&1
and post the contents of debug.log to http://pastebin.com/ please.
– slm
Apr 21 '13 at 21:26
I'd also use ffmpeg. If you use libfaac, it only supports -aq and not -vbr or -ab:
for f in **/*.wav; do ffmpeg -i "$f" -c:a libfaac -aq 150 "${f%wav}m4a"; done
**
requires bash 4.0 or higher and shopt -s globstar
or zsh. You can show information about the result files with ffmpeg -i
.
According to http://ffmpeg.org/trac/ffmpeg/wiki/AACEncodingGuide, the native encoder (which was used if I didn't specify -c:a) is lower quality than libfaac, which is lower quality than libfdk_aac. --enable-libfdk_aac --enable-nonfree
(or brew install ffmpeg --with-fdk-aac
) includes support for libfdk_aac.
If you have 4 CPUs, this runs up to 4 processes in parallel:
find . -name \*.wav | parallel ffmpeg -i {} -c:a libfdk_aac -vbr 4.5 {.}.m4a
-vbr 0 is lowest, -vbr 5 is highest.
bash
orXterm
? Did you mean to include thebash
tag? – drs Apr 21 '13 at 20:40