My problem: I have a growing collection of videos that I’ve acquired over the years. My problem is that I have so many now that it’s difficult to remember what they all are, what they’re about, who is in each etc.
The solution: I developed a workflow of 4 applescripts to accomplish my task. The workflow ultimately places the information about each video in the video file, such that I can open a video and instantly see the data or use Spotlight to search on the data. A more detailed explanation of what each script does is explained inside each applescript.
This is script 3 of 4. Annotations to movie credits:
This script works on a folder full of videos which have their annotations set using script 2. It creates a text track from the annotations, adds the text track to the video, and places the text track at the beginning of the video. This one is really cool. It is also nondestructive to the video.
The 4 scripts are here:
http://bbs.applescript.net/viewtopic.php?pid=82570#p82570
http://bbs.applescript.net/viewtopic.php?pid=82571#p82571
http://bbs.applescript.net/viewtopic.php?pid=82572#p82572
http://bbs.applescript.net/viewtopic.php?pid=82573#p82573
(* This script works on a folder full of video files that have information in their annotations. The purpose is to add some descriptive text to the beginning of the movie. It is designed to work with my "imdb to annotations" script which adds movie data from the imdb database to the annoations of a movie. This script uses those annotations to create the text for the movie. The text is added as a text track (called Opening Credits Track) to the movie and is presented as rolling credits in the beginning of the movie. The default is set such that the text will overlay the opening seconds of the movie. *)
(* Note: Set the property "credits_overlay" to false if you want the rolling credits placed before the movie instead of over the beginning of the movie. *)
(* Note: this is a non-destructive technique. It does not write over any part of the movie. To undo the rolling credits simply disable or delete the "Opening Credits Track" from the movie. *)
property credits_overlay : true -- true means credits overlay the movie, false places them before movie
-- this is a list of annotations, ordered in the order they are displayed on screen
-- note the format: a list of lists. Each list contains the official annotation name. Some of them contain a second name. This second name is the name of the credit when it is displayed on screen, in other words the second word in the list takes the place of the first word when displayed on screen. If there isn't a second name then the annotation name is displayed as is.
set ann_order to {{"Full Name", "Title"}, {"Copyright", "Release Date"}, {"Special Playback Requirements", "MPAA Rating"}, {"Warning", "User Rating"}, {"Description"}, {"Performers", "Actors"}, {"Genre"}}
property title_font : "Baskerville"
property title_style : "{bold}{italic}{dropShadow: on}{dropShadowOffset: 3, 4}"
property title_minSize : 10
property annName_font : "Geneva"
property annName_style : "{italic}"
property annName_font_minSize : 8
property annValue_font : "Geneva"
property annValue_style : "{plain}"
property annValue_font_minSize : 10
property end_duration : 0.5 -- in seconds, the amount of time before the movie starts after the credits end
-- choose the source folder and get all of its files
set source_folder to choose folder with prompt "Choose the folder of movie files:"
set source_folder to source_folder as string
tell application "Finder" to set source_movies to every file of folder source_folder
tell application "QuickTime Player"
launch
my supressAutoPlay(true) -- make sure movies set to auto play do not do that
repeat with i from 1 to count of source_movies
set aMovie to item i of source_movies as string
try
open aMovie
rewind
select none
if saveable of movie 1 is true then
if not (exists track "Opening Credits Track" of movie 1) then
set movie_name to name of front movie
set movie_path to original file of movie movie_name
set nmExt to my getName_andExtension(movie_path)
set movie_title to item 1 of nmExt
tell movie movie_name
set time_scale to time scale
copy natural dimensions to {movie_width, movie_height}
end tell
-- get the movie annotations
set all_anns to my get_allAnns(movie_name)
-- order the annotations so the credits appear properly and make sure that a title appears in the list
set ordered_credits to my orderCredits(ann_order, all_anns)
if item 1 of (item 1 of ordered_credits) is not "Title" then
set beginning of ordered_credits to {"Title", movie_title}
end if
-- setup the header text for the credits file
set the credits_text to ""
set the credits_text to the the credits_text & "{QTtext}" & return
set the credits_text to the the credits_text & "{font:Geneva}"
set the credits_text to the the credits_text & "{plain}"
set the credits_text to the the credits_text & "{size:16}" & return
if credits_overlay then
set the credits_text to the the credits_text & "{textColor: 65535, 65535, 65535}" & return
set the credits_text to the the credits_text & "{backColor: 0, 0, 0}" & return
else
set the credits_text to the the credits_text & "{textColor: 0, 0, 0}" & return
set the credits_text to the the credits_text & "{backColor: 44461,52428,44204}" & return
end if
set the credits_text to the the credits_text & "{anti-alias:on}" & return
set the credits_text to the the credits_text & "{justify:center}" & return
set the credits_text to the the credits_text & "{timeScale:" & time_scale & "}" & return
set the credits_text to the the credits_text & "{width:" & (movie_width as string) & "}" & return
set the credits_text to the the credits_text & "{height:" & (movie_height as string) & "}" & return
set the credits_text to the the credits_text & "{timeStamps:relative}" & return
set the credits_text to the the credits_text & "{language:0}" & return
set the credits_text to the the credits_text & "{textEncoding:0}" & return
set the credits_text to the the credits_text & "{scrollIn:off}" & return
set the credits_text to the the credits_text & "{scrollOut:off}" & return
if credits_overlay then
set the credits_text to the the credits_text & "{keyedText:on}" & return & return
else
set the credits_text to the the credits_text & "{keyedText:off}" & return & return
end if
set the credits_text to the the credits_text & "[00:00:00.000]" & return
-- calculate text sizes and other info for the credits
set title_size to movie_width div 12
if title_size is less than title_minSize then set title_size to title_minSize
set spacer_size to movie_width div 68
if spacer_size is greater than 12 then set spacer_size to 12
set spacer_line to "{font:" & annName_font & "}{plain}{size:" & spacer_size & "} " & return
set annName_size to movie_width div 34
if annName_size is less than annName_font_minSize then set annName_size to annName_font_minSize
set annValue_size to movie_width div 22
if annValue_size is less than annValue_font_minSize then set annValue_size to annValue_font_minSize
set title_duration to 4
set title_timecode to my time2timecode((title_duration * time_scale), time_scale)
set credits_duration to ((count of ordered_credits) - 2) * 3
set credits_timecode to my time2timecode((credits_duration * time_scale), time_scale)
-- add the ordered credits to the text file
repeat with i from 1 to (count of ordered_credits)
if i is 1 then
-- remove the year from the title of the movie if it has one
set this_title to (item 2 of (item i of ordered_credits))
set this_title to my stripYear(this_title)
set title_credit to "{font:" & title_font & "}{size:" & title_size & "}" & title_style & this_title & return
set credits_text to credits_text & return & return & return & return & title_credit & spacer_line
else if i is 2 then
set item_name to (item 1 of (item i of ordered_credits))
set item_value to (item 2 of (item i of ordered_credits))
set this_credit to ¬
"{font:" & annName_font & "}{size:" & annName_size & "}" & annName_style & item_name & return & ¬
"{font:" & annValue_font & "}{size:" & annValue_size & "}" & annValue_style & item_value & return
set credits_text to credits_text & this_credit & title_timecode & return & "{dropShadow: off}{scrollIn:on}{scrollOut:on}" & return
else
set item_name to (item 1 of (item i of ordered_credits))
set item_value to (item 2 of (item i of ordered_credits))
if item_name is "Actors" then set item_value to my parseActors(item_value)
set this_credit to ¬
"{font:" & annName_font & "}{size:" & annName_size & "}" & annName_style & item_name & return & ¬
"{font:" & annValue_font & "}{size:" & annValue_size & "}" & annValue_style & item_value & return & return & return
set credits_text to credits_text & this_credit
end if
end repeat
-- set the time code for the credit
set credits_text to credits_text & credits_timecode & return
-- set the ending line time code
set end_time to end_duration * time_scale
set ending_timecode to my time2timecode(end_time, time_scale)
set end_credit to "{font:" & annName_font & "}{plain}{size:" & annName_size & "} " & return & ending_timecode & return
set credits_text to credits_text & end_credit
-- write the credits file
set target_file to ((path to temporary items folder as text) & "CREDITS_TEMP.TXT")
my writeTo(credits_text, target_file, false, string)
-- open the credits file in quicktime
set new_movie_status to open movie in new player
set open movie in new player to true
open file target_file
set open movie in new player to new_movie_status
-- insert the credits in the movie as defined by the property credits_overlay
tell movie 1
tell track 1 to set name to "Opening Credits Track"
rewind
select all
copy
select none
close saving no
end tell
tell movie movie_name
select none
rewind
if credits_overlay then
add
else
paste
end if
select none
rewind
select at 0 to 0
end tell
-- save and close the movie
close movie 1 saving yes
else
close movie 1 saving no
end if
else
display dialog "This movie has previously been set so that it cannot be copied, edited, or saved." & return & return & "Would you like to close this movie and continue processing the rest of the movies or stop the script?" buttons {"Close and Continue", "Stop"} default button 2
set button_entered to button returned of result
if button_entered is "Stop" then
return
else
close movie 1 saving no
end if
end if
on error
tell application "QuickTime Player" to if exists movie 1 then close every movie saving no
tell application "Finder" to tell file aMovie to set label index to 2
end try
end repeat
end tell
(*==================== SUBROUTINES ======================*)
on getName_andExtension(F)
set F to F as string
set {name:Nm, name extension:Ex} to info for file F
if Ex is missing value then set Ex to ""
if Ex is not "" then
set Nm to text 1 thru ((count Nm) - (count Ex) - 1) of Nm
set Ex to "." & Ex
end if
return {Nm, Ex}
end getName_andExtension
on supressAutoPlay(status_flag)
tell application "QuickTime Player"
set ignore auto play to the status_flag
set ignore auto present to the status_flag
end tell
end supressAutoPlay
on get_allAnns(movie_name) -- get all the annotations from the movie
set all_anns to {}
tell application "QuickTime Player" to tell movie movie_name
set annNames to name of annotations
set annValues to full text of annotations
repeat with i from 1 to count of annNames
set end of all_anns to {item i of annNames, item i of annValues}
end repeat
end tell
return all_anns
end get_allAnns
on orderCredits(ann_order, all_anns) -- order the annotations as defined in the script property ann_order
set ordered_credits to {}
repeat with i from 1 to count of ann_order
set this_ann to (item i of ann_order)
set ann_name to (item 1 of this_ann)
if (count of this_ann) > 1 then
set credit_name to item 2 of this_ann
else
set credit_name to item 1 of this_ann
end if
repeat with j from 1 to count of all_anns
set this_all_ann to (item j of all_anns)
set this_ann_name to item 1 of this_all_ann
set this_ann_value to item 2 of this_all_ann
if ann_name is this_ann_name then
set end of ordered_credits to {credit_name, this_ann_value}
exit repeat
end if
end repeat
end repeat
return ordered_credits
end orderCredits
on writeTo(this_data, target_file, append_data, mode) -- append_data is true or false, mode is string etc. (no quotes around either)
try
set target_file to target_file as Unicode text
if target_file does not contain ":" then set target_file to POSIX file target_file as Unicode text
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof as mode
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end writeTo
on time2timecode(this_time, movie_scale)
set the_secs to this_time / movie_scale
set sub_mins to the_secs div 60
set secs to the_secs mod 60
set hrs to sub_mins div 60
set mins to sub_mins mod 60
set hrs to (text -2 thru -1 of ("00" & hrs)) as string
set mins to (text -2 thru -1 of ("00" & mins)) as string
set decimal_offset to offset of "." in ("00" & secs)
if decimal_offset is 0 then
set secs to (text -6 thru -1 of ("00" & secs & ".000")) as string
else
set secs to text (decimal_offset - 2) thru (decimal_offset + 3) of ("00" & secs & "000") as string
end if
return "[" & hrs & ":" & mins & ":" & secs & "]"
end time2timecode
on stripYear(movie_title)
if movie_title contains "(" then
set x to offset of "(" in movie_title
if character (x + 5) of movie_title is ")" then
if length of movie_title > (x + 5) then
if character (x - 1) of movie_title is space then
set movie_title to (characters 1 thru (x - 2) of movie_title & characters (x + 6) thru -1 of movie_title) as string
else
set movie_title to (characters 1 thru (x - 1) of movie_title & characters (x + 6) thru -1 of movie_title) as string
end if
else
if character (x - 1) of movie_title is space then
set movie_title to (characters 1 thru (x - 2) of movie_title) as string
else
set movie_title to (characters 1 thru (x - 1) of movie_title) as string
end if
end if
end if
end if
return movie_title
end stripYear
on parseActors(actors_value)
set text item delimiters to ", "
set b to text items of actors_value
set text item delimiters to return
set actors_value to b as string
set text item delimiters to ""
return actors_value
end parseActors