Script 4 of 4. Add chapter markers to a video

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 4 of 4. Add chapter markers to a video:
This script works on the front movie in QuickTime Player. This script is only necessary if you want to add chapter markers to a video file. You move the playhead in quicktime to the location where you want to add a chapter and run the script. The script asks you for a name for the chapter and then makes the chapter marker at that location.

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 will help you create chapters in a quicktime movie. You open a movie in quicktime player, place the playhead where you want to add the chapter, and run this script. The script will prompt you for the name and then create the chapter. If the movie doesn't contain a text track where you can place the chapters, then this script will automatically add a text track called "Chapter Track" for you. *)

(* Note: this script is a modified version of scripts I got from here: http://www.apple.com/applescript/quicktime/ and code from the forums of MacScripter BBS found here: http://bbs.applescript.net/viewtopic.php?id=21357 *)

(* Note: I found a problem in quicktime 7 with setting the duration of a chapter when the time scale of the movie is not 600. In these cases, setting a chapter's duration would cause quicktime to delete the chapter and thus not allow the script to work properly. As such, my work-around for this problem is to not set a chapter's duration for movies with a time scale different than 600. Be aware that the durations of the chapters are incorrect in these cases, although I haven't seen any detrimental effects from this. All movies with a time scale of 600 are set properly. *)

tell application "QuickTime Player"
	activate
	try
		if not (exists front movie) then error "Error: No movies are open!"
		set movie_name to name of front movie
		stop movies
		tell movie movie_name
			if saveable is false then error "This movie has previously been set so that it cannot be copied, edited, or saved."
			set new_chapter to my newChapterName(movie_name) -- prompt for a name of the new chapter
			set {time_scale, current_time, movie_end} to {time scale, current time, duration} -- get movie properties
			
			-- check time scale for value of 600 to see if we can set chapter duration properly
			if time_scale is 600 then
				set can_set_duration to true
			else
				display dialog "The time scale of this movie is not 600. You can still make chapters in this movie although the duration of the chapters will not be correct." & return & return & "Would you like to \"Continue\" and make the chapter anyway or do you want to \"Stop\" the script now?" buttons {"Stop", "Continue"} default button 2
				set button_returned to button returned of result
				if button_returned is "Continue" then
					set can_set_duration to false
				else
					return
				end if
			end if
			
			-- if there's not a chapter track then add one
			if current chapter track is {} then
				if current_time is 0 then
					set make_chapter_track to my makeChapterTrack(movie_name, new_chapter, can_set_duration)
					if not make_chapter_track then error "Error: The new chapter track was improperly made!" & return & return & "Please close the movie and DO NOT save any changes. Check to make sure you have write privileges on the volume containing the movie."
					return
				else
					set make_chapter_track to my makeChapterTrack(movie_name, "Start", can_set_duration)
					if not make_chapter_track then error "Error: The new chapter track was improperly made!" & return & return & "Please close the movie and DO NOT save any changes. Check to make sure you have write privileges on the volume containing the movie."
				end if
			end if
			
			-- get chapter info
			set {chapter_list, start_list, duration_list, chapter_count} to {sample data, time, duration, count} of chapters
			
			-- check to make sure the current time is not on a chapter start
			if current_time is in start_list then
				error "Error: There already is a chapter which begins at the current time."
			else if current_time = movie_end then
				error "Error: You cannot add a chapter at the end of a movie."
			end if
			
			-- figure out how many chapters before the current time
			repeat with i from 1 to chapter_count
				if item i of start_list > current_time then
					set i to i - 1
					exit repeat
				end if
			end repeat
			
			-- create the new chapter list
			if i = 0 then -- the new chapter will be first
				set beginning of chapter_list to new_chapter
				set beginning of start_list to current_time
			else if i = chapter_count then -- the new chapter will be last
				set end of chapter_list to new_chapter
				set end of start_list to current_time
			else
				tell chapter_list to set chapter_list to items 1 thru i & new_chapter & (items (i + 1) thru -1)
				tell start_list to set start_list to items 1 thru i & current_time & (items (i + 1) thru -1)
			end if
			
			-- set the chapter list of the movie
			set the contents of current chapter track to chapter_list
			
			-- apply properties to every chapter
			set chapter_count to (chapter_count + 1)
			repeat with i from 1 to chapter_count
				set this_time to item i of start_list
				if can_set_duration then
					if i = chapter_count then -- last chapter
						set x to movie_end - this_time
					else
						set x to (item (i + 1) of start_list) - this_time - 1
					end if
					tell chapter i to set {time, duration, sample data} to {this_time, x, item i of chapter_list}
				else
					tell chapter i to set {time, sample data} to {this_time, (item i of chapter_list)}
				end if
			end repeat
		end tell
	on error error_message number error_number
		if the error_number is not -128 then
			beep
			display dialog error_message buttons {"OK"} default button 1
		end if
	end try
end tell

(*================ SUBROUTINES ==================*)
on newChapterName(movie_name)
	set new_chapter to ""
	tell application "QuickTime Player" to tell movie movie_name
		set chapter_list to sample data of chapters
		repeat
			set new_chapter to text returned of (display dialog "Enter the name for the new chapter:" default answer new_chapter)
			if new_chapter is in chapter_list then
				display dialog "Error: There already is a chapter named \"" & new_chapter & "\"."
				error number -128
			else if new_chapter is not "" then
				exit repeat
			end if
		end repeat
	end tell
	return new_chapter
end newChapterName

on makeChapterTrack(movie_name, chapter_name, can_set_duration)
	try
		tell application "QuickTime Player" to tell movie movie_name
			set these_tracks to the name of every track
			set track_count to count of tracks
			set the link_track to choose from list these_tracks with prompt "This is the first chapter you're adding to this movie. Please pick the track which your chapters will link to."
			if link_track is false then error number -128
			set link_track to link_track as string
			try
           set this_track to make new track at beginning with data chapter_name
       on error
           set name of last track to chapter_name
           set this_track to last track
       end try
			set new_track_count to count of tracks
			if new_track_count is not (track_count + 1) then error
			tell this_track
				set enabled to false
				set preload to true
				set name to "Chapter Track"
			end tell
			set chapterlist of track link_track to track "Chapter Track"
			tell chapter 1 to set the time to 0
			if can_set_duration then
				set movie_duration to the duration
				tell chapter 1 to set duration to movie_duration
			end if
		end tell
		if new_track_count is not (track_count + 1) then error
		return true
	on error
		return false
	end try
end makeChapterTrack

I found several bugs in the above script with version 7.6.6 of quicktime player. Here’s a version that works.

NOTE: in Snow Leopard the name of the application is “Quicktime Player 7”. I’m using 10.6 so this script has Quicktime Player 7 in it. If you need the script to run on 10.5 or earlier change that back to Quicktime Player.

(* This script will help you create chapters in a quicktime movie. You open a movie in QuickTime Player 7, place the playhead where you want to add the chapter, and run this script. The script will prompt you for the name and then create the chapter. If the movie doesn't contain a text track where you can place the chapters, then this script will automatically add a text track called "Chapter Track" for you. *)

(* Note: this script is a modified version of scripts I got from here: http://www.apple.com/applescript/quicktime/ and code from the forums of MacScripter BBS found here: http://bbs.applescript.net/viewtopic.php?id=21357 *)

(* Note: I found a problem in quicktime 7 with setting the duration of a chapter when the time scale of the movie is not 600. In these cases, setting a chapter's duration would cause quicktime to delete the chapter and thus not allow the script to work properly. As such, my work-around for this problem is to not set a chapter's duration for movies with a time scale different than 600. Be aware that the durations of the chapters are incorrect in these cases, although I haven't seen any detrimental effects from this. All movies with a time scale of 600 are set properly. *)

tell application "QuickTime Player 7"
	activate
	try
		if not (exists front document) then error "Error: No movies are open!"
		set movie_name to name of front document
		stop every document
		tell document movie_name
			if saveable is false then error "This movie has previously been set so that it cannot be copied, edited, or saved."
			set new_chapter to my newChapterName(movie_name) -- prompt for a name of the new chapter
			set {time_scale, current_time, movie_end} to {time scale, current time, duration} -- get movie properties
			
			-- check time scale for value of 600 to see if we can set chapter duration properly
			if time_scale is 600 then
				set can_set_duration to true
			else
				set can_set_duration to false
			end if
			
			-- if there's not a chapter track then add one
			if current chapter track is {} then
				if current_time is 0 then
					set make_chapter_track to my makeChapterTrack(movie_name, new_chapter, can_set_duration)
					if not make_chapter_track then error "Error: The new chapter track was improperly made!" & return & return & "Please close the movie and DO NOT save any changes. Check to make sure you have write privileges on the volume containing the movie."
					return
				else
					set make_chapter_track to my makeChapterTrack(movie_name, "Start", can_set_duration)
					if not make_chapter_track then error "Error: The new chapter track was improperly made!" & return & return & "Please close the movie and DO NOT save any changes. Check to make sure you have write privileges on the volume containing the movie."
				end if
			end if
			
			-- get chapter info
			set {chapter_list, start_list, duration_list, chapter_count} to {sample data, time, duration, count} of every chapter
			
			-- check to make sure the current time is not on a chapter start
			if current_time is in start_list then
				error "Error: There already is a chapter which begins at the current time."
			else if current_time = movie_end then
				error "Error: You cannot add a chapter at the end of a movie."
			end if
			
			-- figure out how many chapters before the current time
			repeat with i from 1 to chapter_count
				if item i of start_list > current_time then
					set i to i - 1
					exit repeat
				end if
			end repeat
			
			-- create the new chapter list
			if i is 0 then -- the new chapter will be first
				set beginning of chapter_list to new_chapter
				set beginning of start_list to current_time
			else if i is chapter_count then -- the new chapter will be last
				set end of chapter_list to new_chapter
				set end of start_list to current_time
			else
				tell chapter_list to set chapter_list to items 1 thru i & new_chapter & (items (i + 1) thru -1)
				tell start_list to set start_list to items 1 thru i & current_time & (items (i + 1) thru -1)
			end if
			
			-- set the chapter list of the movie
			set the contents of current chapter track to chapter_list
			
			-- apply properties to every chapter
			set chapter_count to (chapter_count + 1)
			repeat with i from 1 to chapter_count
				set this_time to item i of start_list
				if can_set_duration then
					if i is chapter_count then -- last chapter
						set x to movie_end - this_time
					else
						set x to (item (i + 1) of start_list) - this_time - 1
					end if
					tell chapter i to set {time, duration, sample data} to {this_time, x, item i of chapter_list}
				else
					tell chapter i to set {time, sample data} to {this_time, (item i of chapter_list)}
				end if
			end repeat
		end tell
	on error error_message number error_number
		if the error_number is not -128 then
			beep
			display dialog error_message buttons {"OK"} default button 1
		end if
	end try
end tell

(*================ SUBROUTINES ==================*)
on newChapterName(movie_name)
	set new_chapter to ""
	tell application "QuickTime Player 7" to tell document movie_name
		try
			set chapter_list to sample data of every chapter
		on error
			set chapter_list to {}
		end try
		repeat
			set new_chapter to text returned of (display dialog "The playhead in QuickTime should be where you want this new chapter created." & return & return & "Enter the name for the new chapter:" default answer new_chapter with title "Create New Chapter")
			if new_chapter is in chapter_list then
				display dialog "Error: There already is a chapter named \"" & new_chapter & "\"."
				error number -128
			else if new_chapter is not "" then
				exit repeat
			end if
		end repeat
	end tell
	return new_chapter
end newChapterName

on makeChapterTrack(movie_name, chapter_name, can_set_duration)
	try
		tell application "QuickTime Player 7" to tell document movie_name
			set these_tracks to the name of every track
			set track_count to count of every track
			set link_track to item 1 of these_tracks
			if link_track is false then error number -128
			set link_track to link_track as string
			try
				set this_track to make new track at beginning with data chapter_name
			on error
				set name of last track to chapter_name
				set this_track to last track
			end try
			--set this_track to make new track at beginning with data chapter_name
			set new_track_count to count of every track
			if new_track_count is not (track_count + 1) then error
			tell this_track
				set enabled to false
				set preload to true
				set name to "Chapter Track"
			end tell
			set chapterlist of track link_track to track "Chapter Track"
			tell chapter 1 to set the time to 0
			if can_set_duration then
				set movie_duration to the duration
				tell chapter 1 to set duration to movie_duration
			end if
		end tell
		if new_track_count is not (track_count + 1) then error
		return true
	on error
		return false
	end try
end makeChapterTrack

There is still a problem with the makeChapterTrack routine

Running the script on a movie with no chapter track, I get (in the Event Log):

tell application "QuickTime Player"
	activate
	exists document 1
		true
	get name of document 1
		"Critter Sitters"
	stop every document
	get saveable of document "Critter Sitters"
		true
	get sample data of every chapter of document "Critter Sitters"
	display dialog "The playhead in QuickTime should be where you want this new chapter created.

Enter the name for the new chapter:" default answer "" with title "Create New Chapter"
		{text returned:"0", button returned:"OK"}
	get time scale of document "Critter Sitters"
		1000
	get current time of document "Critter Sitters"
		219809
	get duration of document "Critter Sitters"
		1359559
	get current chapter track of document "Critter Sitters"
		{}
	get name of every track of document "Critter Sitters"
		{"Video Track", "Sound Track"}
	count every track of document "Critter Sitters"
		2
	make new track at beginning of document "Critter Sitters" with data "Start"
		last <<class>>
        count every track of document "Critter Sitters"
		3
	set enabled of last <<class>>  to false
	beep
	display dialog "Error: The new chapter track was improperly made!

Please close the movie and DO NOT save any changes. Check to make sure you have write privileges on the volume containing the movie." buttons {"OK"} default button 1
		{button returned:"OK"}
end tell

So it is aborting on the line “set enabled to false” for some reason.

Once the track is created, however, it adds new markers without a hitch.

But this is still a head-scratcher.

Model: Intel iMac
AppleScript: 2.0.1
Browser: Safari 531.22.7
Operating System: Mac OS X (10.5)