Subsync
synchronize .srt or .ssa subtitles with the video timeline
Install / Use
/learn @xuminic/SubsyncREADME
Adjust Subtitle Timing with Subsync
Subsync is a command-line tool used to adjust the timeline of subtitle files so that audio and subtitles stay synchronized. It can:
- Shift subtitle display times forward or backward by a specified offset
- Scale subtitle timing proportionally to adjust drift
- Adjust subtitles only within a specified time range
- Support
.srt,.ass, and.ssasubtitle formats - A filtering program written in C — simple and fast
- Rely only on the standard C runtime library, making it portable to all operating systems
- A command-line tool, making it easy to integrate into scripts
Why Subsync Is Needed
I have some old TV series and .srt subtitle files found online,
but many of them are out of sync.
Since the structure of .srt is very simple, in theory you only need
to extract the timestamps, adjust them slightly, and write them back.
Surprisingly, all I could find were large GUI programs, not the lightweight command-line tool I wanted. Even worse, I couldn’t find any tool that could scale the subtitle timeline. Some videos run at 30 fps, while the matching subtitles were created for 25 fps. At the beginning, the video and subtitles are in sync, but the further you go, the larger the drift becomes. A simple time offset won’t fix this. So I wrote this small program to fill that gap.
Build and Install
You can fetch the source code from GitHub and compile it:
git clone https://github.com/xuminic/subsync.git
cd subsync
make
If everything goes well, it should produce the subsync executable. You can move it anywhere on your system path.
To build the Windows version, you can compile directly on Windows
using MinGW64 or Cygwin, or cross-compile on Linux using MinGW,
for example:
apt install mingw-w64
Then, inside the subsync directory:
make allwin
make will automatically download libiconv-1.18.tar.gz, compile it,
and generate both Win32 and Win64 versions of the subsync executable.
- You can place
libiconv-1.18.tar.gzin the subsync directory in advance to allow offline compilation - The Windows executables are named as:
subsync_i686.exeandsubsync_x86_64.exe - Prebuilt Windows binaries are available directly in the GitHub Releases section
- There is no installer for Windows — simply copy and use the program
Command Line Options
-
If no filename is specified,
subsyncreads fromstdinand writes tostdout, for example:subsync +12000 < source.ass > target.ass -
Any argument that is not a command-line option is treated as an input filename. You mau use the
-woption to specify the output filename. For example:subsync +12000 -w target.ass source.assThis command is equivalent to the previous one.
-
You may specify multiple filenames in a single command, for example:
subsync +12000 source1.ass source2.ass source3.assHowever, all output will be combined and written to
stdout. The same applies when using-w:subsync +12000 -w target.ass source1.ass source2.ass source3.assAll output will be combined into
target.ass. -
To overwrite files directly, use the
-oor--overwriteoption:subsync +12000 -o source1.ass source2.ass source3.assThe output files will therefore be
source1.ass,source2.ass, andsource3.ass. -
There is a slight difference between
--overwriteand-o:--overwritecreates a backup file:subsync +12000 --overwrite source1.ass source2.ass source3.assThe modified content overwrites
source1.ass,source2.ass, andsource3.ass, while backup filessource1.ass.bak,source2.ass.bak, andsource3.ass.bakare created. If something goes wrong, you can restore them. -
Time-offset option:
-/+OFFSETis used to shift subtitle timing forward or backward.+increases timestamps, meaning subtitles appear later.-decreases timestamps, meaning subtitles appear earlier.OFFSETis the amount of shift applied to subtitle timestamps. Supported formats include:- Milliseconds, e.g. 19700
.srtformat timestamps, e.g.0:0:10,190.ass/.ssaformat timestamps, e.g.0:0:10.19- Timestamp arithmetic, e.g.
01:44:31,660-01:44:36,290 - See the HOWTO: Time Offset section below.
-
Time-scaling option:
-SCALEscales subtitle timestamps by a factor. It may be:- A floating-point number, such as
1.1988 - Predefined constant
N-P(equals1.1988) - Predefined constant
P-N(equals0.83417) - Predefined constant
N-C(equals1.25) - Predefined constant
C-N(equals0.8) - Predefined constant
P-C(equals1.04271) - Predefined constant
C-P(equals0.95904)
This option cannot be confused with
-OFFSET, since scaling must be a floating-point value. See the HOWTO: Time Scale section below. - A floating-point number, such as
-
To delete subtitles within a specific range, use
-c N:Mor--chop N:M.N:Mrefers to subtitle sequence numbers for.srtfiles. -
To reorder
.srtsequence numbers, use-r [NUM]or--reorder [NUM].This is used to tidy up subtitle numbering, especially after splitting or merging subtitles, which often results in messy numbering.
Although this does not affect playback, it looks untidy. The
-roption will renumber subtitles starting from 1. IfNUMis provided, numbering will start fromNUM. -
To specify a timestamp range, use
-s TIMEor--span TIME.If you only want to modify subtitle timestamps within a certain range rather than the whole file, use this option. A range looks like this:
-s 00:00:52,570 0:11:00,140. If only the start time is given, e.g.-s 00:00:52,570, the default end time is the end of the file. -
Specify an output filename using
-w FILENAMEor--write FILENAME.If no output filename is provided, output goes to
stdout, unless-oor--overwriteis used to modify files directly.
Time Formats
subsync supports the following time formats:
-
Integer value, in milliseconds, e.g.
19700 -
.srttimestamp format, e.g.0:0:10,190- The fields separated by colons represent hours, minutes, and seconds.
- They may be omitted from the left, e.g. 1:20 means 1 minute 20 seconds.
- The part after the comma is milliseconds: 190 means 190 ms.
-
.ass/.ssatimestamp format, e.g.0:0:10.19- The fields separated by colons represent hours, minutes, and seconds, and may also be shortened the same way.
- The part after the dot represents centiseconds:
.19means 19 centiseconds = 190 ms.
-
Timestamp arithmetic, used for offsetting timestamps, e.g.
01:44:31,660-01:44:36,290.subsyncconverts both timestamps to milliseconds and subtracts them. The result may be positive or negative:- A negative result shifts subtitles earlier
- A positive result shifts subtitles later
- Formats may be mixed, e.g.
01:44:31,660-12700 - This helps compute differences between timestamps from subtitles in different languages
-
Timestamp ratio, used for scaling timestamps, e.g.
01:44:30,290/01:44:31,660.subsyncconverts both timestamps to milliseconds and divides them, producing a floating-point scaling factor:- If the result is less than 1, subtitle intervals become shorter
- If the result is greater than 1, subtitle intervals become longer
- Formats may be mixed, e.g.
01:44:31,660/12700 - Dividing the last subtitle’s time by the corresponding audio time is a quick way to obtain a scale factor
-
Note: When omitting hour/minute fields, be careful with seconds vs. milliseconds.
For example, 20 means 20 milliseconds, not 20 seconds.
20,0or20.0means 20 seconds. -
Note: The value
20.0is ambiguous and matches a scaling ratio, not a timestamp. Scaling has higher priority than offset. For example:subsync -20.0 -w target.ass source.assThis will enlarge the subtitle timing by 20×, not shift it earlier by 20 seconds.
To shift by 20 seconds, use any of the following:
subsync -20,0 -w target.ass source.ass subsync -20000 -w target.ass source.ass subsync -0:20 -w target.ass source.ass subsync -0:20.0 -w target.ass source.ass
HOWTO: Time Offset
Shifting timestamps is the most common operation: adding or subtracting a fixed value from subtitle timestamps causes the subtitles to appear later or earlier. Most subtitle misalignment issues occur because some content was added to or removed from the opening of the video. A simple timestamp offset can effectively correct this problem.
For example:
subsync +12000 < source.ass > target.ass
This increases all subtitle timestamps in source.ass by 12,000
milliseconds, causing every subtitle to appear 12 seconds later.
In the parameter +12000, the + indicates an increase.
Conversely, - indicates a decrease:
subsync -12000 < source.ass > target.ass
This decreases all timestamps by 12,000 milliseconds, causing every subtitle to appear 12 seconds earlier.
The time format may be an integer (milliseconds),
or a standard HH:MM:SS format. Note that milliseconds
in HH:MM:SS format appear in two different formats:
.srt:HH:MM:SS,mmm.ass/.ssa:HH:MM:SS.nnSee the earlier Time Formats section for details.
To simplify calculations, subsync supports timestamp arithmetic
as the offset parameter.
For example, you can pick any misaligned subtitle in the subtitle
file, then find the correct line’s start time in the video, and
subtract the subtitle timestamp from the correct video timestamp:
subsync +00:00:52,570-0:11:00,140 source.ass > target.ass
In this offset parameter +00:00:52,570-0:11:00,140:
- The leading
+is ignored; using-makes no difference 00:00:52,570is the correct start time of the dialogue in the video
