137 lines
3.3 KiB
Go
137 lines
3.3 KiB
Go
package converter
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"sub-cli/internal/format/lrc"
|
|
"sub-cli/internal/format/srt"
|
|
"sub-cli/internal/model"
|
|
)
|
|
|
|
// ErrUnsupportedFormat is returned when trying to convert to/from an unsupported format
|
|
var ErrUnsupportedFormat = errors.New("unsupported format")
|
|
|
|
// Convert converts a file from one format to another
|
|
func Convert(sourceFile, targetFile string) error {
|
|
sourceFmt := strings.TrimPrefix(filepath.Ext(sourceFile), ".")
|
|
targetFmt := strings.TrimPrefix(filepath.Ext(targetFile), ".")
|
|
|
|
switch sourceFmt {
|
|
case "lrc":
|
|
return convertFromLRC(sourceFile, targetFile, targetFmt)
|
|
case "srt":
|
|
return convertFromSRT(sourceFile, targetFile, targetFmt)
|
|
default:
|
|
return fmt.Errorf("%w: %s", ErrUnsupportedFormat, sourceFmt)
|
|
}
|
|
}
|
|
|
|
// convertFromLRC converts an LRC file to another format
|
|
func convertFromLRC(sourceFile, targetFile, targetFmt string) error {
|
|
sourceLyrics, err := lrc.Parse(sourceFile)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing source LRC file: %w", err)
|
|
}
|
|
|
|
switch targetFmt {
|
|
case "txt":
|
|
return lrcToTxt(sourceLyrics, targetFile)
|
|
case "srt":
|
|
return lrcToSRT(sourceLyrics, targetFile)
|
|
case "lrc":
|
|
return lrc.Generate(sourceLyrics, targetFile)
|
|
default:
|
|
return fmt.Errorf("%w: %s", ErrUnsupportedFormat, targetFmt)
|
|
}
|
|
}
|
|
|
|
// convertFromSRT converts an SRT file to another format
|
|
func convertFromSRT(sourceFile, targetFile, targetFmt string) error {
|
|
entries, err := srt.Parse(sourceFile)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing source SRT file: %w", err)
|
|
}
|
|
|
|
switch targetFmt {
|
|
case "txt":
|
|
return srtToTxt(entries, targetFile)
|
|
case "lrc":
|
|
lyrics := srt.ConvertToLyrics(entries)
|
|
return lrc.Generate(lyrics, targetFile)
|
|
case "srt":
|
|
return srt.Generate(entries, targetFile)
|
|
default:
|
|
return fmt.Errorf("%w: %s", ErrUnsupportedFormat, targetFmt)
|
|
}
|
|
}
|
|
|
|
// lrcToTxt converts LRC lyrics to a plain text file
|
|
func lrcToTxt(lyrics model.Lyrics, targetFile string) error {
|
|
file, err := os.Create(targetFile)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating target file: %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
for _, content := range lyrics.Content {
|
|
if _, err := fmt.Fprintln(file, content); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// lrcToSRT converts LRC lyrics to an SRT file
|
|
func lrcToSRT(lyrics model.Lyrics, targetFile string) error {
|
|
var entries []model.SRTEntry
|
|
|
|
for i, content := range lyrics.Content {
|
|
if i >= len(lyrics.Timeline) {
|
|
break
|
|
}
|
|
|
|
startTime := lyrics.Timeline[i]
|
|
endTime := startTime
|
|
|
|
// If there's a next timeline entry, use it for end time
|
|
// Otherwise add a few seconds to the start time
|
|
if i+1 < len(lyrics.Timeline) {
|
|
endTime = lyrics.Timeline[i+1]
|
|
} else {
|
|
endTime.Seconds += 3
|
|
}
|
|
|
|
entry := model.SRTEntry{
|
|
Number: i + 1,
|
|
StartTime: startTime,
|
|
EndTime: endTime,
|
|
Content: content,
|
|
}
|
|
|
|
entries = append(entries, entry)
|
|
}
|
|
|
|
return srt.Generate(entries, targetFile)
|
|
}
|
|
|
|
// srtToTxt converts SRT entries to a plain text file
|
|
func srtToTxt(entries []model.SRTEntry, targetFile string) error {
|
|
file, err := os.Create(targetFile)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating target file: %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
for _, entry := range entries {
|
|
if _, err := fmt.Fprintln(file, entry.Content); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|