PDA

View Full Version : Newbie shell script question




oedipax
Oct 14, 2010, 02:33 PM
Hey there. I'm an editor trying to cobble together a script for generating video thumbnails automatically. I've done a small amount of programming in my past, but not enough to really code something like this. I've been able to cobble together a solution between Automator and a shell script (plus ffmpeg) I found on the web, but there's one final problem.

Currently the script is as follows:

First, an Automator action: "Get Selected Finder Items."

Then, a Run Shell Script action:

for f in "$@"
do
/usr/local/bin/ffmpeg -i "$f" -an -ss 00:00:30 -t 00:00:01 -r 1 -y /Users/me/Desktop/Thumbs/test/video%d.jpg
done

It grabs a thumb from 30 seconds into the video and saves it out as a jpg. Beautiful. Simple. Automatic.

The only problem, as you can probably guess, is that if I drop several files at once on the script, it gives them all the same name. It overwrites them progressively so that at the end, all you have is the last file.

What I'd like to know is, how can I pass the filenames from the Finder (which I'm using to drag the files over to the script) to the script and maintain them at the end. So if I give it Video1.m4v, Video2.mov, Video3.avi, etc., it will spit out Video1.jpg, Video2.jpg, Video3.jpg.

I'm so close to getting this thing working right and saving myself a ton of time, as I have to make hundreds of thumbnails sometimes. I tried many of the freeware apps and they all had things that bugged me and made them unusable for one reason or another.

Any help would be extremely appreciated! Thanks!



lee1210
Oct 14, 2010, 02:50 PM
for f in "$@"
do
thumb_name=`echo $f|sed 's/\..\{3\}$//'`.jpg
echo $thumb_name
done

You can just subsitute $thumb_name into your ffmpeg command for the filename. I got the sed from:
http://txt.binnyva.com/2007/07/remove-file-extension-using-sed/
by searching google for "shell remove file extension"

It looks like this assumes 3 character extensions. That can be tweaked, but if all of your videos are 3 character extensions it will work. .mpeg will bite you.

for f in "$@"
do
thumb_name=`echo $f|sed 's/\..\{2,4\}$//'`.jpg
echo $thumb_name
done

This will deal with 2 to 4 character extensions.

-Lee

oedipax
Oct 14, 2010, 03:11 PM
Thanks very much for the quick and helpful reply!

Unfortunately I have to show here my own ignorance of what to do next... I'm guessing I need to merge the code somehow, but I'm unsure which part of the old one I need to throw away. Here's how I tried it just now:

for f in "$@"
do
thumb_name=`echo $f|sed 's/\..\{3\}$//'`.jpg
echo $thumb_name
/usr/local/bin/ffmpeg -i $thumb_name -an -ss 00:00:30 -t 00:00:01 -r 1 -y /Users/me/Desktop/Thumbs/test/$thumb_name.jpg
done

Which gives an error (but not a helpful one!) I've also tried putting quotes around $thumb_name in the argument.

Sorry. I really do need this spelled out :p

CarlJ
Oct 14, 2010, 04:22 PM
Try this (as as a replacement/new version for the entire script):
#!/bin/bash

DEST=/Users/me/Desktop/Thumbs/test

for VIDEO in "$@"; do
BASE=${VIDEO##*/}
NAME=${BASE%.*}
/usr/local/bin/ffmpeg -i $VIDEO -an -ss 00:00:30 -t 00:00:01 -r 1 -y $DEST/$NAME.jpg
done

exit 0

It's a little simpler, letting the shell tweak the name directly, rather than farming the work out to external commands like sed. Points of interest:

Incoming filenames each get assigned to $VIDEO, in turn, and look something like "/foo/bar/Animal.m4v".
$BASE is set to a copy of this, with any initial sequence up to the final "/" removed (thus "Animal.m4v"), giving us the base filename without the initial path.
Then $NAME is set to a copy of $BASE, with the trailing ".whatever" removed (thus, "Animal").
We set $DEST up at the start of the script to the directory where you want the files to end up (tweak that as necessary), so $DEST/$NAME.jpg gets us an output filename of (in this example) "/Users/me/Desktop/Thumbs/test/Animal.jpg".
The "#!/bin/bash" at the start of the script makes sure that the script really does run as a Bash script (even if your shell is set to something else, like tcsh or zsh), and the "exit 0" at the end makes the script tell the program that called it that everything went okay.

oedipax
Oct 14, 2010, 07:05 PM
Many thanks again to both of you! Such a supportive forum you all have here, I hope I can give back at some point... just not in this subforum :)