Update June 7, 2007: this script is obsolete. Read about the updated version or visit the new project page on Google Code.

Despite my recent switch to Ubuntu, I still own a video iPod 5G, and I have been searching for a nice replacement for Handbrake and iSquint. I’ve tried every available script and program that purports to encode iPod-compatible video (including Handbrake under Linux), but each falls short on one of several counts:

So I wrote my own: podencoder

Prerequisites:

Please don’t ask me for help installing these prerequisites. Consider it a character-building exercise.

You can run the script from the command line:

$ podencoder # interactively select tracks from default DVD device
$ podencoder -t longest # auto-select longest track and encode it
$ podencoder ./BBSDOC/ # encode from a pre-ripped directory instead
$ podencoder -t "2,3,4" ./BBSDOC/ # encode multiple tracks
$ podencoder -t "2,3,4,5" -i 7 -n "WEEDS1%i" \
     -o ~/Videos/ipod/Weeds/ ./WEEDS_SEASON_1_DISC_2/
   # encode tracks 2-5 from a DVD directory,
   # store them in ~/Videos/ipod/Weeds/
   # and name them WEEDS107.mp4, WEEDS108.mp4,
   # WEEDS109.mp4, and WEEDS110.mp4 respectively

You can set defaults in the configuration file (~/.podencoderrc) like a default DVD device (mine is /dev/scd0), a default output directory, and a default scratch directory.

outputdir=/home/mark/Videos/ipod
scratchdir=/home/tmp
device=/dev/scd0

I use /home/tmp as a scratch directory for video encoding because my /tmp directory is on a small partition. If you’re encoding from a DVD or DVD directory, podencoder dumps the entire track to disk before encoding it, which can require up to 8 GB of free space.

On the other hand, if you dislike the command line, you can double-click podencoder or set up a shortcut in your favorite window manager or desktop environment, and it will graphically prompt you to select tracks from the default DVD device (screenshot — note that it automatically selects the longest track for you). Or you can put a shortcut to it in your Nautilus scripts directory, like this:

$ ln -s /usr/local/bin/podencoder ~/.gnome2/nautilus-scripts/"Encode for iPod"

Then you can right-click a mounted DVD, or a DVD directory, or even a random video file, and select “Scripts → Encode for iPod”.

This is my first shell script longer than 3 lines, so please take this opportunity to berate me for my newbie shell scripting mistakes.

Update: script updated with some feedback from the comments. Now uses /bin/sh for greater portability, and a new test to autodetect console-vs-graphical environment (thanks Bob).

Update June 7, 2007: this script is obsolete. Read about the updated version.

§

Fifteen comments here (latest comments)

  1. Just a quick question – why bash, and not sh?

    — Anonymous #

  2. No idea, really. Would it work in sh? As I said, this is my first non-trivial shell script (in any shell), so I really have no idea which of the things I’ve learned so far are Bash-specific.

    — Mark #

  3. Batch encode video for iPod under Linux | SYP (pingback)
  4. First shell script, and your catching signals? Impressive. Heh.

    The Bourne Shell is more portable than Bash. You can check for Bash specific extensions using the application ‘checkbashisms’ that should be in the Ubuntu repositories. If you switch to the Bourne Shell you should start your script with ‘#!/bin/sh -e’ as well.

    Oh, very trivial and just a personal preference, but some of your lines quite long – why not limit them to 79 characters + newline using the ‘\’ character to escape newlines. It makes it much easier to read your code on a small terminal.

    Weird also, you use lower case variable names – I have always been used to shell script variables to be ALL_UPPER_CASE. But I must admit, it doesn’t look half bad like this.

    — Noah Slater #

  5. A few double-brackets and double-equals, and a let statement, and it runs under /bin/sh. Thanks.

    — Mark #

  6. See http://www.shelldorado.com/goodcoding/tempfiles.html for a useful example of how to use the “program termination” pseudo-signal to clean up temporary files. In this relatively simple script, it may not be necessary, but nonetheless it is a good technique to know.

    — Isaac Lin #

  7. mokshore » Blog Archive » links for 2006-08-31 (pingback)
  8. Hmm. This GUI-vs-console thing is pissing me off. I was sitting at my computer last night and wanted to test some changes, and the GUI dialogs kept coming up, and currently the only way to turn them off is to change the configuration file. But doing that means that my right-click-as-Nautilus-script thing no longer shows the GUI dialogs (or any progress whatsoever, since stdout isn’t displayed anywhere). That’s stupid design. The question is, what’s a better design?

    - An additional command-line flag?
    - A better magical test to determine whether the program is running in what I would call a graphical context? (My current magical test is to check for the existence of the DISPLAY variable, which seemed like a clever hack considering I had no idea what I was doing. But it turns out that it doesn’t actually solve the right problem, because I want to be able to sit at my computer and type “podencoder” in a terminal window and get output in the terminal window, or right-click in Nautilus and select something from the Scripts menu and get graphical progress dialogs.)
    - Fork the script into two separate scripts, one for GUI, one for console, and have them share code by sourcing common files?
    - Make a symlink called “guipodencoder” or “gpodencoder” or something, and key off `basename $0`?

    @Noah: yeah, I figured out traps on my first script. Zenity has an annoying habit of sending SIGHUP to the parent process when you click Cancel, which resulted in the script dying but mplayer/ffmpeg processes continuing. I spent a lot of time testing this script and canceling it halfway, and I finally realized (when both CPUs spiked to 100% and my computer slowed to a crawl) that the background progresses were still running. This led to a whole detour of learning about traps and signals and $! and wait and — for reasons not worth explaining — variable scoping. Bleah.

    More generally, I am good at acquiring deep technical knowledge quickly. I am much more interested in feedback like “why not change 3 lines and use sh?” and “scripts should hard-wrap at 79 columns.” The aesthetics of shell scripting. Example: I think the script has pretty good command-line usage notes and unsurprising command-line flags. They work the way you would expect a shell script to work. Then how do I solve my GUI-vs-console problem? Any of the solutions (and probably many others) could be made to work. But which one *feels* better? I don’t know yet.

    — Mark #

  9. Mark, have you tried testing for the $TERM variable? On Debian testing nautillus sets it to “dumb” when run from a gui, and the name of your terminal when run from the CLI. A possible avenue for exploration.

    — Noah Slater #

  10. I think the $TERM variable differs a lot between the desktop systems/file managers.

    Application links to scripts in KDE have $TERM=linux ?!?

    — Filip #

  11. You can use the tty program to detect whether the script is connected to a terminal or not. If it is being run from Nautilus then there will be no terminal connected.

    Short test script:

    #!/bin/bash

    tty –quiet
    if [ "$?" == 0 ]; then
      echo “Is a terminal” >> afile
    else
      echo “Not a terminal” >> afile
    fi

    — Bob Atkey #

  12. I think that the answer is keeping strict in line with KISS principle — make two scripts. One strictly running from command line (or xterm), which could be well tested as such. The other would be just GUI candy around that script. In this way you can be sure you can separate and test real processing part in xterm.

    And by the way, I have no idea, why in the world you haven’t wrote all this in Python (which you know much better than shell apparently, and which has good GUI extensions — at least for KDE, but I guess that Gnome-Python exists as well).

    — Matej Cepl #

  13. Just if you like to read — http://www.catb.org/~esr/writings/taoup/html/ — ESR has some crazy comments lately, but this thing is pretty smart and ESR is here doing what he can do the best — recording Unix tradition.

    — Matej Cepl #

  14. @Bob: that’s exactly what I was looking for. I’ve updated the script accordingly, and removed the (rather useless) gui= option in the configuration file. (Sorry your comment took so long to appear; it fell into my spam filters!)

    @Noah: script is now wrapped at 78 characters.

    @Isaac, @Matej: thanks for the links, I’ll read them this weekend.

    (Comments temporarily closed until I return from vacation.)

    — Mark #

  15. Hi, nice script, but i’ts possible burn subtitles??
    like .srt, .sub files ????

    :(

    — Harold #

Respond privately

I am no longer accepting public comments on this post, but you can use this form to contact me privately. (Your message will not be published.)



§

firehosecodeplanet

© 2001–9 Mark Pilgrim