// Package utils 提供工具函数 package utils import ( "fmt" "regexp" "strconv" "strings" "time" "gitea.malaihome.work/ans/podcast_search/model" ) // SrtParser 用于解析SRT格式的转录文件 type SrtParser struct { // SRT格式匹配正则表达式 srtMatcher *regexp.Regexp // 换行符匹配正则表达式 newlineMatcher *regexp.Regexp } // NewSrtParser 创建新的SRT解析器 func NewSrtParser() *SrtParser { return &SrtParser{ srtMatcher: regexp.MustCompile( `(\d*)\s?((\d{2}):(\d{2}):(\d{2})[,|.](\d{3})) +--> +((\d{2}):(\d{2}):(\d{2})[,|.](\d{3})).*[\r\n]+\s*([^\r\n]+(\n|\r|\n)(?:.*))`, ), newlineMatcher: regexp.MustCompile(`[\r\n]+`), } } // Parse 解析SRT格式的转录文件 func (p *SrtParser) Parse(srtData string) (*model.Transcript, error) { matches := p.srtMatcher.FindAllStringSubmatch(srtData, -1) subtitles := make([]model.Subtitle, 0) i := 0 for _, match := range matches { i++ // 索引可能存在也可能不存在 index := i if match[1] != "" { parsedIndex, err := strconv.Atoi(match[1]) if err == nil { index = parsedIndex } } // 解析开始时间 startTimeHours, _ := strconv.Atoi(match[3]) startTimeMinutes, _ := strconv.Atoi(match[4]) startTimeSeconds, _ := strconv.Atoi(match[5]) startTimeMilliseconds, _ := strconv.Atoi(match[6]) // 解析结束时间 endTimeHours, _ := strconv.Atoi(match[8]) endTimeMinutes, _ := strconv.Atoi(match[9]) endTimeSeconds, _ := strconv.Atoi(match[10]) endTimeMilliseconds, _ := strconv.Atoi(match[11]) // 计算开始和结束时间的Duration startDuration := time.Duration(startTimeHours)*time.Hour + time.Duration(startTimeMinutes)*time.Minute + time.Duration(startTimeSeconds)*time.Second + time.Duration(startTimeMilliseconds)*time.Millisecond endDuration := time.Duration(endTimeHours)*time.Hour + time.Duration(endTimeMinutes)*time.Minute + time.Duration(endTimeSeconds)*time.Second + time.Duration(endTimeMilliseconds)*time.Millisecond // 解析文本内容 textLines := p.newlineMatcher.Split(match[12], -1) text := "" // 处理文本行 for _, line := range textLines { if text == "" { text = line } else if strings.HasSuffix(text, " ") || strings.HasPrefix(line, " ") { text += line } else { text += " " + line } } // 创建字幕 subtitle := model.Subtitle{ Index: index, Start: startDuration, End: endDuration, Data: strings.TrimSpace(text), Speaker: "", // SRT格式通常不包含发言人信息 } subtitles = append(subtitles, subtitle) } if len(subtitles) == 0 { return nil, fmt.Errorf("解析SRT失败: 未找到有效的字幕") } return &model.Transcript{ Subtitles: subtitles, }, nil }