Server:Server Status

Bash Script to Clip Ripped Home Movies

Bash script I wrote to assist in clipping home movies. Still some more to do, but here's a summary.

Particularly useful was the code I used to find the difference under bash between start and end points using date...and keeping the result in a format ffmpeg could understand.

#!/bin/bash

# Title: HomeMoviesClipper.sh
# Description: Use ffmpeg to split raw home movie captures into clips
# Original Author: Joseph Gullo (surfrock66) (surfrock66@surfrock66.com)
#
# This script works with a very specific set of constraints and formats to 
#  take raw video captures and split them into clips of events.  Each of 
#  these movies was captured, using a Dazzle USB video capture device, 
#  into h264 video and mp3 audio, using VLC.  These original tapes were 
#  typically close to 2 hours long, however capture was often left to run, 
#  creating videos that were 8+ hours long.  The capture device produced 
#  video that was 480x480 and audio that only contains 1 channel (recorded 
#  through stereo), and the output video will retain this.  The desired 
#  format is high-bitrate h264 and aac audio, encapsulated in .mp4 files. 
#  This script also works within a predictable directory environment 
#  because of how specific the task is, and because I'm a lazy bastard 
#  that doesn't want to code bunch of directory logic.  The script first 
#  queries the input file, then works on this file recursing the steps 
#  for each clip.  Each clip requires an output name, a start timecode 
#  (formatted hh:mm:ss.nnn) and an ending timecode.  This is part of 
#  some of the headache, as ffmpeg processes clips with a start time 
#  and a duration, meaning you have to do the difference math yourself.  
#  I take care of this in there.  After producing a clip, the script 
#  will ask the user if they want to create another clip from the same 
#  source file, at which it recurses through a prompting loop.  The 
#  script also can be run from the command line...however in CLI mode, 
#  the intent is to NOT allow the script to re-prompt for additional cips 
#  from the same source video.

# The script can optionally take 4 command line arguments:
#  1) The filename for the source video, without extension
#  2) The desired resulting clip name, without extension
#  3) The start timecode for the clip, format hh:mm:ss.nnn
#  4) The end timecode for the clip, format hh:mm:ss.nnn
#
# Variables:
#  INPUTFILE - Input video filename, without extension
#  OUTPUTFILE - Clip output filename, without extension
#  STARTTIME - Clip starting timecode, format hh:mm:ss.nnn
#  ENDTIME - Clip ending timecode, format hh:mm:ss.nnn
#  NANODIFF - Difference between start and end timecode, in milliseconds
#  NUMSECS - Timecoe difference in whole seconds
#  NUMNANO - Timecode difference remainder in milliseconds
#  REPLY - Flag for checking if the script should create another clip
#  CLIFLAG - Flag set if command line mode is detected, to prevent prompting
#

# Prompt the user for all parameters, by asking for the source clip name, then calling
#  the function which prompts for the clip info.  This can safely call the clip-info 
#  prompting function, as this should only be used once per execution, if at all.
PROMPTFULL() {
  echo "---What is the source video name? (No Extension) (Inside /home/surfrock66/Videos/HomeMoviesRaw/):"
  # First point of possible declaration for INPUTFILE
  read INPUTFILE
  # Execute the PROMPCLIP function
  PROMPTCLIP
}

# Prompt the user for the clip name, start time, and end time.  
PROMPTCLIP() {
  echo "---What is the output filename for this clip? (No Extension):"
  # First point of possible declaration for OUTPUTFILE
  read OUTPUTFILE
  echo "---What is the timecode for the start of this clip? (##:##:##.###):"
  # First point of possible declaration for STARTTIME
  read STARTTIME
  echo "---What is the timecode for the end of this clip? (##:##:##.###):"
  # First point of possible declaration for ENDTIME
  read ENDTIME
}

# This function handles the timecode calculations to find the clip duration, 
#  then executes the actial ffmpeg command.
PROCESSVID() {
  # Calculate the actuall difference, in milliseconds (but we'll call them 
  #  nanoseconds, because that's how the date command works) between the 
  #  start time and end time.  This relies heavily on the "date" command.  
  #  It can convert formatted timecodes between different format 
  #  conventions, but to go from something resembling a standard video 
  #  editing timecode to a raw nanosecond count is a PAIN IN THE ASS.  
  #  This strips out the amount of hours in milliseconds, then the number 
  #  of minutes in milliseconds, then the number of seconds in milliseconds, 
  #  then the number of nanoseconds in milliseconds.  It then adds them 
  #  together, creates a full millisecond count for the start an end time, 
  #  and then finds the difference, in milliseconds.
  NANODIFF=$(($(($(($(date -d $ENDTIME +%-H) * 3600000)) + $(($(date -d $ENDTIME +%-M) * 60000)) + $(($(date -d $ENDTIME +%-S) * 1000)) + $(($(date -d $ENDTIME +%-N) / 1000000)))) - $(($(($(date -d $STARTTIME +%-H) * 3600000)) + $(($(date -d $STARTTIME +%-M) * 60000)) + $(($(date -d $STARTTIME +%-S) * 1000)) + $(($(date -d $STARTTIME +%-N) / 1000000))))))
  # Convert the resulting difference, in millisecodns, into seconds
  NUMSECS=$(($NANODIFF / 1000))
  # Convert the reaminder of the resulting difference, in milliseconds,
  #  to milliseconds
  NUMNANO=$(($NANODIFF % 1000))
  # Print out the ffmpeg command that is generated, mostly for debugging
  echo "\nCommand: ffmpeg -i \"/home/surfrock66/Videos/HomeMoviesRaw/$INPUTFILE.mp4\" -ss $STARTTIME -t $NUMSECS.$NUMNANO -vcodec libx264 -b 1500k -s 480x480 -acodec libfaac -ab 192k -ac 1 -threads 8 \"/home/surfrock66/Videos/HomeMoviesRaw/$INPUTFILE/$OUTPUTFILE.mp4\"\n"
  # Execute the ffmpeg command, this is the big kahuna.
  ffmpeg -i "/home/surfrock66/Videos/HomeMoviesRaw/$INPUTFILE.mp4" -ss $STARTTIME -t $NUMSECS.$NUMNANO -vcodec libx264 -b 1500k -s 480x480 -acodec libfaac -ab 192k -ac 1 -threads 8 "/home/surfrock66/Videos/HomeMoviesRaw/$INPUTFILE/$OUTPUTFILE.mp4"
}

# Start of the main script.  Section 1: Input validation
#  Check that there is a first parameter.  If not, Prompt the user for the
#   parameters.  If there is one, validate the rest of the params, then 
#   either prompt the user, or use the passed params.
if [ -z "$1" ]
then
  # Call the prompt function, including asking for the source video
  PROMPTFULL
else
  # Assuming the first parameter exists, check for parameters 2,3, and
  #  4.  I'm not validating these strings, mostly because ffmpeg will 
  #  flip out if there's something wrong with them...as you know, it's
  #  quite verbose.
  if [ -z "$2" -o -z "$3" -o -z "$4" ]
  then
    # If any parameters are invalid, prompt for them all. Even if param 1
    #  is successfully detected, re-ask for it.  
    echo "--Parameters are incomplete, switching to prompt mode."
    PROMPTFULL 
  else
    # Pass all the command line parameters to the variables
    INPUTFILE="$1"
    OUTPUTFILE="$2"
    STARTTIME="$3"
    ENDTIME="$4"
    # Change the flag to indicate later that this initiated by CLI
    CLIFLAG="yes"
  fi
fi

# Create the default output directory, if it's not already created
if [ ! -d /home/surfrock66/Videos/HomeMoviesRaw/$INPUTFILE ]; then
  mkdir /home/surfrock66/Videos/HomeMoviesRaw/$INPUTFILE
fi

# Now...initiate the final video processing
#  Declare and initiate the REPLY flag...can be set to anything byt n/N
REPLY="y"
# As long as the REPLY flag isn't n or N, repeat the loop
while [ "$REPLY" != "n" ] && [ "$REPLY" != "N" ]
do
  # Call the function PROCESSVID
  PROCESSVID
  # Check to see if the script was run with command line parameters,
  #  If not, issue a bunch of logic to see if we want to re-run the
  #  code for new clips
  if [ -z "$CLIFLAG" ]
  then
    # Now that we know the script was run in prompt mode, ask the user
    #  if they want to make another clip, repeating this loop
    echo "---Would you like to create another clip from this input video? {Y/n}"
    read REPLY
    if [ "$REPLY" != "n" ] && [ "$REPLY" != "N" ]
    then
      PROMPTCLIP
    fi
  # If it was run by command line, essentially abort the loop,
  #  and the script.
  else
    REPLY="n"
  fi
done
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Raspberry Pi Shadowbox Case

Come on, no one reads this. However I need a place to show off my Raspberry Pi case, so I will make it go here.

OBJECTIVES:

  • Functional case for the Raspberry Pi as a media player
  • Attractive enough to pass the wife-approval test
  • Can end up near the TV without any furniture around it

So I got this idea...let's mount the thing in a shadow box. It can hang on the wall next to the tv, will have some air in the case to dissipate heat, can have all cables routed out one side, and can have a matte to hide internal wires.

Here's the results!

pi1

This is the mount, before any cabling is done.

pi2

Here it is up on the wall, with some of the cable management. The HDMI cable isn't done yet, so it's just hanging out the bottom.

Pi3

On the wall, with cables in and power on, basically the finished product.

pi4

The finished thing, with raspBMC powered up and running.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Redoing Bathrooms

Thought I'd show some updates to the work Jenn and I are doing to redo our bathrooms in the new house. All three full bathrooms had awful green 70's tile which we're removing and replacing. One bathroom (the master) has a green tub as well...we'll be getting that resurfaced.

The steps have been as follows:

  1. Remove old tile, being very careful to preserve it to donate to habitat
  2. Remove existing rotted drywall
  3. Clean all surfaces
  4. Put up concrete backer board
  5. Cut tile, apply mortar, put tile up (usually 4-5 stages per room)
  6. Grout tile
  7. Seal tile
  8. Apply Caulk
  9. Replace Fixtures
Read more »
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Dynamic Menus in WordPress as a CMS

I've been developing a site where I'm using wordpress as a CMS more than a blog, for many reasons. I'm very familiar with it, I like the automated SEO, I think it's simple to use, etc. But one big challenge is the menu navigation and how to set it up. I want this to be automated and I don't want to have to edit the menu every time there's a new page.

To clarify the terms, there's a menu with "solutions" then "products" with 3 sub categories "indoor" "outdoor" and "media players." Plus there's a "guides" area and a "blog" area.

The menu system is handled by the category management. If a page is made that goes into the menu, you simply tag it with the category where it should go. You can click the main header of the menu to go to a page with all the posts in the category. Then you hover over the header of the menu, and I want a dropdown menu with a list of posts in there. I want to limit this to a certain number of posts, then have a button for "more" at the bottom. You can see an example here.

Let's take a look at the code at the start of my menu. This basically encapsulates the markup for the menu, and for the first dropdown. I have this in a separate "nav_menu.php" file but it could go in your header as well.

   <div id="nav_menu">
   <ul id="main-nav">
    <li id="solutions-nav" class="singlelevel"><a href="./?cat=9&amp;feature=solutions">Solutions For...</a>
     <div class="subnav">
      <ul>
        <?php query_posts('cat=9&posts_per_page=10&orderby=title&order=ASC'); ?>
       <?php while (have_posts()) : the_post(); ?>
        <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
       <?php endwhile; ?>
       <li><a href="./?cat=9">More...</a></li>
      </ul>
     </div>
    </li>

So, take a look at the php code there. First of all, important to note, this disrupts the wordpress loop so we'll need to fix it a little bit later. First, it does a post query limiting the list to one category (you can search by "category_name" but I'm a fan of the Id's) and then setting a limit to how many to pull; I chose 5 by default. Then, there's a while loop that pulls some data from each post and formats it into a listed menu entry. After the while loop closes, I throw out the "more" button which queries the whole category for posts.

If you do just that, every time you try to list posts you'll pull a list of every post you've got and it will supremely annoy you. You need to reset your post query to be able to limit it to the page at hand. At the bottom of my theme's "header.php" file, right before the posts would get displayed by "index.php," I added the following php line:

<php query_posts('cat='.@$_GET['cat'].'&p='.@$_GET['p']); ?>

This will pull the post list based on the categories selected or the specific post listed; all of my links and navigation are handled through those 2 "GET" variables so it will limit the posts queried to anything selected. Make sure to put the @ before $_GET to suppress any errors the get command gets, for example, if there's nothing passed.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Rooting to the Palm Pre in Ubuntu

I found a lot of disjointed instructions for rooting to the palm pre in linux, so I thought I'd document the process I used to make it work. These instructions were written using Ubuntu 9.04 Jaunty Jackalope and WebOS version 1.1.0.

  1. Add the repository for virtualbox to your sources list. For Ubuntu 9.04, add deb http://download.virtualbox.org/virtualbox/debian jaunty non-free A list of repos for other distros can be found here: http://www.virtualbox.org/wiki/Linux_Downloads, or if you want to download the .deb and install it that way, go here and choose version 2.2: http://www.virtualbox.org/wiki/Download_Old_Builds I know V-Box is past 3 now, but I had the most success with 2.2. The source for the GPG key can be found here: http://download.virtualbox.org/virtualbox/debian/sun_vbox.asc. Virtualbox is a virtual machine platform that acts as a development platform for the pre, so you may not use it much, but you should do it anyway.
  2. Install virtualbox using the following command: sudo apt-get install virtualbox-2.2
  3. Install the Java JRE using the following terminal command: sudo apt-get install sun-java6-jre
  4. Download the Palm Mojo SDK at the following website: http://developer.palm.com/index.php?option=com_ajaxregister&view=register&sdkdownload. You will be asked to register as a developer, at which point you will be able to choose to Download the sdk, and you should choose the Linux SDK, which will say it is designed for Ubuntu 8.04.
  5. The SDK is a .deb file. You should double-click this file, which will prompt you to install. Install the package.
  6. Download the Novacom Driver from the following link: https://cdn.downloads.palm.com/sdkdownloads/1.1/sdkBinaries/palm-novacom_0.3-svn177284-hud9_i386.deb Install it exactly as you did the SDK
  7. Open your palm pre and load the launcher. Type the following text EXACTLY: upupdowndownleftrightleftrightbastart
  8. This will launch a dialogue asking you to put the phone into dev mode. Slide the switch to activate dev mode, and agree when it asks you to reboot the phone. This same procedure is used to remove the phone from developer mode, and you will be asked to do that later.
  9. Once the phone comes back on, plug it into the computer using the USB cable, and choose "Just Charge" on the phone's screen.
  10. You now have terminal access to your phone. Open a terminal and type: cd /opt/Palm/novacom If this doesn't work, some people report the files for novaterm are located in /opt/nova/bin
  11. Type novaterm and you should be brought to a command prompt that displays:"root@castle:/#
  12. Before taking this step, make sure you either have a data signal, or make sure you have wifi access; you need the internet here. Type the following command in EXACTLY to enable Optiware . In fact, it's probably wise to copy and paste them into your terminal: cd /tmp
    wget http://gitorious.org/webos-internals/bootstrap/blobs/raw/master/optware-bootstrap.sh
    sh optware-bootstrap.sh
    Follow the on-screen instructions to complete the setup.
  13. This step istalls the "Quilt" patch manager (pun intended.) Type the following code in exactly: cd /tmp
    wget http://gitorious.org/webos-internals/bootstrap/blobs/raw/master/quilt-bootstrap.sh
    sh quilt-bootstrap.sh
  14. The Pre already has a package management app, called FileCoaster, meaning you can install apps from the pre, without rooting in through a terminal, over the web. To install the package manager though, I recommend using the terminal. At the Pre terminal prompt, type this exactly: sudo ipkg -o /var install http://www.precentral.net/sites/precentral.net/files/webos-homebrew-apps/feeds/com.palm_.net_.precoder.fcoaster_1.1.1_all.ipk Check here for updated links to .ipk files for versions of FileCoaster past 1.1.1.
  15. It's annoying to have to type the whole code to turn the developer mode on and off, but fortunately there's a patch to put a button in your launcher. This uses the procedure for applying patches using quilt, and there's an instruction sheet for this process here. Basically, you're going to enter the following code exactly:sudo mount -o remount,rw /
    cd /
    sudo quilt import /opt/src/modifications/luna/enable-dev-mode-icon.patch
    sudo quilt push
    sudo mount -o remount,ro /
    For a complete list of patches you can apply using this procedure, look here: http://www.webos-internals.org/wiki/Portal:Patches_to_webOS
  16. To log out of your pre and close terminal access, type: exit
  17. Turn off your pre, then turn it back on.
  18. While this is not necessarily a step, you can now ssh to your pre even if you don't have a USB cable attached. I'll check my home router's config to find the IP of the pre (or just use www.checkmyip.com) and ssh in on port 222 with the following command:ssh <IP Address> -p 222 -l <username>

That should set you up to do most of what you could ever want to do with homebrew on the pre. Check out this thread for a list of homebrew apps, and the links to the .ipk files which you can use to install via FileCoaster: http://forums.precentral.net/homebrew-apps/194104-links-all-homebrew-apps-updated-7-31-a.html.

I credit this article to the following sources:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -