LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 03-08-2017, 11:05 AM   #1
breadbin
Member
 
Registered: Sep 2002
Location: Dublin, Ireland
Distribution: Linux Mint 17
Posts: 158

Rep: Reputation: 26
how to list bitrate of all my mp3's on command line?


I ripped all my CD's ages ago into 128Kbs MP3s . I used audiograbber on a Windows laptop at the time. I've since ripped some of my most listened to albums in 320kbps and now i'm seeing the benefits of flac. I am trying to find out which CDs need to be ripped again in 320 and Flac. All my ripped CDs are in their respective folders and then in a base folder called 'Music'.

I can probably use mp3tag, I use it with Wine and love it, but I would like to get to know the bash script better so I am looking for a way to write a script that will get the bitrate from the mp3 and echo it to the screen, which i can then echo to a file. Ideally I will run it once and it will recursively?? go into each folder and check for mp3s and add them to the list.

I have mediainfo installed and I am sure I can use that. It has a command line version and will display the bitrate but whether or not i can display just the filename or folder name and bitrate is another thing.

I would really only have to read one file in the folder and then I would know if the folder is 128kbps or 320.

Any suggestions? I am not averse to a bit of programming and I have used C and python in the past. A long time ago! I'm sure a bash script would be a hell of a lot handier to do.
 
Old 03-08-2017, 11:17 AM   #2
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,294
Blog Entries: 3

Rep: Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719
You can use find to recursively find any file named *.mp3 and then have that feed exiftool via a pipe. In turn, you can have awk extract and display the relevant fields from the resulting metadata.

Which field shown by exiftool do you want?

While you're re-ripping you might consider CD quality, which would be 44100 samples per second.
 
1 members found this post helpful.
Old 03-08-2017, 03:25 PM   #3
breadbin
Member
 
Registered: Sep 2002
Location: Dublin, Ireland
Distribution: Linux Mint 17
Posts: 158

Original Poster
Rep: Reputation: 26
thanks for the reply Turbocapitalist, I never heard of them tools so I have them all installed. Awk was already on there but the other 2 weren't. The field I'm looking for from exiftool is the 'Audio Bitrate' field. I can use the wildcard *.mp3 to display the bitrate with exiftool.

Code:
exiftool -AudioBitrate *.mp3
will give me what I am looking for but how would I do this for all folders?

Also I'm sure there is a way then to add this information to the folder name? That would be real handy

Edit:

Well I sort of figured it out. It is not perfect but it should do the trick. It is quite slow for whatever reason but hey. It is a complete new area for me. Here is the command if it helps anyone. Did alot of researching to find out how to use the find command properly. Them escapes and backslashes are painful.

Code:
find /home/ed/Music -iname "*.mp3" -exec exiftool '{}' - Album -AudioBitrate \;

Last edited by breadbin; 03-08-2017 at 04:20 PM.
 
1 members found this post helpful.
Old 03-08-2017, 04:10 PM   #4
Sefyir
Member
 
Registered: Mar 2015
Distribution: Linux Mint
Posts: 634

Rep: Reputation: 316Reputation: 316Reputation: 316Reputation: 316
Code:
find -type f -iname \*.mp3 -execdir exiftool -AudioBitrate {} \;
This will recursively search directories
My files did not seem to have exif data on them however, leading to a result of

Code:
======== Filename
======== Filename
======== Filename
======== Filename
======== Filename
======== Filename
======== Filename
======== Filename
======== Filename
======== Filename
Using ffprobe, I was able to get the information anyways.
Code:
while read i; do echo "$(ffprobe -i "$i" 2>&1 | egrep -o 'bitrate: [0-9]{1,3} .{4}' | cut -d' ' -f2-3)" "$i"; done < <(find . -type f \( -iname \*.ogg -o -iname \*.mp3 \))

171 kb/s Filename
170 kb/s Filename
169 kb/s Filename
171 kb/s Filename
170 kb/s Filename
169 kb/s Filename
171 kb/s Filename
170 kb/s Filename
170 kb/s Filename
171 kb/s Filename
I'm not a expert with grep so it may need to be adjusted.
 
1 members found this post helpful.
Old 03-08-2017, 04:23 PM   #5
breadbin
Member
 
Registered: Sep 2002
Location: Dublin, Ireland
Distribution: Linux Mint 17
Posts: 158

Original Poster
Rep: Reputation: 26
Sorry Sefyir, only seen your post just now. Think you posted as I was editing my last post. It looks interesting! I'll try that. The thing I thought up is really basic and I would love to use grep!
 
Old 03-08-2017, 05:48 PM   #6
Sefyir
Member
 
Registered: Mar 2015
Distribution: Linux Mint
Posts: 634

Rep: Reputation: 316Reputation: 316Reputation: 316Reputation: 316
Quote:
It looks interesting! I'll try that. The thing I thought up is really basic and I would love to use grep!
I've written up a small guide of what the one-liner does

Code:
while read i
 do 
    echo "$(ffprobe -i "$i" 2>&1 | egrep -o 'bitrate: [0-9]{1,3} .{4}' | cut -d' ' -f2-3)" "$i"
done < <(find . -type f \( -iname \*.ogg -o -iname \*.mp3 \))
This creates the while loop. for each line in the file do something. Each line is represented by variable i in this case
Code:
while read i; do something; done < file
This writes out to the screen the output of "$(commands)" and "$i". A good way of understanding $() is echo $(ls), this will echo out the current files in your directory in a single echo statement. $i represents the current line in the while loop.
Code:
echo "$(commands)" "$i"
This takes ffprobe and outputs all information about it to stdout. You may notice 2>&1. This means take the stderr and redirect it to stdout. This is critical since we will be piping the output! A lot of programs write their output to stdout but ffprobe is funny that way.
Code:
ffprobe -i "$i" 2>&1
This takes the stdin (input data) from ffprobe and matches a string starting with "bitrate: ", then matches any numbers between 0 to 9 between 1 to 3 times. So 1 24 and 932 counts, but 32523 or 2352 does not. Then it matches any character with "." exactly 4 times (so fasd and fsa9 is fine, dd is not).
It then pipes the output (with |) to cut
Code:
egrep -o 'bitrate: [0-9]{1,3} .{4}'
This sets the deliminator to whitespace so you can say. "I want fields 2 to 3. For example, if you had 3 blocks and assumed the space between each block was the deliminator, you can could say "I want blocks 2 through 3" by specifying field 2 through 3.
Code:
cut -d' ' -f2-3"
This is called "Process Substitution". Essentially, it writes the output of commands to a special FIFO or named pipe file so that it may be used by the while loop. More info -> https://en.wikipedia.org/wiki/Named_pipe
Code:
<(commands)
This takes the current directory referenced as ".", looks for only regular files (not FIFO's, directories, sockets, etc), then using \( \), makes a test then if either the file starts with .ogg or .mp3 (case insensitive) it will match
Code:
find . -type f \( -iname \*.ogg -o -iname \*.mp3 \)
 
1 members found this post helpful.
Old 03-08-2017, 06:44 PM   #7
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,119

Rep: Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120
Nice explanation @Sefyir.
Quote:
Originally Posted by breadbin View Post
I would really only have to read one file in the folder and then I would know if the folder is 128kbps or 320.
Makes sense - but
Quote:
Also I'm sure there is a way then to add this information to the folder name? That would be real handy
... this could get difficult - especially if the name contains special characters or spaces. Not impossible, but given your apparent shell skills, not trivial.
Another thought might be just to create a file either named or containing the bit rate in each directory. Simple redirect your output to that file - you might need to invoke basename though to resolve the directory name if using a simple "find . " command.
 
Old 03-09-2017, 01:50 AM   #8
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
just to throw in one more option (this is linux, right?):

Code:
mediainfo --Output="General;%OverallBitRate%" *mp3
https://sourceforge.net/projects/mediainfo/
 
2 members found this post helpful.
Old 03-09-2017, 05:28 AM   #9
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018Reputation: 5018
There's also the option of soxi from the sox suite. Sadly sox doesn't handle aac/mp4 format which limits its usefulness, but it's fine for mp3.
Code:
for file in *.mp3; do   [ "$( soxi -B "$file" )" = '128k' ]  && echo $file; done

Last edited by GazL; 03-09-2017 at 05:34 AM.
 
Old 03-09-2017, 06:37 AM   #10
breadbin
Member
 
Registered: Sep 2002
Location: Dublin, Ireland
Distribution: Linux Mint 17
Posts: 158

Original Poster
Rep: Reputation: 26
wow thanks everyone, this is why I love linux. there's so many ways to do everything and there's so many people waiting to help too. The command line is so powerful when you know what you're doing!

wow sefyir that's unreal. There's alot going on in that one liner! I'll try get my head round it.

Thanks ondoho for the mediainfo arguments. I didn't realise i could printf out specific headers but of course I shouldn't be surprised! I tried that command you posted and it just outputs a long number. I tried it on one folder and it was so random.

228848220557221879208113197145212806

I didn't know what it was doing so I tired it on a different folder and I get

320000320000320000320000320000320000320000320000320000320000320000320000

So at least now I know the previous folders MP3s are variable bitrate and the bitrate is outputted with the three trailing zeroes. Alot of trial and error!

Still wasn't great so I added the name of the album to the mediainfo output and this is eventually what I came up with. Not great but maybe a bit better. If i add all this to a file I can easily spot which albums need to be ripped again.

Code:
mediainfo --Output="General; %OverallBitRate% %CompleteName%\n" *mp3
Now I just have to add this line to the find command and I might be a bit happier

Last edited by breadbin; 03-09-2017 at 07:13 AM.
 
Old 03-09-2017, 06:44 AM   #11
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,294
Blog Entries: 3

Rep: Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719Reputation: 3719
Quote:
Originally Posted by breadbin View Post
Now I just have to add this line to the find command and I might be a bit happier
One tip regarding find is that there are two ways to invoke -exec

Code:
time find /home/ed/Music -type f \( -name '*.ogg' -o -name '*.mp3' \) -exec mediainfo --Output="General; %OverallBitRate% %CompleteName%\n" {} \;

time find /home/ed/Music -type f \( -name '*.ogg' -o -name '*.mp3' \) -exec mediainfo --Output="General; %OverallBitRate% %CompleteName%\n" {} +
The top line sends the file names one at a time to mediainfo. The bottom line sends them in larger batches. So you might find the + method much faster than the \; method for -exec.

The same applies to -execdir if you use that instead.
 
Old 03-09-2017, 12:02 PM   #12
breadbin
Member
 
Registered: Sep 2002
Location: Dublin, Ireland
Distribution: Linux Mint 17
Posts: 158

Original Poster
Rep: Reputation: 26
Quote:
Originally Posted by Turbocapitalist View Post
One tip regarding find is that there are two ways to invoke -exec

Code:
time find /home/ed/Music -type f \( -name '*.ogg' -o -name '*.mp3' \) -exec mediainfo --Output="General; %OverallBitRate% %CompleteName%\n" {} \;

time find /home/ed/Music -type f \( -name '*.ogg' -o -name '*.mp3' \) -exec mediainfo --Output="General; %OverallBitRate% %CompleteName%\n" {} +
The top line sends the file names one at a time to mediainfo. The bottom line sends them in larger batches. So you might find the + method much faster than the \; method for -exec.

The same applies to -execdir if you use that instead.
To be honest I didn't know what the \ was for. I assumed it was an escape character so the shell would be able to read the ;. It is good to know though. I timed the two commands and there is a huge difference. I tried just with a handful of folders and the first command "exec \;" took 13.9s and the second way "exec +" took only 3.07s! Not that it really matters but it is a massive time saving.
 
Old 03-09-2017, 01:04 PM   #13
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
mp3info

Code:
rateis="$(mp3info -r m -p "%r\n" "$script_dir"/"${newFile}")"
I do not have mp3info installed on slack so I cannot check my script code against the cli. But I'd say all you'd have to write is this. Cd into your mp3 dir or set pathname after arguments.
Code:
$mp3info -r m -p "%r/n" /path/to/mp3/*
Quote:
-r a|m|v
Report bit rate of Variable Bit Rate (VBR) files as one of the
following (See the section below entitled Bit Rates for more
information):
http://manpages.ubuntu.com/manpages/...mp3info.1.html

Last edited by BW-userx; 03-09-2017 at 01:05 PM.
 
Old 03-09-2017, 01:13 PM   #14
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
here is something that may help you make a list of all the files at whatever bit rate you want to find out, and store the names or yo could mod it and make it move the files to a location so you can have them in one place to work on.
Code:
#!/bin/bash


mp3_path="path to mp3s"

while read FILENAME
do


		f=$FILENAME
		path=${f%/*}
		xfile=${f##*/}
		title=${xfile%.*}
		ext=${xfile##*.}

rateis="$(mp3info -r m -p "%r\n" "${FILENAME}")"

if [[ "$rateis" -eq '320' ]] ; then

  printf "$rateis - $title\n"

  echo '$rateis - $FILENAME" >> /pathTOList/ListName


done < <(find "$mp3_path" -type f -name "*.mp3")
you could also just write a script to re sample or do whatever it is you want done to them while in the directory they are in. Leaving them all in the order you created and organized them.

Last edited by BW-userx; 03-09-2017 at 01:23 PM.
 
1 members found this post helpful.
Old 03-09-2017, 01:46 PM   #15
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Or use exiftool like this.
Code:
BitRate="`exiftool -AudioBitrate  "$FILENAME" -p '$AudioBitrate'`"

rateis=${BitRate% *}
that last bit of code strips off the kbs at the tail end leaving you with just the number to check.
LOOKUP: string manipulation BASH for more info on how to manipulate strings in BASH.

Last edited by BW-userx; 03-09-2017 at 01:53 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How do I find out the bitrate of an mp3? redhatman Linux - Newbie 4 11-22-2013 05:30 PM
Same mp3 but bitrate changes on different distro farmerdave Linux - Software 1 01-30-2011 02:19 AM
Reduce MP3 bitrate lumpfish Linux - Software 5 10-26-2009 05:17 AM
mp3 bitrate converter bird603568 Slackware 10 08-13-2006 10:56 PM
Covert Bitrate of MP3's DiZASTiX Linux - Software 5 05-19-2003 06:24 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 01:21 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration