Category Archives: Audio/Video

Rotate Android Videos in Ubuntu

It seems that if I don’t have my phone angled just so, it will invisibly rotate my video.  The rotation at the beginning of the film is what is used throughout, so if you think you have it horizontal and it turns out your first frame was vertical the entire film is then vertical.  And you won’t realize this until you attempt playback.

There are probably a million and one ways to fix the video rotation.  Unfortunately none of those are built into the phone.  I downloaded the video onto my laptop (running Ubuntu 16.04).

Most of the advice I found was to use a program called Avidemux.  I have used it in the past to change audio or video codices or move a video into a different container/wrapper (to mkv for example), and I have found it useful enough.  However, it would appear that Avidemux is no longer present in the usual Ubuntu repositories as both apt and the Ubuntu Software Center did not find it.

I poked around and found a pretty simple command line rotation solution using ffmpeg here.  I tried the version of the command in the response, but encountered an error:

[aac @ 0x6cf380] The encoder ‘aac’ is experimental but experimental codecs are not enabled, add ‘-strict -2’ if you want to use it.

Since my phone uses aac (apparently) I needed to add the -strict -2 in order to enable an experimental encoder.  So metal!

ffmpeg -i Desktop/VID_20161008_144216.mp4 -vf “transpose=2” -strict -2 Desktop/VID_20161008_144216_rotatecc.mp4

It worked great.  The response offers some other rotation options, but of course the man page for ffmpeg is extensive.

Share

ALAC Freed at Last (Not That It’ll Matter Much)

If you are an Apple user there is a very slim chance you have used ALAC files on your various components.

ALAC or Apple Lossless Audio Codec is a lossless audio codec (duh).  It compresses music down from their original size on a CD to about half of that size without any change in audio fidelity (the two files are mathematically equivalant); compare this to the mp3 (or ogg or aac or …) where the two files, though very different in size, are not the same sonically speaking (the conversion equation leaves a remainder which is thrown out and thus lost).  Audiosnobsphiles (myself included) seek out lossless compression formats over lost (or lossy) formats in pursuit of sound qualities nearer to the original master recordings.  Suffice it to say, it’s a niche market.

Apple developed their own lossless codec back in 2004 (or at least introduced it then).  FLAC (the Free Lossless Audio Codec) was introduced just a few years before in 2001, so perhaps this was part of Apple’s motivation.  In terms of math and in terms of sound there is no fundamental reason to select one of these two codecs over the other: they will sound identical if from the same source and can be interconverted indefinitely with no change to the music there contained.

Until recently, however, only one of these was freely available and open to the public (open source).  Just a few days ago Apple released the source code for ALAC under the Apache license.  (FLAC has open under the GNU GPL since it’s introduction.)  (This is about the best article currently available on the Apple announcement.)

For those of us who use software which is not owned by Apple we have still been able to play ALAC files (or convert them to FLAC) since about March of 2005 (thanks to two clever C programmers—read about that here).  (I wrote an article on converting ALAC and other formats to FLAC on Ubuntu.)

I have no ALAC currently in my collection.  Since ALAC was held by Apple and only functional on Apple software and devices by default it would have made a poor choice for my larger music collection since it has always been my intention to use that music on all of my devices.  I even went so far as to install Rockbox on my iPod Classic so that I could enjoy my FLAC files on that device.

I just don’t see this open-sourcing of ALAC as likely to effect many folks.  It may have some minor impact on the larger acceptance of FLAC if Apple continues to dis-support FLAC on their operating systems, software, and devices.  Then again this could well be a sign that Apple will finally begin supporting (or at least no longer actively dis-supporting) FLAC.  (Dream with me.)

The only thing I really dislike about ALAC is the lack of conformity and sense in the file extension.  Typically Apple uses the m4a extension.  This is because they put the file within the mp4 wrapper.  Unfortunately m4a is not an accepted file extension under the mp4 specifications.  It’s also possible that you will find an AAC file (remember that’s the extension they use for their lost compression format).   Keep in mind there is no programmatic relationship between AAC and ALAC; this is a bad practice and is to be avoided.

I suppose they could use either ALE or ALAC but I don’t think I’ve ever seen them.  So, yes, typically they use the unspecified (We made it up!) file extension mp4, and that wouldn’t be all that bad except that mp4 is a wrapper and you can put anything you’d like in it; like an AAC.  So really it’s anybody’s guess if you have a lossless or a lost file.

Of course this isn’t a criticism of the specification but rather merely a criticism of the deployment thereof.

Anyway, that’s the news.  Probably you won’t care.  If they have some clever political agenda for this maneuver it’s beyond me at present.  We shall see what the future holds.

Share

Burning in Banshee

I wanted to burn one of my playlists to a CD this morning, but I had some trouble figuring out how or where Banshee managed the burning.

I thought perhaps I could just locate a playlist and right-click on that playlist and choose Burn to CD or something equally obvious. Nope.

Right-clicking on a playlist in Banshee gives three options:

Rename
Export Playlist…
Delete Playlist…

I then thought maybe there would be an export option that was something like … as CD or maybe even … as ISO. No luck. Just three different playlist file options (m3u, pls, and xspf). I really didn’t want to have to export the playlist and use another application to burn from that file manually.

After some thrashing about and some mild cursing I found that if you right-click on any track (in a playlist or otherwise) you will find a related option:

Write CD…

Of course that will open Brasero with the one track ready to burn. Ok. That was enough for understanding but let’s agree that’s a little silly.

Here is the short version for those who are still scratching their heads. First you enter one of your playlists (by clicking on it). Then you select all of the tracks in that playlist. Finally you right-click on those selected tracks and send those to Brasero using the Write CD… option.

Have fun with that.

Share

Banshee, Its Library, and Importing Playlists

I have been preparing myself for the move from Rhythmbox to Banshee as the default media library application in future versions of Ubuntu.  I have encountered some interesting peculiarities and I thought I’d talk a bit about them here for your benefit.

One significant change from Rhythmbox to Banshee is the way playlists and the library itself are managed.  Rhythmbox, bless its little heart, uses a simple XML file for the library and another for all the playlists combined.  Banshee by contrast makes use of SQLite to house all this information.

XML is particularly easy to manipulate using a basic text editor.  I’m no database administrator, so it will take me some time to get up to speed in making the SQL queries and changes I might want to make.  There is one functionality I was able to work through, however, and that is migrating playlists.

(In the end I abandoned importing my playlists and am looking into alternative solutions.  Reason is Banshee eventually either emptied every playlist (what?) or shifted the playlist contents to a neighboring playlist (double-what?) so that I couldn’t trust Banshee to store a playlist in any useful way.)

In order to move playlists from Rhythmbox to Banshee I first exported the playlists individually (I exported them as .pls files).  That was simple enough.  Here is a quirk though.  Rhythmbox marks the file paths for playlists in the format [library root]/path/to/file.flac.  In my case, since the library was located in ~/Music and since Music contained a link to my server share with all the music the path looked something like this:

Music/[share]/path/to/file.flac

Banshee, using the same setup and for reasons I have yet to determine, decided that all of the file locations were not at ~/Music/[share]/ but instead were located at /media/[share]/ (the mount point to which the shortcut in Music was aimed).

If I imported the playlist(s) as exported Banshee would get all confused about file locations and paths and I would end up with a bunch of duplicate entries where one used the ~/Music designation and the other used the /media designation.  It was rampant and bizarre and spilled beyond the borders of the imported playlists to files never mentioned in any playlist (though it did not infect the entire library).  Very odd; very frustrating.

It did not end there though.  The playlists would eventually empty.  All of the tracks listed in the playlist would, over some seemingly random period or through some as yet undetermined set of events, become devoid of tracks until each playlist would contain zero tracks.  The files were still in the collection; however, the mis-pathed files or duplicate files would be purged from the library.

I finally manipulated the playlist files (the .pls files) themselves using GEdit.  (Any text editor with a find and replace feature will do nicely.)  I changed every occurrence of Music/ to /media/ and this made all the difference.  The path duplication problem was gone since all the file paths were pointing to the /media/ location. I am confident this fixes this issue.

I have no idea why Banshee parses the link into its destination path (parses the relative path into an absolute path?).  I can’t think of another case where an application changes /path/to/link/ into /destination/of/link all on its own.  This may be expected behavior for Banshee (and by all measures seems to be), but I don’t understand it at present.

At any rate, this article ought to help anyone trying to migrate from Rhythmbox to Banshee at least get their playlists migrated over, and it ought to help understand some unique behavior in this new default media application.

I suppose I should take a moment to mention why Rhythmbox saves playlists with Music/ as the path root.  It seems that when you save a playlist Rhythmbox changes the file paths from what is used in the playlist.xml file which stores all playlist data (in my case: file:///home/[username]/Music/[share]/…) into a home-directory relative path (in my case: Music/[share]/…).  My guess is this is done to make the playlist available to anyone in a similar situation as the user who created the playlist (.pls) file—that user would run the .pls file from their own home directory and all would be well enough.

Again, you may or may not find this useful.  For my part I know I’d rather not have to rediscover it.

Oh there is one more important thing about importing playlists I should mention.  When you import the playlist it will be ordered by something-of-which-I-remain-uncertain.  It’s probably ordered by a field I don’t view.  Anyway, to get the playlist to sort by the playlist order (that is to say the order you created for that playlist) thrice click on any of the view column headers to first sort by that view, then reverse sort by that view, then finally to turn off view-by-column sorting for the playlist.

I created some related posts on the Ubuntu forums (here and here) as I was working through these matters.

Let me know if you have anything to add.

Happy hunting.

Share

A New Script for Skipping Tracks

A while back I wrote a simple script for skipping tracks (and a couple of other things) for Rhythmbox.  Now that Ubuntu is moving to Banshee as their default media library application I have tossed together a new script for use with Banshee.

The trouble with Rhythmbox was getting the system to understand, when attached remotely, which monitor contained Rhythmbox.  This was dealt with by making use of the $DISPLAY variable.  Banshee makes this problem a bit more difficult.  Banshee uses dbus and dbus is more difficult to guess at and more difficult to inquire.  A little research has given me a workable bit of code that gets me there.  (I am still researching this code either for better or safer or more elegant solutions.)

I have built in some logic to make the script handle situations where the user inputs a command (argument) that is not necessarily appropriate to the current state of Banshee. It should handle most of what you might (accidentally?) throw at it. I still want to give it some parsing abilities so that when it displays the currently playing information it’s more user friendly. I’ll just add that here when I get that built.

I have built a code section (in two parts) for seeking (forward and reverse). The problem is that in my version of Ubuntu there is a dependency bug (in dbus) so the seeking won’t work for Banshee from the command line. I have included it here for folks for whom this bug does not apply. Feel free to comment on your operating system and Banshee version if my code works for you.

To get the seek code working simply paste the two parts into the two places in the script where I have placed markers. (You may optionally uncomment (remove the #’s) from the two lines in the help section near the end of the script, but it’s not required for the seek code to function. If you are running Ubuntu 10.04 like me you won’t need the seek code unless you have dealt with the dbus bug yourself.)

##
#!/bin/bash
# Banshee Control Script
# by JamesIsIn from JamesIsIn.com
# Do something nice today.

# First tell the system how to find the current running version of Banshee if you are running this script remotely.  If you only use the script locally you can comment out this export line.
# This command reports a host of permissions errors and doesn't need to display its output to the user so we divert STDERR to null.

export $(strings /proc/*/environ 2> /dev/null | grep DBUS_SESSION | tail -1)


# Now we can manipulate Banshee.
# Grab that variable...

argument=$1

## The first part of the seek code belongs here.



##



# ... and shake it!

   if [ "$argument" = "p" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
         if [ "$pbstat" = "paused" ]; then
            printme="I am resuming playback."
            banshact="banshee --play"
            banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
         elif [ "$pbstat" = "idle" ]; then
            printme="I am beginning playback."
            banshact="banshee --play"
            banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
         elif [ "$pbstat" = "playing" ]; then
            printme="I am pausing playback."
            banshact="banshee --pause"
         else
            printme="Is Banshee even on?  I'm confused." 
         fi

   elif [ "$argument" = "play" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
      if [ "$pbstat" = "idle" ]; then
         printme="I am beginning playback."
         banshact="banshee --play"
         banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
      elif [ "$pbstat" = "paused" ]; then
         printme="I am resuming playback."
         banshact="banshee --play"
         banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
      elif [ "$pbstat" = "playing" ]; then
         printme="Banshee is already playing."
      else
         printme="Is Banshee even on?  I'm confused."
      fi

   elif [ "$argument" = "pause" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
      if [ "$pbstat" = "playing" ]; then
         printme="I am pausing playback."
         banshact="banshee --pause"
      elif [ "$pbstat" = "paused" ]; then
         printme="Banshee is paused.  Use p or play to resume playback."
      elif [ "$pbstat" = "idle" ]; then
         printme="Banshee is stopped.  Use play to resume playback."
      else
         printme="Is Banshee even on?  I'm confused."
      fi

   elif [ "$argument" = "stop" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
      if [ "$pbstat" = "playing" ]; then
         printme="I am stopping playback."
         banshact="banshee --stop"
         
      elif [ "$pbstat" = "paused" ]; then
         printme="Banshee was paused and I have now stopped it."
         banshact="banshee --stop"
         
      elif [ "$pbstat" = "idle" ]; then
         printme="Banshee is already stopped."
      else
         printme="Is Banshee even on?  I'm confused."
      fi

   elif [ "$argument" = "n" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
      if [ "$pbstat" = "playing" ]; then
         printme="I am skipping to the next track."
         banshact="banshee --next"
         banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
      elif [ "$pbstat" = "paused" ]; then
         printme="Banshee is paused.  Use p or play to resume playback."
      elif [ "$pbstat" = "idle" ]; then
         printme="Banshee is stopped.  Use play to resume playback."
      else
         printme="Is Banshee even on?  I'm confused."
      fi
   

   elif [ "$argument" = "r" ]; then
      printme="I am going to rewind now.  Doing this early enough will supposedly go to the previous track."
      banshact="banshee --previous"
      banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
      
# I should be able to prettify this and account for null variables.
# what I want: You are listeing to song by so-and-so (x of y) from album [] [year] ti:me.

   elif [ "$argument" = "s" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
      if [ "$pbstat" = "playing" ]; then
         printme="This is what is currently playing:"
         banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
      elif [ "$pbstat" = "paused" ]; then
         printme="Banshee is currently paused here:"
         banshow="banshee --query-title --query-artist --query-track-number --query-track-count --query-album --query-disc --query-year --query-duration"
      elif [ "$pbstat" = "idle" ]; then
         printme="Banshee is currently stopped.  Use play to resume playback."
      else
         printme="Is Banshee even on?  I'm confused."
      fi

## The second part of the seek code belongs here.



##

   elif [ "$argument" = "c" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
      printme="Banshee is currently $pbstat."

   else
      printf "\nI'm sorry.  I only understand the following arguments:\n\n"
      printf "  p     -- attempt to toggle between play and pause\n"
      printf "  r     -- rewind to beginning or skip reverse\n"
      printf "  n     -- skip to next track\n"
      printf "  s     -- show what's playing\n"
      printf "  play  -- play\n"
      printf "  pause -- pause\n"
      printf "  stop  -- stop\n"
      printf "  c     -- display the current state of Banshee\n\n"
# You may want to uncomment the next two lines if you are using the seek code.
#      printf "  ff    -- fast forward (include seconds as ff 10)"
#      printf "  rr    -- rewind (include seconds as rr 5)"
      printf "Note that the arguments do not use a hyphen.  Please try again.\n\n"
      exit
   fi


$banshact
echo
echo $printme
echo
$banshow
echo


exit

##

As you can see, I have given play/pause toggling (where banshee itself doesn’t really have it) through the clever use of an if-loop (I’ll just pat myself on the back, ok?). Also it tells you what is playing anytime you start playing something (new or resumed).

Point of interest, there is bit of code that was not working in the script:

banshee –play; banshee –query-title –query-artist –query-track-number –query-track-count –query-album –query-disc –query-year –query-duration

Thing is if you paste this into a terminal it works perfectly. The problem is that semi-colon. On the command line it’s just fine, but in the script there must be a space after the --play or the shell will interpret the argument as literally --play; and it won’t work.

So the basic usage of the script is in this format:

Bs p

I placed this script in /usr/local/bin on the hi-fi machine. I called it merely Bs. That way the script is available to all users on that machine and is easy to call up from the terminal.

Be sure to make the file executable:

sudo chmod a+x /usr/local/bin/Bs

For those who would like to add the seek functionality, here it is. You can always test it on your system to see if it works and remove it (or comment it out) if it doesn’t.

##
#!/bin/bash
# Seek functionality for Banshee Control Script
# by JamesIsIn from JamesIsIn.com
# Do something nice today.

## This is the first part of the seek code.

seekseconds=$2
roundseek=$( printf "%0.f\n" $seekseconds )

##


## This is the second part of the seek code.

   elif [ "$argument" = "ff" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
         if [[ $roundseek =~ ^[0-9]+$ ]]; then
            currentlocation=`banshee --query-position`
            currloc=${currentlocation#* }
            roundloc=$( printf "%0.f\n" $currloc )
            seekchange=$(( roundloc + roundseek ))
               if [ "$pbstat" = "playing" ]; then
                  printme="I am advancing playback by $roundseek seconds."
                  banshact="banshee --set-position=$seekchange"
                  banshow=""
               elif [ "$pbstat" = "paused" ]; then
                  printme="Banshee is paused but I have advanced the pause location by $roundseek seconds."
                  banshact="banshee --set-position=$seekchange"
                  banshow=""
               elif [ "$pbstat" = "idle" ]; then
                  printme="Banshee is neither playing nor paused and thus I am not able to advance anything"
                  banshact=""
                  banshow=""
               else
                  printme="Is Banshee even on?  I'm confused."
                  banshact=""
                  banshow=""
               fi
         else
            printme="When using ff you must enter seconds in the format \"Bs ff 5\" in order for me to process your request."
            banshact=""
            banshow=""
         fi   
      
   elif [ "$argument" = "rr" ]; then
      playbackstatus=`banshee --query-current-state`
      pbstat=${playbackstatus#* }
         if [[ $roundseek =~ ^[0-9]+$ ]]; then
            currentlocation=`banshee --query-position`
            currloc=${currentlocation#* }
            roundloc=$( printf "%0.f\n" $currloc )
            seekchange=$(( roundloc - roundseek ))
               if [ "$pbstat" = "playing" ]; then
                  printme="I am rewinding playback by $roundseek seconds."
                  banshact="banshee --set-position=$seekchange"
                  banshow=""
               elif [ "$pbstat" = "paused" ]; then
                  printme="Banshee is paused but I have rewound the pause location by $roundseek seconds."
                  banshact="banshee --set-position=$seekchange"
                  banshow=""
               elif [ "$pbstat" = "idle" ]; then
                  printme="Banshee is neither playing nor paused and thus I am not able to rewind anything"
                  banshact=""
                  banshow=""
               else
                  printme="Is Banshee even on?  I'm confused."
                  banshact=""
                  banshow=""
               fi
         else
            printme="When using rr you must enter whole-numbered seconds in the format \"Bs rr 5\" in order for me to process your request."
            banshact=""
            banshow=""
         fi



##

Have fun with this one too. Suggestions are welcome.

Share

OGG Will Ninja Your MP3 and Make You Happy

I’d prefer that everyone in the world used FLAC, but since there is still an inexplicable desire to use lost compression formats to save storage space I am going to recommend that you at least upgrade to the OGG Vorbis format.

PlayOgg

This lost format uses a better compression algorithm than does MP3 (or AAC or WMA &c).   This means that for a comparable bit rate you will get a better sounding reproduction and likely a slightly smaller file.

No, iTunes does not natively support either FLAC or Ogg.  However, nearly every other media player out there does (from VLC to Windows Media Player with a plugin to Winamp).  If you are using a Mac iTunes can be made to play nicely with FLAC and Ogg (see this post for information about this lamentable exclusion on the part of Apple and a workaround for Mac users), but again I would recommend using some of the other players (a nice list is found on the workaround article I linked above).

Seriously though, buy some decent storage and use FLAC.  It’s lossless so you are not making a compromise as you are with each of the lost formats.

Don’t cry to me because you can’t fit six months worth of music on your personal music player.   We used to be content carrying around three or four tapes at a time (while walking up hill both ways in the snow).  Even a small player (say 8 GB) will hold more than that (8 GB could hold about 20 albums as FLAC).

I have a 60 GB iPod (running RockBox so I can play FLAC’s; kiss my ass, Apple) and there is enough music on there (though less than 10% of my collection) that I don’t see repeated tracks after months of casual listening on the bus.

If you don’t feel up to making the switch to lossless audio and want to stick with lost formats, OGG will still provide better performance than an MP3.

Be good to your ears.  They love you long time.

Share

Script for Skipping Tracks

I use Rhythmbox to play music on my hi-fi system.  There is a command line element for Rhythmbox called rhythmbox-client.  This element can be used to initiate a series of commands in Rhythmbox.  The problem is that these commands end up being a bit longish if you are attached to that machine via ssh.  Here is an example:

DISPLAY=:0.0 rhythmbox-client –play-pause

That’s a lot of typing especially when you are attached via ssh from your Android phone.  It was just too tedious to type all that out on that on-screen keyboard.  So I wrote a script that would manage the arguments I felt were most important.

##
#!/bin/bash
# by JamesIsIn from JamesIsIn.com
# Do something nice today.


   if [ "$1" = "n" ]; then
      argument="--next --print-playing"
      printf "\nI am skipping to the next track:\n\n"
   elif [ "$1" = "p" ]; then
      argument="--play-pause"
      printf "\nI am toggling between play and pause.\n\n"
   elif [ "$1" = "s" ]; then
      argument="--print-playing"
      printf "\nThis is what is currently playing:\n\n"
#   if [ "$1" = "q" ]; then
#      $argument="--enqueue"
   else [ argument = "" ]; 
      printf "\nI'm sorry.  I only understand the following commands:\n\n"
      printf "p (play/pause)\n\n"
      printf "s (show what's playing)\n\n"
      printf "n (skip to next track)\n\n"
      printf "Please try again.\n\n"
      exit
      # I could add --enqueue but I have to figure out to make it work
   fi


# assuming DISPLAY does not matter for local runs (though this is for a single monitor configuration)

DISPLAY=:0.0 rhythmbox-client $argument
echo


exit

##

The use of DISPLAY is required so that rhythmbox-client knows on which monitor Rhythmbox is present.  The configuration above is for a single monitor arrangement.  You’re on your own to figure out what you need in there if you have a different monitor configuration.

So, using my script, if you wanted to issue the same command I mentioned above you would merely type:

Rb p

(Now I just need to streamline the ssh command and this whole procedure will be much easier and thereby more impressive.)

I placed this script in /usr/local/bin on the hi-fi machine. I called it merely Rb. That way the script is available to all users on that machine. Be sure to make the file executable:

sudo chmod a+x /usr/local/bin/Rb

(Since I use my server as a proper server now I moved my script to the share: /media/[share]/Rb so that it would be available across the network.)

Have fun with that.

Share

Conquer Giant APE and Giant FLAC

I have already written posts on splitting and converting from either album-length APE files or album-length FLAC files into track-length FLAC files.

(My post on converting APE files; my post on splitting APE files; my post on splitting FLAC files. You will want to go over these other articles if you have not done any of this before as there are some dependencies which you will not likely have installed.)

That was rather satisfying, but I then found that I would locate entire discographies where every album was a single APE or FLAC.  I did not enjoy the prospect of running each command on each pair of files.

That’s why scripting languages exist.  It’s a good thing I bought that BASH book.

Anyway, this script is designed to recursively locate APE, FLAC, and CUE files under a user-supplied root directory; then it runs shntool and cuetag on each APE/FLAC and CUE pair.  (You can read my previous posts linked above for more details about how these two commands work.)

It even cleans up after itself.  Since it deletes not only the temporary files it creates but also all the APE, FLAC, and CUE files it uses, you will want to pay close attention when the script tells you it is about to clean up all those files.  If you tell it to proceed (by hitting ENTER) without checking its work all those files will be deleted.  As such you should work from copies and you should check that it did what you wanted it to do before hitting ENTER when it asks about cleaning up all files.

Feel free to suggest any improvements.  I hope you find that it works well and improves your lives.

One important thing to note is that it is not an intelligent script.  It cannot determine for you whether a given APE or FLAC file is actually album length.  It assumes that you are offering it a folder (with or without sub-folders) which contains only album-length APE or album-length FLAC files with an accompanying CUE file (one matching pair per containing folder).

Sometimes a cue file will be formatted incorrectly or have some other issue.  Sometimes they can be fixed by opening them in a text editor.  Probably they can always be fixed in a text editor, but it might be difficult to determine what’s wrong with the CUE file.  If a CUE files has issues you will see errors on the command line (if you are staring at your monitor) and the album-length file will not be split/tagged.  You’ll have to work on that pair separately, but since you are working from copies it won’t matter if they get deleted.

If you throw something unusual at it, it’s hard to imagine how it might behave.  It’s likely not dangerous but you should always work from copies and preserve the originals until you are satisfied.

##
#!/bin/bash
# covert APE/FLAC albums to FLAC tracks recursively
# by JamesIsIn from JamesIsIn.com
# Do something nice today.

## gather information

# obtain directory in which to work

printf "\nHello.\n\n"
read -e -p "Please provide the root folder under which I will work recursively: "
if [ -d "$REPLY" ]; then
printf "\nI have confirmed this is a directory.\n\n"
directory="$REPLY"
else
printf "\nI cannot confirm this is a directory.\n\n"
echo "$REPLY"
exit 1
fi

# number, performer, and track names

printf "There are two formatting options for file naming (assuming the cue contains correct information):\n\n"
printf "01 – Track Name.flac\n"
printf "01 – Performer Name – Track Name.flac.\n\n"
read -p "Do you want to include the performer name in the file names (this is only recommended for multiple-artist albums)? [Y or N]: "
if [ "$REPLY" = "Y" ]; then
printf "\nOk, I'll include performer names: 01 – Performer Name – Track Name.flac\n\n"
trackname="%n – %p – %t"
elif [ "$REPLY" = "y" ]; then
printf "\nOk, I'll include performer names: 01 – Performer Name – Track Name.flac\n\n"
trackname="%n – %p – %t"
else [ "$REPLY" = "[Nn]" ];
printf "\nOk, I won't include performer names: 01 – Track Name.flac\n\n"
trackname="%n – %t"
fi

printf "\n\nLet's get to work.\n\n\n"

## do the work

# parse files into respective arrays recursively

find "$directory" -type f -name \*.[Aa][Pp][Ee] -o -name \*.[Ff][Ll][Aa][Cc] > /tmp/whyme

declare -a albumfind
let i=0
while read albumline; do
albumfind[$i]=$albumline
((i++))
done < /tmp/whyme

find "$directory" -type f -name \*.[Cc][Uu][Ee] > /tmp/whyme2

declare -a cuefind
let i=0
while read cueline; do
cuefind[$i]=$cueline
((i++))
done < /tmp/whyme2

# follow array counts

printf "\n\nCounts are as follows. There are "${#albumfind[@]}" albums and "${#cuefind[@]}" cues. Your albums ought to equal your cues. If these counts are not as expected, please inspect the contents of the folder you provided before proceding or re-run the script and select a different folder.\n\n"
read -p "Press <ENTER> to coninue. "

# split apes and flacs; hide album files

for (( i=0 ; i < ${#albumfind[@]} ; i++ )) ; do
# path is cue iteration less file name
albumfolder="${cuefind[i]%/*.*}"
shnsplit -d "$albumfolder" -o flac -f "${cuefind[i]}" -t "$trackname" "${albumfind[i]}" ;
mv "${albumfind[i]}" "${albumfind[i]}".hideme ;
done

# remove 00 files

find "$directory" -type f -name 00\*.[Aa][Pp][Ee] -o -name 00\*.[Ff][Ll][Aa][Cc] > /tmp/whyme3

declare -a deadfiles
let i=0
while read deadline; do
deadfiles[$i]=$deadline
((i++))
done < /tmp/whyme3

for (( i=0 ; i < ${#deadfiles[@]} ; i++ )) ; do
mv "${deadfiles[i]}" "${deadfiles[i]}".hideme ;
done

# tag files

for (( i=0 ; i < ${#cuefind[@]} ; i++ )) ; do
# path is cue iteration less file name
albumfolder="${cuefind[i]%/*.*}"
cuetag "${cuefind[i]}" "$albumfolder"\/*.flac
mv "${cuefind[i]}" "${cuefind[i]}".hideme ;
done

## clean-up

printf "\n\nI have completed all operations to the best of my ability.\nI will now clean up all files.\n\nPlease ensure you are satisfied with the state of things before you continue."
printf "\n\nPlease note: I am about to delete all the album-length files I believe I have used."
read -p "Press <ENTER> to coninue (Ctrl-c will abort clean-up). "

# remove temp files, hideme files, and unset all variables

find "$directory" -type f -name *.hideme > /tmp/whyme4

declare -a hidemes
let i=0
while read hidelines; do
hidemes[$i]=$hidelines
((i++))
done < /tmp/whyme4

for (( i=0 ; i < ${#hidemes[@]} ; i++ )) ; do
rm "${hidemes[i]}" ;
done

rm /tmp/whyme*
unset

exit

##

Have fun with that.

Share

Little Apes to FLAC Files

You may come across individual APE files which you would like to convert to FLAC files.  This can be especially useful if you have an album FLAC and an accompanying CUE file and you are having trouble getting the APE to burn correctly.

There is a fairly simple tool for dealing with this conversion.  As fortune would have it this tool will also manage conversions to and from ALAC, SHN, TTN, and WAVE files.  How can they pack so much fun into such a small package?  Now it’ll be that much easier to clean your collection up and keep everything tidy: flacflacflac.

Ok, so you’ll need—and if you’ve been following along here you already have—the MAC (Monkey Audio Codec).

Next you’ll need to get something called apeinfo.   There exist both 32 and 64 bit versions so be sure you get the proper version for whichever Ubuntu you are running.  You will find them here.  You will want to change the name of the file you download to merely apeinfo (so remove the _32 or _64) or it won’t work when called up by the next tool.

The next tool being known as convtoflac.  You may find that here.

Download both of your files and they all gets stuck into /usr/local/bin.

I downloaded each of these to my desktop and then used sudo to copy them into /usr/local/bin.  Make certain you have given them execute permissions (set the execute bit).  By storing them in /usr/local/bin I am sure they are in my command path (basically those places your system looks when you type a command) and they are ready to use.  Here is the command you need to move the apeinfo file from the Desktop to /usr/local/bin:

sudo mv /home/[usename]/Desktop/apeinfo /usr/local/bin/apeinfo

You can copy and paste that line and make the necessary substitutions for your system, download location, and specific file.

Once you have these installed correctly you are ready to use the tools to make conversions.  I have written a small simple script for making all of this work together.  If you make my script executable and place it  in your /usr/local/bin you can merely call the whole thing up by typing the name of the command (whatever you decide to name your version of my script) in your terminal.  I named my script Ape2Flac.sh.

##
#!/bin/bash
# by JamesIsIn from JamesIsIn.com
# Do something nice today.

#  Ape2Flac.sh

#  also requires apeinfo and convtoflac
#  http://jamesisin.com/a_high-tech_blech/?p=1335

for i in *.ape
do convtoflac.sh "$i"
done

##

This method will preserve any existing tags.

To fire it up, navigate into the folder in which you have the APE files and run my script (by typing its name into the command line).  It’s that easy.

See, nothing to fear from the command line.

Happy hunting.

Share

Make a Big APE into Several Small, Tagged FLAC Files

You may recall with great excitement my post on splitting and tagging album length FLAC files into track length FLAC files.  It may come to pass that you find yourself staring at an album length APE file.

What?  What the hell is an APE file?

In short, some folks decided “hey, what the world needs is another media player and it’s very own lossless codec”.  In their defense, MediaMonkey looks like a pretty cool application (say “iTunes killer”), and it does support FLAC and OGG so I don’t dispise it.  Nonetheless, it is my advice to avoid specialized and proprietary codices wherever possible.  Unfortunately Monkeys, this means no APE files.

As fate would have it, if you are already set up to split and tag an album FLAC, you are nearly ready to do the same for an album APE.  You just need the MAC (monkey audio codec).

You have two choices.  This codec isn’t part of what Canonical normally provides, so you can either add a repository which includes it or you can download the codec directly.  I tend to prefer adding a repository, but the codec can be downloaded in this package.

http://members.iinet.net.au/~aidanjm/mac-3.99-u4_b3-1_i386.deb

(If you choose to download the .deb package, double-clicking on it once you have downloaded it and your system will run the installation.)

For those of you, like me, who prefer to add a repository, the Eudoxos repositories include MAC, so we can add this one.

http://ppa.launchpad.net/eudoxos/ubuntu yourubuntuversion main

Once you have added that repository Monkey Audio will appear in Synaptic.  To install the Monkey Shite open Synaptic and look for Monkey Audio. (Please note that newer editions of this repository no longer carry the MAC, yet I am using the repo for 8.10 in my 10.04 machine successfully.)

Now let’s get to the meat of it.  I have grown lazy and tend to rename my FLAC, APE, and cue files to the letter a, so my commands look like this:

shnsplit -o flac -f a.cue -t “%n – %t” a.ape

cuetag a.cue *.flac

(Please note there may be a copy and paste problem here.  The quotation marks are different.  So when you grab the part -t “%n – %t” you will have to replace the quotation marks by typing them afresh.  Failure to do so will yield an error—shnsplit: error: need exactly one file to process.  Alternatively you may copy from the  code section below.)

[CODE=”BASH”]##

# Here are the two commands you will need

shnsplit -o flac -f a.cue -t “%n – %t” a.ape

# Note: you may substitute “%n – %a – %t” if you want artist names in your file names

# now you may move or remove the album APE]

cuetag a.cue *.flac

##[/CODE]

Unlike splitting a FLAC file into smaller flac files, you don’t necessarily have to send the album length APE to the trash (or remove it’s file extension) between performing these two commands.  But you can.

If this isn’t strait forward, you may want to read through my previous post to sort out the details of the conversion process and then come to this post for the APE specific information.

Thanks to this post for some information.

Share