Generate SMIL with an Applescript

Greetings all!

I’ve been lurking around for a while. Finally, I have a good question to post.

I am Technical Manager at a college movie theater. Our pre-movie slide show uses an SMIL script to play slides, movies and video clips before the movie starts. It works out pretty well but the time has come for me to train somebody else to handle the pre-movie multimedia.

I put all the multimedia files into my “Shared” folder specially set aside for the purpose… (JPEG/TIFF pictures, MP3/AIFF music, MOV/MPEG/etc. movie files.) I tell the people who supply me with the media where to put them and the deadline for publication. They simply drop the files into the folder. Later on, I go into that folder, preview the files then write the script. It works out pretty well but the time has come for me to pass the torch. But the sad truth is that I have little chance of finding a Work Study student who knows how to hand-code an SMIL script. My solution is to write an AppleScript to do it auto-magically.

I have a script that does the job but it needs work. It’s rather long so I won’t put it into this message but, if you want to read it, Click HERE.

It’s a bit convoluted and pretty clunky but it has basic function. Simply put, my question is how to clean it up?

The script works like this:

  1. It asks for the location of the folder containing the multimedia files.
  2. It asks for the location of a template file that contains all the headers and region definitions that SMIL needs to get started.
  3. It reads in the list of all the filenames in the selected folder and builds the SMIL from the information contained therein.

My method is to code the file names so that the AppleScript knows what to do with them.

An example woud be:

01 B MyFileName reg 30.jpg

The first two digits determine the order the files play in. (The finder does this for me when it automatically alphebetizes the list.)
The next letter tells the script if there should be a “ – ” tag. (B=Begin a block. E=End a block.)
“MyFileName” is descriptive text.
“reg” is the screen region I want the picture or movie to play in.
The last two digits are the duration I want the file to play.
The script parses the file extension (“jpg”, “mp3”, etc.) to find out what type of media it is.

I’ve got a bunch of questions but, I’ll limit it to just this one for now…

Is there a better way to do this? Can AppleScript determine some information about a file without me having to code it into the file name?

T.I.A.! :slight_smile:

Randy

As I see it, your script is OK. AppleScript can’t guess for you what is the duration of a clip, or what is the play order you wish, so you can use your method (adding the info in the file name), write all to a text file or whatever. But AS can’t guess arbitrarilly.

As for cleaning your current code, you can rework some things, but functionality will be still the same after rewriting. And, if I’m reading OK, you won’t notice speed nor efficiency changes. Anyway, some advices. For example, for this kind of usage:

AddText(FilePath, cr(2))

on cr(i)
	(* Generate "i"  carriage returns. *)
	
	set r to ""
	
	repeat with j from 1 to i
		set r to r & "
" (* This line actually contains "\r" but the computer doesn't show it. *)
	end repeat
	
	set result to r
end cr

I would simply write:

AddText(FilePath, return & return)

But, if you find it more comfortable, I would rewrite the handler as follow:

property crs : return & return & return & return & return & return & return

on cr(i)
	text 1 thru i of crs
end cr

(And the same for tabs: tab & tab & tab & tab…).

As a rule, a handler will return allways the result of the last expression. So, using “set result to blah” at the end of a handler is redundant. It would be good enough stating “blah” or “return blah”. This is not important, but only the usual syntax.

The “PAR” handler could be also refined as follow:

on PAR(x)
	"<" & x & "par>"
end PAR

Same for “EndTags”. As it will be allways the same text, you can enclose it in a property and use it later, instead of creating the text from scratch every time:

property EndTags : tab & "</body>" & return & "</smil>"

AddText(FilePath, EndTags)

The if/end-if block in the “TypeOf” handler could be rewriten as follow:

if imgList contains tle then
	return "img"
else if audioList contains tle then
	return "audio"
else if textList contains tle then
	return "textstream"
else if videoList contains tle then
	return "video"
end if

(And you better declare the globals -imgList, etc.- in the top of the run handler, next to “FolderPath” and “FileList”).

You could also re-write “AddText” as follow:

on AddText(fname, StuffToWrite)
	set fNum to open for access file fname with write permission --> open for access
	write (StuffToWrite & cr(1)) to fNum starting at eof --> write appending data
	close access fNum --> close
end AddText

Absolutely fabulous! Thanks a million! :slight_smile:
Honestly, I didn’t think anybody would take the time to read that script!

The reason I have the handlers “CR(x)” and “T(x)” work the way they do is SUPPOSED to be so that I can make the indentations and double-spaces between lines. That way I can (attempt to) keep the generated SMIL as human readable as possible.

I’m seriously looking at your suggestions for changes. I don’t have much time right now. I’m working on several jobs at once. (Normal in my line of work! :wink: ) When I get the chance to put them in I’ll get back to you!

I just put my AppleScript into action today and it works well. I’ve got a couple-three things to fix up before I take the “b” off the end of the name:

  1. Fix up the way the script renames the files. I want the output file to be something like, “Show . sml”. I need to figure out how to make AppleScript get the date for me in a way that’s convenient. (Like “MM/DD/YY”.)

  2. I think I have found a way to command QuickTime Player, via AppleScript, to tell me the duration of a video or sound clip. I’m still figuring out the method. When I have a QT movie on my desktop the Finder displays its duration. How does Finder know that? Is it weaseling the information out of QuickTime or does it have a direct way of finding it out? If I could get the AppleScript to do this for me it would greatly simplify the file naming convention.

  3. Pretty-up the code. Comment it then save it as an application. Once this is done I think I’ll be ready for Prime Time!

Thanks again for all your help!

Randy
:slight_smile:

There are various ways. For example:

set cd to current date

set fileName to "Show " & formatDate(cd) & ".smil"

to formatDate(d)
	text -2 thru -1 of ("0" & (month of d as number)) & "-" & ¬
		text -2 thru -1 of ("0" & (day of d)) & "-" & ¬
		text -2 thru -1 of (year of d as text)
end formatDate
  • I think this code requires Panther, at least.

Yes, in QT Player this would be something as:

tell application "QuickTime Player" to duration of movie 1

More easy thru System Events:

tell application "System Events" to duration of QuickTime file "path:to:blah.mov"

(Not sure, though, if this will work in systems other than Tiger)
And I think you could get the info also thru some command-line tools, IIRC, such as ffmpegX.

Anyway, wouldn’t you have to type manually the duration for static things? (eg, images)

There is almost always a sound clip or movie clip playing in parallel to every static image.

For instance, if there is a static slide that says, “Buy your Christmas gift certificates early!” there will be an audio clip of “Jingle Bells” playing in the background. That’s why I have the script parse the “B” and “E” in the file name to start and end the “ - ” blocks.

IF you name a file “01 B GiftCertificateAdvert.jpg”
THEN you name the next file “01 E JingleBells.mp3”
the computer SHOULD generate the code:

<par> <img src="01 B GiftCertificateAdvert.jpg" region="fs" dur="{some duration}s" /> <audio src="01 E JingleBells.mp3" dur="{some duration}s" /> </par>
As it stands, now, I have to put the duration of every clip into the file name, thus:

01 B GiftCertificateAdvert 30.jpg (Where the “30” determines “{some duration}”.)

I would LIKE the script to look at the duration of the file “01 E JingleBells.mp3” then use that information to determine the value for “{some duration}”.

This will be in a future revision, of course.
Last night I used your suggestions to help me get the beta version of the script working. (T.Y.V.M!)
There are some things that need to be fixed, though:

  1. There can ONLY be multimedia clips with specially-formatted file names in the target folder. If there is a wrong file or a file with a wrong file name the script will barf. (Throw an error.)
    I would like to have the script put up a dialog to catch that error. ("Hey! I found a file that didn’t fit! What do you want to do with it? Button: {“Skip it.”, “Quit”, “Continue Anyway.”})

  2. The files have to have VERY specifically-written filenames.
    I am going to have to get used to the fact that the thing I want AppleScript to do for me is probably ALWAYS going to need special file names but I would like to make the requirements less dificult.