srt_util- SubRip Text (SRT) File Utilities
The SRT_UTIL package provides functions for reading, manipulating, and saving SubRip Text (SRT) subtitle files.
An SRT file is a text file containing the subtitles for a video. Each subtitle is in the following format:
sequence # HH:MM:SS,LLL --> HH:MM:SS,LLL -- Beginning and ending display times. first line of subtitle ... last line of subtitle -- Blank line signalling end of record.
172 00:09:28,340 --> 00:09:30,880 JOHN: George Harrison, the scouse of distinction. blank line
Assume an existing SRT file is to be modified. An application must (i) create an empty list of subtitles, (ii) read the subtitles from the file and add them to the list, (iii) modify the subtitles as desired, and (iv) save the list of modified subtitles to a file:
SubtitleList list ; srtListCreate (&list) ; -- Empty list. srtListLoad (list, "input file", -1) ; -- Read file. ... modify the subtitles in the list ... srtListSave (list, "output file", -1) ; -- Write file. srtDestroyList (list) ; -- All done!
Individual subtitles in a list can be found by sequence number
srtListFind() or by position (1..N)
srtListGet(). When chopping up a list, the
sequence numbers can get out of order; regenerating a normal
sequence of numbers is done with
In the case of inserting a new subtitle in an existing SRT file or adding it to a brand new SRT file, the following example (i) creates a new subtitle; (ii) sets its sequence number (1768), beginning and ending display times, and lines of text; and (iii) adds it to the end of a list like the one above:
Subtitle caption ; srtCreate (1768, &caption) ; srtSetTimes (caption, srtStringToTime ("01:35:38,566"), srtStringToTime ("01:35:40,899")) ; srtAddLine (caption, "There's nothing wrong with you", -1) ; srtAddLine (caption, "that can't be cured with a", -1) ; srtAddLine (caption, "little Prozac and a polo mallet.", -1) ; srtListAdd (list, caption, -1) ;
Attributes of a subtitle can retrieved or modified by name with
A subtitle's display times can be accessed with those two
functions or, more directly, with
I wrote my subtle program and this function package for the purpose of synchronizing subtitles with a video's audio track. The program and package assume that the subtitles (i) are already synchronized, (ii) have a constant offset from the audio throughout the video, or (iii) have an offset that varies linearly with time. The SRT_UTIL package can calculate the equation of the line in the latter two cases (and the trivial first case as well).
The user must supply the offsets in seconds of two widely separated subtitles, ideally from the beginning and end of the video. The offsets are more or less easily measured by watching the video and listening for what's said in the subtitle of interest to begin being said. Pause the video immediately and compare the video's timestamp to the subtitle's beginning time. Subtract the subtitle's time from the video's time. If the difference (offset) is positive, that means the subtitle appears too early and must be delayed the given number of seconds. If the difference is negative, that means the subtitle appears too late and must be moved up by the (absolute value) number of seconds.
The following code fragment calculates the equation of the line connecting the synchronized (shifted) times of two subtitles:
Subtitle caption1, caption2 ; double offset1, offset2, slope, yIntercept ; caption1 = srtListGet (list, 2) ; -- Second subtitle. offset1 = 3.75 ; -- Observed offset. caption2 = srtListGet (list, -1) ; -- Next-to-last subtitle. offset1 = 15.0 ; -- Observed offset. srtCalcMXB (caption1, offset 1, caption2, offset2, &slope, yIntercept) ;
The synchronized beginning and ending times of any subtitle in the list can be computed by substituting the unsynchronized times into the equation:
sync-time = (slope × unsync-time) + y-intercept
In the case of a constant offset throughout the video,
srtCalcMXB() can be skipped altogether —
the slope is simply 1 and the y-intercept is the offset.
NOTE because I get confused myself:
with a graph that maps unsynchronized times (along the x-axis)
to synchronized times (y-axis). If the subtitles are perfectly
aligned with the audio, the modeled line would be a 45-degree diagonal
through the origin (y = 1x + 0 = x). If the offset
is constant throughout the video, there would again be a 45-degree
diagonal positioned above or below the origin by the offset.
Confusion sets in for me when I offhandedly visualize the graph,
as the image that immediately comes to mind is a graph of the offsets
versus the uncorrected times. Thus I picture a constant offset as a
horizontal line parallel to the x-axis instead of the 45-degree
line whose equation
srtCalcMXB() actually returns. Each
approach works — I just happened to choose the synchronized
times approach (which, incidentally, saves one floating-point addition
when applying the equation to a raw time!).
All of the subtitles in the list can be corrected with a single call:
srtListApplyMXB (list, slope, yIntercept) ;
srtAddLine()- adds a line of text to a subtitle.
srtApplyMXB()- adjusts the begin and end display times of a subtitle.
srtCalcMXB()- find the line connecting the shifted times of two subtitles.
srtCheck()- checks two adjacent captions for various errors.
srtCreate()- creates a single subtitle.
srtDestroy()- destroys a subtitle.
srtDuplicate()- duplicates a subtitle.
srtGet()- gets the value of a subtitle attribute.
srtGetTimes()- gets a subtitle's beginning and ending display times.
srtReadFile()- reads a subtitle from a disk file.
srtReadString()- reads a subtitle from a string.
srtSet()- sets the value of a subtitle attribute.
srtSetTimes()- sets a subtitle's beginning and ending display times.
srtStringToTime()- converts a string to a subtitle time.
srtTimeToString()- converts a subtitle time to a string.
srtListAdd()- adds/inserts a subtitle to/in a list.
srtListApplyMXB()- adjusts the times of all the subtitles in a list.
srtListCreate()- creates an empty list of subtitles.
srtListDelete()- deletes a subtitle from a list.
srtListDestroy()- destroys a list of subtitles.
srtListFind()- finds a subtitle by sequence number.
srtListGet()- retrieves a subtitle by position.
srtListLength()- returns the number of subtitles in a list.
srtListLoad()- loads subtitles from a disk file.
srtListMerge()- merges two lists into a new list.
srtListRenumber()- renumbers the subtitles in a list.
srtListSave()- saves subtitles to a disk file.