Using Applescript and FFmpeg (through ffmpegX) to create Flash Video Files (FLV)
by Greg Walsh (gregwalsh.com)
Problem
I often need to create a number of Flash Video Files from source video for
e-learning. We use one dual-processor Macintosh G5 system for all of our audio
and video needs. We develop Flash movies on PC Workstations and import the FLVs
to be used in our custom video player.
Almost all of our tasks are instantanious or can happen in paralell. Our
workflow hits a bottle neck when exporting to FLV files from Quicktime Pro using
the Flash Video Exporter plug-in because it only allows you to export one file
at a time and and requires human interaction to start the process again with the
next movie when the current one has finished. Although the plug-in promises that
you can use it in a program that uses Quicktime plug-ins (Final Cut Pro is often
mentioned), I haven't been able to use it in Apple's Compressor program to batch
process files. When I use the plug-in with FCP, I can only export one file at a
time which, again, creates a bottleneck in my workflow because I need to see if
it is done and it ties up the editing program.
Here is my group's current workflow:
-
Record audio into digital files
-
Edit audio into appropriate chunks
-
Record video
-
Capture raw digital video
-
Cut up video into selected chunks using Quicktime Pro
-
Create a new project in Final Cut Pro
-
Import audio & video
-
Edit together
-
Export to video format
-
Convert video to FLV
I wanted a solution that would let me submit my videos for batch processing at
the end of my work session and either continue working on the mac (preferred but
not mandatory) or walk away and do another part of the project on a pc without
having to monitor the processing.
Solution (and how I came up with it)
My initial thought was to create an AppleScript that controlled the Quicktime
Player and batched processed the files using the FLV exporter. I downloaded the
AppleScripts for Quicktime from Apple's Web site and began looking through the
various examples. Each of the exporting examples required the Quicktime Player
to have a preset defined. Quicktime has some common presets but none to export
to FLV. I used an AppleScript to create a new preset based on the FLV export,
but, I never got an AppleScript to work using the new preset.
After searching for awhile, I started to see lots of references to FLVs and
FFmpeg, the open source engine for media production and conversion. I had used
ffmpegX for OS X so I started to look for info on if ffmpegX and FLVs.
Unfortunately, ffmpegX is focused on more traditional video formats and portable
video formats (It's a great set of tools). I did find an article on Cyril
Godefroy's Web site that explained how to use ffmpeg to make FLVs but it
required me compliling ffmpeg from scratch...or at least I thought it did. In a
ffmpegX message board, I saw an example of how to use the embedded version of
ffmpeg in ffmpegX to convert a video.
In the terminal, I combined Godefroy's shell commands with the ffmpeg in
/Applications/ffmpegX.app/Contents/Resources/ to convert a Quicktime movie taken
with my consumer digital camera to an FLV and it worked...it seemed to work
significantly faster than the official
FLV Exporter for Quicktime. Next, I made that into an AppleScipt using the
do shell command. Finally, I took that
code, combined it with the Quicktime droplet example AppleScript and set up
variables to make it work as a Droplet.
I found that the only video format that it supports converting to an FLV with
sound is MPEG-1. It worked without sound as a Quicktime movie encoded in the
Sorenson format but none of the audio codecs worked for me. I kept getting Bus
Errors from ffmpeg. I found that I could make the movies with audio an MPEG-1 in
Compressor and that translated well into an FLV.
The last piece to this puzzle was hooking it into Compressor somehow. I created
a Compressor preset to make the MPEG-1 file to the size I wanted. One of the
options in Compressor is Action and it lets you designate some type of file or
script to be run on the movie when it's done processing. I pointed this tab to
the Droplet I created and it runs after the movie is exported to MPEG. The only
problem I've had so far is if the processed movie takes longer in the droplet
than the next movie being processed takes in Compressor, the second movie
doesn't get converted in the Droplet.
I guess I'll have to work on that.
Some other things I'd like it to do: display a terminal window showing what's
going on, make it work with another file format other than mpeg-1.
Solution Summary
Write an AppleScript that utlizes do
shell to process a file with the ffmpeg that is part of ffmpegX.
AppleScript Code
-- AN EXAMPLE
DROPLET WITH SETABLE PROPERTIES
property type_list : {"MooV"} -- the list
of file types which will be
processed
-- since file types are optional in Mac
OS X,
-- check the name extension if there is
no file type
-- NOTE: do not use periods (.) with the
items in the name extensions list
-- eg: {"txt", "text", "jpg", "jpeg"},
NOT: {".txt", ".text", ".jpg",
".jpeg"}
property extension_list : {"mov",
"mpg"}
property example_property_A :
"On"
property example_property_B :
"On"
-- THE FOLLOWING ROUTINE APPEARS ONLY
WHEN THE DROPLET IS DOUBLE-CLICKED
on
run
display dialog
"Convert an MPEG-1 w/Audio to an FLV file" & return & return &
¬
"by
Greg Walsh" & return & ¬
"3/2006"
end
run
-- This droplet processes both files or
folders of files dropped onto the
applet
on open
these_items
-- CHECK THE VERSION
OF QUICKTIME INSTALLED
-- make something that
checks for ffmpegx
repeat with i from 1
to the count of these_items
set
this_item to (item i of these_items)
set
the item_info to info for this_item
if
folder of the item_info is true then
process_folder(this_item)
else if (alias of the item_info is false) and
¬
((the file type of the item_info is in the type_list) or
¬
the name extension of the item_info is in
the extension_list) then
process_item(this_item)
end
if
end
repeat
end
open
-- this sub-routine processes
folders
on
process_folder(this_folder)
set these_items to
list folder this_folder without
invisibles
repeat with i from 1
to the count of these_items
set
this_item to alias ((this_folder as text) & (item i of
these_items))
set
the item_info to info for this_item
if
folder of the item_info is true then
process_folder(this_item)
else if (alias of the item_info is false) and
¬
((the file type of the item_info is in the type_list) or
¬
the name extension of the item_info is in
the extension_list) then
process_item(this_item)
end
if
end
repeat
end
process_folder
-- this sub-routine processes
files
on
process_item(this_item)
-- NOTE that the
variable this_item is a file reference in alias
format
-- FILE PROCESSING
STATEMENTS GOES HERE
set myFileName to
getFileName(this_item)
with timeout of 3600
seconds -- one hour per movie time
limit
--display dialog "/Applications/ffmpegx.app/Contents/Resources/ffmpeg -i " &
the POSIX path of this_item & " -acodec mp3 -ab 32 -f flv -s 320x240 -ar
22050 -aspect 4:3 -pass 1 -b 256 -r 15 -y ~/Desktop/" & myFileName &
".flv"
do
shell script "/Applications/ffmpegx.app/Contents/Resources/ffmpeg -i " & the
POSIX path of this_item & " -acodec mp3 -ab 32 -f flv -s 320x240 -ar 22050
-aspect 4:3 -pass 1 -b 256 -r 15 -y ~/Desktop/" & myFileName &
".flv"
end
timeout
end
process_item
on
getFileName(thefile)
set {oldDelims,
AppleScript's text item delimiters} to {AppleScript's text item delimiters,
{":"}}
set mytextfilename to
last text item of (thefile as text)
set AppleScript's text
item delimiters to oldDelims
return
mytextfilename
end getFileName
Resources
(As of 2006/03/15):
Cyril Godefroy's Web site
lelab
- How to encode flash video - when you don't have Flash
Technical
Note TN2065: do shell script in AppleScript
AppleScript
- getting a file name from a path name
ffmpegX
Homepage
Note: ffmpegX is shareware. I'm not sure what the "legality" is in using the
ffmpeg from the app bundle without paying for it. It is open-source but I'm
still not sure.