80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
package sync
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"sub-cli/internal/format/ass"
|
|
"sub-cli/internal/model"
|
|
)
|
|
|
|
// syncASSFiles synchronizes two ASS files
|
|
func syncASSFiles(sourceFile, targetFile string) error {
|
|
sourceSubtitle, err := ass.Parse(sourceFile)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing source ASS file: %w", err)
|
|
}
|
|
|
|
targetSubtitle, err := ass.Parse(targetFile)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing target ASS file: %w", err)
|
|
}
|
|
|
|
// Check if entry counts match
|
|
if len(sourceSubtitle.Events) != len(targetSubtitle.Events) {
|
|
fmt.Printf("Warning: Source (%d events) and target (%d events) have different event counts. Timeline will be adjusted.\n",
|
|
len(sourceSubtitle.Events), len(targetSubtitle.Events))
|
|
}
|
|
|
|
// Sync the timelines
|
|
syncedSubtitle := syncASSTimeline(sourceSubtitle, targetSubtitle)
|
|
|
|
// Write the synced subtitle to the target file
|
|
return ass.Generate(syncedSubtitle, targetFile)
|
|
}
|
|
|
|
// syncASSTimeline applies the timing from source ASS subtitle to target ASS subtitle
|
|
func syncASSTimeline(source, target model.ASSFile) model.ASSFile {
|
|
result := model.ASSFile{
|
|
ScriptInfo: target.ScriptInfo,
|
|
Styles: target.Styles,
|
|
Events: make([]model.ASSEvent, len(target.Events)),
|
|
}
|
|
|
|
// Copy target events
|
|
copy(result.Events, target.Events)
|
|
|
|
// If there are no events in either source or target, return as is
|
|
if len(source.Events) == 0 || len(target.Events) == 0 {
|
|
return result
|
|
}
|
|
|
|
// Extract start and end timestamps from source
|
|
sourceStartTimes := make([]model.Timestamp, len(source.Events))
|
|
sourceEndTimes := make([]model.Timestamp, len(source.Events))
|
|
|
|
for i, event := range source.Events {
|
|
sourceStartTimes[i] = event.StartTime
|
|
sourceEndTimes[i] = event.EndTime
|
|
}
|
|
|
|
// Scale timestamps if source and target event counts differ
|
|
var scaledStartTimes, scaledEndTimes []model.Timestamp
|
|
|
|
if len(source.Events) == len(target.Events) {
|
|
// If counts match, use source times directly
|
|
scaledStartTimes = sourceStartTimes
|
|
scaledEndTimes = sourceEndTimes
|
|
} else {
|
|
// Scale the timelines to match target count
|
|
scaledStartTimes = scaleTimeline(sourceStartTimes, len(target.Events))
|
|
scaledEndTimes = scaleTimeline(sourceEndTimes, len(target.Events))
|
|
}
|
|
|
|
// Apply scaled timeline to target events
|
|
for i := range result.Events {
|
|
result.Events[i].StartTime = scaledStartTimes[i]
|
|
result.Events[i].EndTime = scaledEndTimes[i]
|
|
}
|
|
|
|
return result
|
|
}
|