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 }