Documentation
¶
Overview ¶
Package subsync provides subtitle timing synchronization.
It supports multiple sync strategies:
- Constant-offset alignment (alass algorithm port)
- Framerate correction (known ratios + golden-section search)
- Split-aware DP alignment (handles commercial breaks, different cuts)
- Audio-based sync (energy VAD + FFT cross-correlation, no reference needed)
- Encoding normalization (UTF-16, Windows-1252 → UTF-8)
Basic usage:
result, err := subsync.SyncFile(ctx, "video.mkv", "subtitle.srt", nil)
if err != nil {
log.Fatal(err)
}
os.WriteFile("subtitle.synced.srt", result.Data, 0o644)
With a reference subtitle:
result, err := subsync.SyncFile(ctx, "video.mkv", "subtitle.srt", &subsync.Options{
Reference: "reference.en.srt",
})
Index ¶
- Constants
- Variables
- func IsASSContent(data []byte) bool
- func NormalizeEncoding(data []byte) []byte
- func OutputPath(inputPath string) string
- func PostProcessBytes(data []byte, opts PostProcessOptions) []byte
- func WriteSRT(w io.Writer, cues []Cue) error
- type AudioSyncHints
- type Confidence
- type ConfidenceCaps
- type Cue
- func ExtractEmbeddedSRT(ctx context.Context, videoPath, lang, excludeLang string, ...) ([]Cue, error)
- func ParseASSDialogue(data []byte) (dialogueCues, maskCues []Cue, err error)
- func ParseSRT(r io.Reader) ([]Cue, error)
- func PostProcess(cues []Cue, opts PostProcessOptions) []Cue
- func ShiftCues(cues []Cue, offset time.Duration) []Cue
- type LangMapper
- type Options
- type PostProcessOptions
- type Result
- type SyncMethod
- type SyncOptions
- type SyncResult
- type TimeSpan
Constants ¶
const MinCuesForSync = 5
MinCuesForSync is the minimum number of subtitle cues required for any timing-based sync strategy to produce meaningful results. Fewer than this provides insufficient signal for correlation or alignment.
Variables ¶
var DefaultConfidenceCaps = ConfidenceCaps{
Audio: 0.9,
Offset: 0.9,
FramerateGSS: 0.85,
FramerateKnown: 0.95,
FramerateFPS: 0.98,
Crosslang: 0.92,
SplitBase: 0.85,
SplitPenaltyPerSegment: 0.05,
SplitMinConf: 0.4,
}
DefaultConfidenceCaps is the production confidence cap table.
var ErrFileTooLarge = errors.New("subsync: file too large")
ErrFileTooLarge is returned when a subtitle file exceeds the maximum safe size. Wrap it with fmt.Errorf("%w: ...") so callers can use errors.Is.
Functions ¶
func IsASSContent ¶
IsASSContent reports whether data looks like ASS/SSA subtitle content by checking for the [Script Info] header or Dialogue: lines.
func NormalizeEncoding ¶
NormalizeEncoding detects the encoding of subtitle data and converts it to UTF-8. Handles UTF-8 (with/without BOM), UTF-16 LE/BE, and common single-byte encodings (Windows-1252, ISO-8859-1).
Returns the UTF-8 normalized data with any byte-order mark and embedded NUL bytes removed. When the input is already valid, BOM-free, NUL-free UTF-8 the original slice is returned (not a copy); callers must not mutate the returned slice if they need the original data unchanged. The result is a fixed point: NormalizeEncoding(NormalizeEncoding(x)) always equals NormalizeEncoding(x).
func OutputPath ¶
OutputPath generates the output file path for a synced subtitle. For "movie.fr.srt" it returns "movie.fr.synced.srt".
func PostProcessBytes ¶
func PostProcessBytes(data []byte, opts PostProcessOptions) []byte
PostProcessBytes applies encoding normalization and line ending fixes to raw subtitle bytes. Call this before parsing, or on the final output.
Types ¶
type AudioSyncHints ¶
type AudioSyncHints struct {
// DialogueCues and MaskCues are pre-classified ASS cues from the native
// parser. When set, audioSyncFromPCM uses these directly instead of
// applying text-based heuristics (karaoke pair detection, SDH filtering)
// to the flat cue list. This produces better results for ASS files
// because style-based classification is more accurate than text patterns.
DialogueCues []Cue
MaskCues []Cue
// DurationSec is the total media duration in seconds.
DurationSec int
// IsASS indicates the subtitle was ASS-extracted (clean cues, no tag remnants).
IsASS bool
// DisableVAD skips the GMM VAD fallback (Strategy D). Used for benchmarking
// to measure the energy-only pipeline's accuracy.
DisableVAD bool
}
AudioSyncHints provides content characteristics for adaptive strategy selection. Zero values use the default strategy.
type Confidence ¶
type Confidence float64
Confidence represents the quality of a sync operation (0.0 to 1.0).
const ( // ConfidenceNone means no sync was performed or the result is unusable. ConfidenceNone Confidence = 0 // ConfidenceWeak means the sync may be wrong; caller should consider // keeping the original timing. ConfidenceWeak Confidence = 0.3 // ConfidenceModerate means the sync is likely correct but may have issues. ConfidenceModerate Confidence = 0.6 // ConfidenceStrong means high confidence in the sync result. ConfidenceStrong Confidence = 0.8 // ConfidencePerfect means hash match or perfect correlation. ConfidencePerfect Confidence = 1.0 )
const DefaultMinConfidence Confidence = 0.5
DefaultMinConfidence is the default minimum confidence used by the sync engine when no explicit threshold is provided. This is the single source of truth for the engine's default; the API layer's DefaultSyncMinConfidence (0.6) is intentionally stricter for user-facing auto-apply decisions.
const ShouldApplyThreshold Confidence = 0.5
ShouldApplyThreshold is the exported minimum confidence for a sync result to be considered applicable. Consumers comparing Result.Confidence against a threshold should use this constant instead of a magic 0.5 literal. This is the audio/fallback threshold; reference-based sync uses DefaultMinConfidence (0.5) as the engine default, while the API layer may apply a stricter threshold (e.g. 0.6) for user-facing auto-sync.
type ConfidenceCaps ¶
type ConfidenceCaps struct {
Audio Confidence // audio-based sync
Offset Confidence // constant-offset sync
FramerateGSS Confidence // golden-section framerate search
FramerateKnown Confidence // known-ratio framerate match
FramerateFPS Confidence // video FPS confirms the ratio
Crosslang Confidence // cross-language alignment
SplitBase Confidence // split-aware alignment (reduced by segment penalty)
SplitPenaltyPerSegment Confidence // confidence penalty per additional segment
SplitMinConf Confidence // minimum confidence floor for split alignment
}
ConfidenceCaps holds per-strategy confidence ceilings. Each strategy has a different cap reflecting its inherent reliability. The relative ordering is intentional: framerate with FPS confirmation > known ratio > audio/offset > GSS/split.
func (ConfidenceCaps) ForMethod ¶
func (c ConfidenceCaps) ForMethod(m SyncMethod) Confidence
ForMethod returns the confidence cap for the given sync method. For framerate methods, returns FramerateGSS as the conservative default; callers with FPS confirmation should use FramerateFPS directly.
type Cue ¶
Cue represents a single subtitle cue with timing and text content. This is a local definition that mirrors api.SubtitleCue, decoupling the subsync package from the application's domain types.
func ExtractEmbeddedSRT ¶
func ExtractEmbeddedSRT(ctx context.Context, videoPath, lang, excludeLang string, mapper ffmpeg.LangMapper) ([]Cue, error)
ExtractEmbeddedSRT extracts text-based subtitle data from a video file and returns it as parsed SRT cues. Uses ffprobe for track detection and ffmpeg for subtitle extraction.
Track selection priority:
- Matching language (if lang is non-empty)
- Prefer SRT/subrip over ASS/SSA
- Skip forced tracks (sparse cues)
- Skip tracks matching excludeLang
Returns nil cues if no suitable track is found.
func ParseASSDialogue ¶
ParseASSDialogue parses raw ASS content and returns dialogue cues and mask cues separately.
dialogueCues: only cues from classified dialogue styles (for subtitle envelope / correlation signal). maskCues: all cues regardless of style classification (for dialogue mask / time region detection). Even OP/ED/signs mark time regions with audio activity, giving broader mask coverage.
Two-pass: first collects all style names and cue counts, classifies them, then extracts cues.
func PostProcess ¶
func PostProcess(cues []Cue, opts PostProcessOptions) []Cue
PostProcess applies the configured processing steps to subtitle cues. Steps run in order: encoding normalization (on raw bytes before parsing) is handled by the caller; this function operates on parsed cues.
type LangMapper ¶
type LangMapper = ffmpeg.LangMapper
LangMapper is a type alias for ffmpeg.LangMapper, preserving backward compatibility for consumers that reference subsync.LangMapper.
type Options ¶
type Options struct {
// PostProcess configures subtitle post-processing (HI removal, tag stripping, etc.).
// Nil means no post-processing.
PostProcess *PostProcessOptions
// Framerate enables framerate correction detection.
// nil = default (true), non-nil = explicit value.
Framerate *bool
// Splits enables split-aware alignment.
// nil = default (true), non-nil = explicit value.
Splits *bool
// Reference is the path to a correctly-timed reference subtitle.
Reference string
// SplitPenalty controls split detection sensitivity (0 = default 1000ms).
SplitPenalty float64
// MinConfidence is the minimum confidence to accept a sync result (default: 0.5).
MinConfidence float64
// Audio enables audio-based sync (default: false).
Audio bool
}
Options configures a sync operation.
type PostProcessOptions ¶
type PostProcessOptions struct {
// StripHI removes hearing-impaired annotations:
// [sound effects], (music playing), ♪ lyrics ♪, and speaker labels (JOHN:).
StripHI bool
// StripTags removes HTML-like tags: <i>, </i>, <b>, </b>, <u>, </u>, <font ...>, </font>.
StripTags bool
// NormalizeEncoding converts the subtitle to UTF-8 from any detected encoding
// (UTF-16 LE/BE, Windows-1252, ISO-8859-1). Also strips UTF-8 BOM.
NormalizeEncoding bool
// NormalizeLineEndings converts all line endings to CRLF (SRT standard)
// and ensures a single trailing CRLF.
NormalizeLineEndings bool
// CleanWhitespace trims leading/trailing whitespace from each text line
// and removes blank lines and bare dialogue dashes.
CleanWhitespace bool
// RemoveEmpty drops cues that have no text content after all other
// processing steps. Cue numbers are assigned when writing SRT output.
RemoveEmpty bool
}
PostProcessOptions configures subtitle post-processing. All fields default to false (no processing). Enable what you need.
type Result ¶
type Result struct {
// Method describes which strategy produced the result.
// One of: MethodOffset, MethodFramerate, MethodSplit, MethodAudio, MethodCrosslang, MethodNone.
Method SyncMethod
// Data is the synchronized subtitle file content (UTF-8, SRT format).
Data []byte
// OffsetMs is the constant offset applied (milliseconds).
OffsetMs int64
// Confidence is the quality score of the sync (0.0 to 1.0).
Confidence Confidence
// Rate is the framerate ratio applied (1.0 = no change).
Rate float64
// Applied is true if the sync changed timing and confidence was sufficient.
Applied bool
}
Result holds the output of a sync operation.
type SyncMethod ¶
type SyncMethod string
SyncMethod is a typed string identifying the sync algorithm used.
const ( MethodNone SyncMethod = "none" MethodOffset SyncMethod = "offset" MethodFramerate SyncMethod = "framerate" MethodSplit SyncMethod = "split" MethodAudio SyncMethod = "audio" MethodCrosslang SyncMethod = "crosslang" )
Sync method identifiers.
type SyncOptions ¶
type SyncOptions struct {
// VideoPath is the path to the video file (required for audio sync).
VideoPath string
// AudioHints provides content characteristics for adaptive audio
// sync strategy selection. Optional; zero value uses defaults.
AudioHints AudioSyncHints
// SplitPenalty controls split detection sensitivity (0 = default).
SplitPenalty float64
// MinConfidence is the minimum confidence to apply a sync result.
// Default: 0.5.
MinConfidence Confidence
// EnableFramerate enables framerate correction detection.
EnableFramerate bool
// EnableSplits enables split-aware DP alignment.
EnableSplits bool
// EnableAudio enables audio-based sync (requires video file path).
EnableAudio bool
}
SyncOptions configures the sync behavior.
func DefaultSyncOptions ¶
func DefaultSyncOptions() SyncOptions
DefaultSyncOptions returns sensible defaults.
type SyncResult ¶
type SyncResult struct {
Method SyncMethod // MethodNone, MethodOffset, MethodFramerate, MethodSplit, MethodAudio, MethodCrosslang
Cues []Cue
Offset int64 // milliseconds (constant offset applied)
Confidence Confidence // quality of the sync
Rate float64 // framerate ratio applied (1.0 = no change)
}
SyncResult holds the output of any sync operation.
func SyncWithOptions ¶
func SyncWithOptions(ctx context.Context, reference, incorrect []Cue, opts *SyncOptions) SyncResult
SyncWithOptions performs multi-strategy subtitle synchronization.
Strategy order:
- If reference subtitle available: try framerate correction, then split-aware alignment, then constant offset
- If no reference but video path provided and audio enabled: try audio-based sync
Returns the best result above the minimum confidence threshold.
func (SyncResult) Applied ¶
func (r SyncResult) Applied() bool
Applied returns true if the sync actually changed the subtitle timing. Checks offset (constant shift), rate (framerate correction), and split method (multi-segment alignment where no single offset/rate captures the change).
func (SyncResult) ShouldApply ¶
func (r SyncResult) ShouldApply() bool
ShouldApply returns true if the confidence is high enough to use the result. Threshold: ShouldApplyThreshold (moderate confidence or better). This is the post-hoc check used by callers after sync completes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package crosslang implements cross-language subtitle alignment using anchor-based matching and dynamic programming.
|
Package crosslang implements cross-language subtitle alignment using anchor-based matching and dynamic programming. |
|
Package ffmpeg provides low-level ffmpeg/ffprobe subprocess wrappers for stream probing, subtitle extraction, and PCM audio extraction.
|
Package ffmpeg provides low-level ffmpeg/ffprobe subprocess wrappers for stream probing, subtitle extraction, and PCM audio extraction. |
|
Package fft provides a radix-2 Cooley-Tukey FFT implementation for cross-correlation in the subsync package.
|
Package fft provides a radix-2 Cooley-Tukey FFT implementation for cross-correlation in the subsync package. |
|
Package framerate provides framerate drift detection for subtitle alignment.
|
Package framerate provides framerate drift detection for subtitle alignment. |