package ass import ( "fmt" "sub-cli/internal/model" ) // ConvertToSubtitle 将ASS文件转换为通用字幕格式 func ConvertToSubtitle(filePath string) (model.Subtitle, error) { // 解析ASS文件 assFile, err := Parse(filePath) if err != nil { return model.Subtitle{}, fmt.Errorf("解析ASS文件失败: %w", err) } // 创建通用字幕结构 subtitle := model.NewSubtitle() subtitle.Format = "ass" // 转换标题 if title, ok := assFile.ScriptInfo["Title"]; ok { subtitle.Title = title } // 转换事件为字幕条目 for i, event := range assFile.Events { // 只转换对话类型的事件 if event.Type == "Dialogue" { entry := model.SubtitleEntry{ Index: i + 1, StartTime: event.StartTime, EndTime: event.EndTime, Text: event.Text, Styles: make(map[string]string), Metadata: make(map[string]string), } // 记录样式信息 entry.Styles["style"] = event.Style // 记录ASS特有信息 entry.Metadata["Layer"] = fmt.Sprintf("%d", event.Layer) entry.Metadata["Name"] = event.Name entry.Metadata["MarginL"] = fmt.Sprintf("%d", event.MarginL) entry.Metadata["MarginR"] = fmt.Sprintf("%d", event.MarginR) entry.Metadata["MarginV"] = fmt.Sprintf("%d", event.MarginV) entry.Metadata["Effect"] = event.Effect subtitle.Entries = append(subtitle.Entries, entry) } } return subtitle, nil } // ConvertFromSubtitle 将通用字幕格式转换为ASS文件 func ConvertFromSubtitle(subtitle model.Subtitle, filePath string) error { // 创建ASS文件结构 assFile := model.NewASSFile() // 设置标题 if subtitle.Title != "" { assFile.ScriptInfo["Title"] = subtitle.Title } // 转换字幕条目为ASS事件 for _, entry := range subtitle.Entries { event := model.NewASSEvent() event.Type = "Dialogue" event.StartTime = entry.StartTime event.EndTime = entry.EndTime event.Text = entry.Text // 检查是否有ASS特有的元数据 if layer, ok := entry.Metadata["Layer"]; ok { fmt.Sscanf(layer, "%d", &event.Layer) } if name, ok := entry.Metadata["Name"]; ok { event.Name = name } if marginL, ok := entry.Metadata["MarginL"]; ok { fmt.Sscanf(marginL, "%d", &event.MarginL) } if marginR, ok := entry.Metadata["MarginR"]; ok { fmt.Sscanf(marginR, "%d", &event.MarginR) } if marginV, ok := entry.Metadata["MarginV"]; ok { fmt.Sscanf(marginV, "%d", &event.MarginV) } if effect, ok := entry.Metadata["Effect"]; ok { event.Effect = effect } // 处理样式 if style, ok := entry.Styles["style"]; ok { event.Style = style } else { // 根据基本样式设置ASS样式 if _, ok := entry.Styles["bold"]; ok { // 创建一个加粗样式(如果尚未存在) styleName := "Bold" found := false for _, style := range assFile.Styles { if style.Name == styleName { found = true break } } if !found { boldStyle := model.ASSStyle{ Name: styleName, Properties: map[string]string{ "Format": "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "Style": "Bold,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,1,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1", }, } assFile.Styles = append(assFile.Styles, boldStyle) } event.Style = styleName } if _, ok := entry.Styles["italic"]; ok { // 创建一个斜体样式(如果尚未存在) styleName := "Italic" found := false for _, style := range assFile.Styles { if style.Name == styleName { found = true break } } if !found { italicStyle := model.ASSStyle{ Name: styleName, Properties: map[string]string{ "Format": "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "Style": "Italic,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,1,0,0,100,100,0,0,1,2,2,2,10,10,10,1", }, } assFile.Styles = append(assFile.Styles, italicStyle) } event.Style = styleName } if _, ok := entry.Styles["underline"]; ok { // 创建一个下划线样式(如果尚未存在) styleName := "Underline" found := false for _, style := range assFile.Styles { if style.Name == styleName { found = true break } } if !found { underlineStyle := model.ASSStyle{ Name: styleName, Properties: map[string]string{ "Format": "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", "Style": "Underline,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,1,0,100,100,0,0,1,2,2,2,10,10,10,1", }, } assFile.Styles = append(assFile.Styles, underlineStyle) } event.Style = styleName } } assFile.Events = append(assFile.Events, event) } // 生成ASS文件 return Generate(assFile, filePath) }