adding chapters to a quicktime movie

See if you can fix this script supplied from Apple!

I came across a bunch of quicktime applescripts at http://www.apple.com/applescript/quicktime/. I thought they looked interesting so I decided to try them. Specifically I started with the ones about “chapters”. Basically with this bunch of scripts you can add chapter markers to quicktime movies. One problem… I can’t get it to work. Here’s what I did.

First I opened a quicktime movie which didn’t have any chapters in it. Then I ran the following script (Create Chapter Track.scpt) to add a blank chapter track to the movie… it worked fine.

tell application "QuickTime Player"
	activate
	
	try
		if not (exists movie 1) then error "No movies are open."
		
		stop every movie
		
		-- CHECK FOR THE CORRECT VERSION
		set QT_version to (QuickTime version as string)
		set player_version to (version as string)
		if (QT_version is less than "5.0") or ¬
			(player_version is less than "5.0") then
			error "This script requires QuickTime 5.0 or greater." & ¬
				return & return & ¬
				"Current QuickTime Version: " & QT_version & return & ¬
				"Current QuickTime Player Version: " & player_version
		end if
		
		-- CHECK FOR QUICKTIME PRO
		if QuickTime Pro installed is false then
			set the target_URL to "http://www.apple.com/quicktime/download/"
			display dialog "This script requires QuickTime Pro." & return & return & ¬
				"If this computer is currently connected to the Internet, " & ¬
				"click the "Upgrade" button to visit the QuickTime Website at:" & ¬
				return & return & target_URL buttons {"Upgrade", "Cancel"} default button 2
			ignoring application responses
				tell application "Finder"
					open location target_URL
				end tell
			end ignoring
			error number -128
		end if
		
		tell movie 1
			if the current chapter track is not {} then ¬
				error "The front movie already has a chapter track."
			set these_tracks to the name of every track
			set the link_track to choose from list these_tracks with prompt "Pick the track which the new chapter track describes:"
			if the link_track is false then error number -128
			set the link_track to the link_track as string
			set this_track to make new track at beginning with data "Start"
			set enabled of this_track to false
			set the name of this_track to "Chapter Track"
			set chapterlist of track link_track to track "Chapter Track"
			set the movie_length to the duration
			tell chapter 1
				set the time to 0
				set the duration to movie_length
			end tell
		end tell
	on error error_message number error_number
		if the error_number is not -128 then
			beep
			display dialog error_message buttons {"Cancel"} default button 1
		end if
	end try
end tell

Then I wanted to add a chapter marker to the empty chapter track that I added. So I moved the playhead in quicktime a little bit into the movie and then ran the following script (Add Chapter at Current Time.scpt) to make a chapter at that spot in the movie.

tell application "QuickTime Player"
	launch
	activate
	try
		if not (exists movie 1) then error "No movies are open."
		stop every movie
		tell movie 1
			set the chapter_track to the current chapter track
			if the chapter_track is {} then ¬
				error "This movie has no chapter track."
			set the current_time to the current time
			set the movie_end to the duration
			-- get chapter info
			set the chapter_list to the name of every chapter
			set the start_list to the time of every chapter
			set the duration_list to the duration of every chapter
			-- check to make sure the current time is not on a chapter start
			if the current_time is in the start_list then
				error "There already is a chapter which begins at the current time."
			else if the current_time is the movie_end then
				error "You cannot add a chapter at the end of a movie."
			end if
			-- prompt for the new chapter name
			set the new_chapter to ""
			repeat
				display dialog "Enter the name for the new chapter:" default answer new_chapter
				set the new_chapter to the text returned of the result
				if the new_chapter is "" then
					beep
				else if the new_chapter is in the chapter_list then
					display dialog "There already is a chapter named "" & new_chapter & ""."
				else
					exit repeat
				end if
			end repeat
			-- figure out how many chapters before the current time
			set the chapter_count to the count of the start_list
			set the chapter_index to the chapter_count
			repeat with i from 1 to the chapter_count
				set this_time to item i of the start_list
				if this_time is greater than the current_time then
					set the chapter_index to (i - 1)
					exit repeat
				end if
			end repeat
			-- CREATE NEW CHAPTER LIST
			if the chapter_index is 0 then
				-- THE NEW CHAPTER WILL BE THE FIRST
				set the new_chapterlist to the chapter_list
				set the beginning of the the new_chapterlist to the new_chapter
				set the new_startlist to the start_list
				set the beginning of the new_startlist to the current_time
				
				
				(*======== WARNING WARNING WARNING =========*)
				set the contents of the chapter_track to the new_chapterlist -------> see if you can fix this line!
				(*======== THIS IS THE PROBLEM LINE ==========*)
				
				
			else if the chapter_index is the chapter_count then
				-- THE NEW CHAPTER WILL BE THE LAST
				set the new_chapterlist to the chapter_list
				set the end of the new_chapterlist to the new_chapter
				set the new_startlist to the start_list
				set the end of the new_startlist to the current_time
				set the contents of the chapter_track to the new_chapterlist
			else
				set the new_chapterlist to ¬
					(items 1 thru chapter_index of the chapter_list) & ¬
					new_chapter & ¬
					(items (chapter_index + 1) thru -1 of the chapter_list)
				set the new_startlist to ¬
					(items 1 thru chapter_index of the start_list) & ¬
					current_time & ¬
					(items (chapter_index + 1) thru -1 of the start_list)
				set the contents of the chapter_track to the new_chapterlist
			end if
			-- APPLY PROPERTIES TO EVERY CHAPTER
			set the list_count to the count of the new_chapterlist
			repeat with i from 1 to the list_count
				if i is the list_count then -- last chapter
					set this_time to item i of the new_startlist
					set the time of chapter i to this_time
					set the duration of chapter i to ¬
						movie_end - this_time
				else
					set this_time to item i of the new_startlist
					set the time of chapter i to this_time
					set the duration of chapter i to ¬
						(item (i + 1) of the new_startlist) - this_time - 1
				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 {"Cancel"} default button 1
		end if
	end try
end tell

It didn’t work. I get an NSUnknownKeyScriptError. I found the line in the code which causes the error… I marked it in the script above so you can see it. I tried everything I could think of to fix the problem but couldn’t. CAN YOU FIX THIS???

I tried these scripts on two movies. The first script only worked on one of my movies.
The second script failed to work.
Maybe the success has something to do with the encoding of the movie.
Sorry I can’t help more.

Hi SwissalpS, thanks for trying. I don’t think it has to do with the encoding because I tried at least 4 different movies types and none of them worked. It’s that one line I highlighted. I need to figure out how to make that line work. I’m starting to believe that maybe these scripts were written for MacOS9 because a bunch of the scripts I found on that web page don’t work for me. But there must be a way to fix that code. It’s just one line!

Hi Jacques, I get a couple errors with your script. First this one errors because chapter_count is 0 when you have a new chapter track. It says “the variable i is not defined”.

repeat with i from 1 to chapter_count -- figure out how many chapters before the current time
				if item i of start_list > current_time then
					set i to i - 1
					exit repeat
				end if
			end repeat

So I tried commenting out that section and setting i to zero so the rest of the script would run. When I do this I get NSReceiverEvaluationScriptError: 4.

OK, I figured out why we’re getting the error NSReceiverEvaluationScriptError: 4.

in the script you have…
set x to movie_end - this_time
tell chapter i to set {duration, sample data} to {x, item i of chapter_list}

So when we tell chapter i to set its duration to x, this command actually deletes chapter i from the chapter list. So when we’re setting the first chapter and then we delete that chapter from the list then the chapter_list is empty ie. {}. So therefore when we execute the next command - set sample data to item i of chapter_list there is no item i and therefore the error.

I’m not sure why setting the duration deletes the chapter, but it does. It doesn’t delete all the chapters, just the chapter that we’re setting the duration of. Any thoughts?

Thanks for helping Jacques,

This is really weird. I tried your script on some movies of all different types. The one I was originally working with while developing my script is one I created using quicktime pro. It’s encoded using h.264 for video and aac for audio. It doesn’t work with your script. It does as I explained above… it deletes the chapter whenever the duration of the chapter is set. I then tried your script on some mpg movies that I get from my ReplayTV (that’s a dvr). It encodes as an mpeg2 muxed file, and it too deletes the chapter when the duration is set. But then I tried it on an avi which is divx encoded and a wmv which is windows media 8 encoded and your script worked for those files. It didn’t delete the chapter when setting the duration! How weird is that? I’m using the latest version of quicktime and the only plugins I have are perian and the flip4mac ones, so I don’t have non-standard stuff going on.

I had written a script earlier deleting all of the lines where the duration is set in the script and it works on the problem movies. Of course the duration of the chapters isn’t set properly but that doesn’t seem to cause me any problems. Can you think of any reason where having the duration improperly set would cause a problem?

Anyway, here’s my script… without the duration setting stuff… which works on all my movies… in case someone else has the same problems as me. Jacques, if you could try your script on the different movie types that I mentioned and let me know your results, I’d appreciate it. I’m wondering if it’s just me!

NOTE: I removed this script to save space in this thread. See below for a better version.

Well Jacques, I think I found the problem. It seems that each of the movies we’re having problems with have a non-standard time scale. According to quicktime documents on Apple’s website, a standard time scale for movies is 600. When I saw this I checked and all of my problem movies had a time scale other than 600. So I modified my script such that when the time scale of a movie is 600 then I set the duration properly and when the time scale isn’t 600 then I don’t set the duration of the chapters. This seems to be the best compromise to avoid the problems.

Let me know what you think. Could you check your problem movie for the time scale and verify that it isn’t 600?

Here’s my modified script…

NOTE: I removed this script to save space in this thread. See below for a better version.

Thanks regulus6633, I’ll be implementing what you found into my script.
Your latest post worked fine until I tried this Movie that acts weirdly:
Format: Apple Cinepak
DataRate: 4041.10 kbits/sec
TimeScale: 600
Audio: None

I remember that I made it from a MUXED (audio in video track) movie and lost the audio in the process.
when I run your script on it, I get NSReceiverEvaluationScriptError: 4
and video track is deleted. Edit: it wasn’t deleted, just disabled and renamed
The same happens when I force:
set can_set_duration to false

in makeChapterTrack(…, …, …) the following line should make the new track
set this_track to make new track at beginning with data chapter_name
however when I look in QT’s tracklist (Apple+J) there is no new track.

The next line then disables the video track
Then video track is renamed to “Chapter Track”

now link_track is “Video Track” but there is no longer a track with that name → error

Edit: for the record; I tested this on QT Pro 7.1.6.

It sounds like that particular movie won’t even let you add a chapter track to it. Here’s something to try. Try adding a chapter track manually. It’s not hard. Here’s how:

copy/paste the following into a text editor and save it as a plain text file. Set the timeScale value to the frames per second of the movie. Set the last time code to the length of your movie in hh:mm:ss.fraction format. Basically this is setting up 2 chapters, one at the beginning called start and one at 20 seconds callled chapter1.

{QTtext}{timeScale:30}
[00:00:00.0]
start
[00:00:20.0]
chapter1
[00:01:35.52]

Next drag that txt file onto the quicktime icon so that it opens as a movie. Then “select all” and then “copy”. You can close this text movie now. Now open up your video and “select all” and “add to selection & scale”. Then show the movie properties for the video and you should see a text track. Uncheck the text track. Click on the video track and go to the “other settings” tab. Under the chapters pop-up select “text track”. Now you should have the chapters showing in the video.

Does that work? If that works then I’m not sure why my script couldn’t add the chapter track as normal. Anyway, I added some error checking to my script. Here’s an updated version. It won’t fix the problem but it should catch the problem. Let me know if this catches your error.

(* This script will help you create chapters in a quicktime movie. You open a movie in quicktime player, place the playhead to the place 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 "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 Jacques at the forums of MacScripter BBS found here: http://bbs.applescript.net/viewtopic.php?pid=82150#p82150 *)

(* 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
			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 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
			set this_track to make new track at beginning with data chapter_name
			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 was able to create a chapter track with chapters in the mentioned cinepak movie using my “hand” - method that normally works for me.

Your newest release doesn’t Make any track and also doesn’t Mess up the existing tracks and doesn’t display an error message.

good luck

I updated the above script, it should show you an error message now. If you figure out why the script won’t create a chapter track let me know.

The message is great.
I’m currently quite busy with a data source headache, but I found the time to export another movie to Apple Cinepak and your latest script worked fine.
Also when I export the problematic movie with the same properties, its exported clone works.
Also a clone to desktop made with finder works —> seems to have something to do with the fact that the problematic movie is on a “read-only” disk image.
might want to include that check in the script :wink:
that is, if you experience a problem with “read-only” residence too :o

Good, I’m glad to hear it. I did a bunch of testing and reading before I came up with that conclusion. Most of the stuff I want to add chapters to comes from my dvr, which creates movies with the non-standard time scale, so I was interested in finding out why they were causing problems.

I did a little checking on how to change the time scale of a movie hoping that I could fix my problem, but I haven’t found a solution. I figure I’d have to change both the time scale and the duration for it to work. There is a tool created by Apple called dumpster that lets you see the headers of a file and make changes, but it’s so complicated because there’s so many headers that I couldn’t figure out the right ones to change. I only ended up messing up the movie… so I’m giving up on that idea… unless someone has a way to do that.

have you considered exporting the movies? Probably not the fastest solution - should work though

Can you set the time scale when you export a movie? You can set the data rate and the frame rate, but I don’t think this impacts the time scale.

I can’t so much as set the time scale, it defaults to 6oo
I haven’t tried all variations of formats, but so far it seems to work.
Apple’s “Get A Mac” ads have a time scale of 2997 after exporting 6oo :smiley:

I did some checking on this and found that I could use quicktime to change the time scale of a movie to 600 as you mentioned SwissalpS. I didn’t want to use the export command though because then you have to recompress an already compressed file which 1) taks a long time and 2) you also lose quality in the movie.

So what I tried is just doing a “save-as” to a new file. That didn’t quite work because the new file also had the same time scale… but it was close. What I had to do was extract the video and audio tracks into new separate windows using the “show movie properties” window. Then I copied one and “add scaled” to the other basically re-combining them in one of the new windows. Then I used “save-as” on the newly combined file and it worked.

So thanks for pointing me in the right direction SwissalpS. It doesn’t take long to do because you’re not re-encoding the movie.

Thanks for investigating on that. I’m glad there is a faster way.
This work-around could probably be scripted. (says my feeling, haven’t tried as I’m still debugging big time on data source issues)

:smiley: regulus6633 has saved the day again! :cool:

FYI: I posted 4 scripts which will help you do anything you want to a quicktime video… the first one performs the conversion process. You can see them 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

Finally I found some time to work with the findings of this thread.
Linking text tracks to other tracks as chapter track has been consuming a lot of my time.

Here’s my stumbling line:

set chapterlist of track a to track b

oddly it has worked for me but mostly it just quietly does nothing or sets the chapter track to “none
I have tried several different formulations, but it just won’t link up my tracks.

so here’s my snippet of my work-around:

-- have a valid (time scale 600) chaptered mov open in QTPP (QuickTime Player Pro)

tell application "QuickTime Player"
	set myMovie to movie 1
end tell

QTlinkChapterTrack(myMovie, "", "")

to QTlinkChapterTrack(myMovie, textTrackName, link2trackName)
	try
		tell application "QuickTime Player" to tell myMovie
			if "" = textTrackName then
				set textTrackName to my getTrackName(name of every track whose data format = "text")
			end if
			if "" = link2trackName then
				set link2trackName to my getLinkTrackName(name of tracks)
			end if
			-- here's my headache starter
			set chapterlist of track link2trackName to track textTrackName
			-- and this my "make sure it's done" dialog
			tell me to activate
			tell me to display dialog "Please check if connection was created properly for track \"" & link2trackName & "\" to text track \"" & textTrackName & "\", and adjust manually as needed (Command+J). Only then continue" buttons {"Continue"} default button 1
			return true
		end tell -- QuickTime myMovie
	on error eMsg number eNum
		eHandler(eMsg, eNum)
		return false
	end try
end QTlinkChapterTrack

to getLinkTrackName(trackNamesList)
	set a to "false"
	tell me to activate
	repeat while "false" = a
		set a to (choose from list trackNamesList default items {} OK button name "Link" cancel button name "" with title "Choose a Track" with prompt "Please pick the track which your chapters will link to" without multiple selections allowed and empty selection allowed) as Unicode text
	end repeat
	return a
end getLinkTrackName

to getTrackName(trackNamesList)
	tell me to activate
	set a to "false"
	repeat while "false" = a
		set a to (choose from list trackNamesList default items {} OK button name "Choose" cancel button name "" with title "Choose a Track" with prompt "Please pick the chapter track" without multiple selections allowed and empty selection allowed) as Unicode text
	end repeat
	return a
end getTrackName

I’m using OS X 10.4.10, QTPP 7.1.6
Any test results are greatly appreciated.