Perfect! My hack was close enough, but this gets even more exact; rounding is certainly fine.
FWIW, here is my working script. I say working, not complete, as there are still some things I’d like to do. It requires an XML from a Final Cut sequence. That sequence must contain sequence markers that have both an in and out and a comment. But of course, that is the whole point: line up transcipts of a video within the sequence, using markers to determine when the captions will turn on and off. This will then generate an XML file for Flash captions and an SRT file for YouTube captions.
It also needs the XMLLib addition from http://www.satimage.fr/software/en/downloads/downloads_companion_osaxen.html
I installed this in my User/Library/ScriptingAdditions folder as opposed to the system library.
I realize this may not be the most efficient or prettiest, but for now it does what I need it to do. That said, I’d love any comments for improvement or things that I’ve done glaringly wrong.
Thanks again for the help!
Mike
property FrameRate : 30
set theXML to XMLOpen (choose file with prompt "Select the XML file which contains your caption markers" without invisibles)
set the_root to XMLRoot theXML
set the_child to XMLChild the_root index 1
set theTitle to XMLChild the_child index 3
set youtubeTitle to (XMLGetText theTitle) & " - YouTube Captions"
set flashTitle to (XMLGetText theTitle) & " - Flash Captions"
set allMarkers to XMLXPath the_child with "marker/name"
set theMarkers to XMLGetText (allMarkers)
set startMarker to 11
set theIndex to startMarker
set theList to {}
set desktop_ to path to desktop as Unicode text
--create an .xml file on the desktop and add the xml header in the proper format for Flash
set theHeader to setHeader()
write_to_Flashfile(theHeader, (desktop_ & flashTitle & ".xml"), true)
repeat with my_item in theMarkers
try
set the_child_2 to XMLChild the_child index theIndex
set theMarker to XMLGetText (XMLChild the_child_2 index 1)
set theComment to XMLGetText (XMLChild the_child_2 index 2)
set inFrame to XMLGetText (XMLChild the_child_2 index 3)
set outFrame to XMLGetText (XMLChild the_child_2 index 4)
set theDuration to ((inFrame) - (outFrame))
--convert times from frames to hh:mm:ss,000
set inYouTube to (framesToYouTubeTime from inFrame by FrameRate)
set outYouTube to (framesToYouTubeTime from outFrame by FrameRate)
--convert times from frames to hh:mm:ss:ff
set inFlash to (framesToFlashTime from inFrame by FrameRate)
set outFlash to (framesToFlashTime from outFrame by FrameRate)
--create list of comment index, comment, in point, out point, and duration
set tempList to {theMarker, theComment, inYouTube, outYouTube, theDuration}
--write the list to an .srt file on the desktop in the proper format for YouTube
write_to_file(return & theIndex - 10 & return & item 3 of tempList & " --> " & item 4 of tempList & return & item 2 of tempList & return, (desktop_ & youtubeTitle & ".srt"), true)
--write the list to an .xml file on the desktop in the proper format for Flash
write_to_Flashfile(return & "<p begin=\"" & inFlash & "\" end=\"" & outFlash & "\" style=\"1\">" & theComment & "</p>", (desktop_ & flashTitle & ".xml"), true)
set theIndex to theIndex + 1
end try
end repeat
--add the xml footer in the proper format for Flash
set theFooter to setFooter()
write_to_Flashfile(theFooter, (desktop_ & flashTitle & ".xml"), true)
-- Subroutine to write to UTF-8 file
to write_to_Flashfile(this_data, target_file, append_data)
try
set the target_file to the target_file as 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 as «class utf8» starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_Flashfile
-- Subroutine to write to text file
to write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as 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 as «class utf8» starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
--Subroutine to convert frames to YouTube timecode in format hh:mm:ss,000
on framesToYouTubeTime from ti by rate
tell ti div rate to tell (1000000 + it div hours * 10000 + it mod hours div minutes * 100 + it mod minutes) as text to return text 2 thru 3 & ":" & text 4 thru 5 & ":" & text 6 thru 7 & "," & text 2 thru 4 of ((1000 + ti mod rate * 1000 / rate) as text)
end framesToYouTubeTime
--Subroutine to convert frames to timecode in format hh:mm:ss:ff
on framesToFlashTime from ti by rate
tell ti div rate to tell (100000000 + it div hours * 1000000 + it mod hours div minutes * 10000 + it mod minutes * 100 + ti mod rate) as text to return text 2 thru 3 & ":" & text 4 thru 5 & ":" & text 6 thru 7 & ":" & text 8 thru 9
end framesToFlashTime
--Subroutine to write XML header for Flash captions
on setHeader()
set theHeader to "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" & return
set theHeader to theHeader & "<tt xml:lang=\"en\" xmlns=\"http://www.w3.org/2006/04/ttaf1\" xmlns:tts=\"http://www.w3.org/2006/04/ttaf1#styling\">" & return & return
set theHeader to theHeader & "<head>" & return
set theHeader to theHeader & "<styling>" & return
set theHeader to theHeader & "<style id=\"1\"" & return
set theHeader to theHeader & tab & "tts:fontFamily=\"_sans\"" & return
set theHeader to theHeader & tab & "tts:color=\"#FFFFFF\"" & return
set theHeader to theHeader & tab & "tts:fontWeight=\"bold\"" & return
set theHeader to theHeader & tab & "tts:fontSize=\"16\"" & return
set theHeader to theHeader & tab & "tts:backgroundColor=\"transparent\" />" & return
set theHeader to theHeader & "</styling>" & return
set theHeader to theHeader & "</head>" & return & return
set theHeader to theHeader & "<body>" & return
set theHeader to theHeader & "<div xml:lang=\"en\">"
end setHeader
--Subroutine to write XML header for Flash captions
on setFooter()
set theFooter to "</div>" & return
set theFooter to theFooter & "</body>" & return
set theFooter to theFooter & return & "</tt>"
end setFooter