package ass import ( "fmt" "os" "path/filepath" "strings" "sub-cli/internal/model" ) // Generate 生成ASS文件 func Generate(assFile model.ASSFile, filePath string) error { // 确保目录存在 dir := filepath.Dir(filePath) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("创建目录失败: %w", err) } // 创建或覆盖文件 file, err := os.Create(filePath) if err != nil { return fmt.Errorf("创建ASS文件失败: %w", err) } defer file.Close() // 写入脚本信息 if _, err := file.WriteString(ASSHeader + "\n"); err != nil { return fmt.Errorf("写入文件失败: %w", err) } for key, value := range assFile.ScriptInfo { if _, err := file.WriteString(fmt.Sprintf("%s: %s\n", key, value)); err != nil { return fmt.Errorf("写入文件失败: %w", err) } } // 写入样式信息 if _, err := file.WriteString("\n" + ASSStylesHeader + "\n"); err != nil { return fmt.Errorf("写入文件失败: %w", err) } // 写入样式格式行 if len(assFile.Styles) > 0 { var formatString string for _, style := range assFile.Styles { if formatString == "" && style.Properties["Format"] != "" { formatString = style.Properties["Format"] if _, err := file.WriteString(fmt.Sprintf("Format: %s\n", formatString)); err != nil { return fmt.Errorf("写入文件失败: %w", err) } break } } // 如果没有找到格式行,写入默认格式 if formatString == "" { defaultFormat := "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding" if _, err := file.WriteString(fmt.Sprintf("Format: %s\n", defaultFormat)); err != nil { return fmt.Errorf("写入文件失败: %w", err) } } // 写入样式定义 for _, style := range assFile.Styles { if style.Properties["Style"] != "" { if _, err := file.WriteString(fmt.Sprintf("Style: %s\n", style.Properties["Style"])); err != nil { return fmt.Errorf("写入文件失败: %w", err) } } } } // 写入事件信息 if _, err := file.WriteString("\n" + ASSEventsHeader + "\n"); err != nil { return fmt.Errorf("写入文件失败: %w", err) } // 写入事件格式行 if _, err := file.WriteString(DefaultFormat + "\n"); err != nil { return fmt.Errorf("写入文件失败: %w", err) } // 写入事件行 for _, event := range assFile.Events { eventLine := formatEventLine(event) if _, err := file.WriteString(eventLine + "\n"); err != nil { return fmt.Errorf("写入文件失败: %w", err) } } return nil } // formatEventLine 将事件格式化为ASS文件中的一行 func formatEventLine(event model.ASSEvent) string { // 格式化时间戳 startTime := formatASSTimestamp(event.StartTime) endTime := formatASSTimestamp(event.EndTime) // 构建事件行 var builder strings.Builder if event.Type == "Comment" { builder.WriteString("Comment: ") } else { builder.WriteString("Dialogue: ") } builder.WriteString(fmt.Sprintf("%d,%s,%s,%s,%s,%d,%d,%d,%s,%s", event.Layer, startTime, endTime, event.Style, event.Name, event.MarginL, event.MarginR, event.MarginV, event.Effect, event.Text)) return builder.String() }