.unicode issue converter

This commit is contained in:
afkarxyz
2026-03-25 18:04:22 +07:00
parent 528bf65771
commit 8919b9a77a
2 changed files with 119 additions and 6 deletions
+7 -1
View File
@@ -16,6 +16,7 @@ import (
"time"
"github.com/ulikunitz/xz"
"golang.org/x/text/unicode/norm"
)
func ValidateExecutable(path string) error {
@@ -650,6 +651,7 @@ func ConvertAudio(req ConvertAudioRequest) ([]ConvertAudioResult, error) {
outputExt := "." + strings.ToLower(req.OutputFormat)
outputFile := filepath.Join(outputDir, baseName+outputExt)
outputFile = norm.NFC.String(outputFile)
if inputExt == outputExt {
result.Error = "Input and output formats are the same"
@@ -671,7 +673,11 @@ func ConvertAudio(req ConvertAudioRequest) ([]ConvertAudioResult, error) {
fmt.Printf("[FFmpeg] Warning: Failed to extract metadata from %s: %v\n", inputFile, err)
}
coverArtPath, _ = ExtractCoverArt(inputFile)
inputFile = norm.NFC.String(inputFile)
coverArtPath, err = ExtractCoverArt(inputFile)
if err != nil {
fmt.Printf("[FFmpeg] Warning: Failed to extract cover art from %s: %v\n", inputFile, err)
}
lyrics, err = ExtractLyrics(inputFile)
if err != nil {
fmt.Printf("[FFmpeg] Warning: Failed to extract lyrics from %s: %v\n", inputFile, err)
+112 -5
View File
@@ -13,6 +13,7 @@ import (
"github.com/go-flac/flacpicture"
"github.com/go-flac/flacvorbis"
"github.com/go-flac/go-flac"
"golang.org/x/text/unicode/norm"
)
type Metadata struct {
@@ -218,16 +219,68 @@ func EmbedLyricsOnly(filepath string, lyrics string) error {
}
func ExtractCoverArt(filePath string) (string, error) {
filePath = norm.NFC.String(filePath)
ext := strings.ToLower(pathfilepath.Ext(filePath))
var coverPath string
var err error
switch ext {
case ".mp3":
return extractCoverFromMp3(filePath)
coverPath, err = extractCoverFromMp3(filePath)
case ".m4a", ".flac":
return extractCoverFromM4AOrFlac(filePath)
coverPath, err = extractCoverFromM4AOrFlac(filePath)
default:
return "", fmt.Errorf("unsupported file format: %s", ext)
}
if err != nil || coverPath == "" {
fmt.Printf("[ExtractCoverArt] Library extraction failed for %s, trying FFmpeg fallback...\n", filePath)
ffmpegCover, ffmpegErr := extractCoverWithFFmpeg(filePath)
if ffmpegErr == nil {
return ffmpegCover, nil
}
return coverPath, err
}
return coverPath, nil
}
func extractCoverWithFFmpeg(filePath string) (string, error) {
ffmpegPath, err := GetFFmpegPath()
if err != nil {
return "", err
}
tmpFile, err := os.CreateTemp("", "cover-*.jpg")
if err != nil {
return "", err
}
tmpPath := tmpFile.Name()
tmpFile.Close()
cmd := exec.Command(ffmpegPath,
"-i", filePath,
"-an",
"-vframes", "1",
"-f", "image2",
"-update", "1",
"-y",
tmpPath,
)
setHideWindow(cmd)
if output, err := cmd.CombinedOutput(); err != nil {
os.Remove(tmpPath)
return "", fmt.Errorf("ffmpeg cover extraction failed: %v, output: %s", err, string(output))
}
if info, err := os.Stat(tmpPath); err != nil || info.Size() == 0 {
os.Remove(tmpPath)
return "", fmt.Errorf("ffmpeg produced empty cover file")
}
return tmpPath, nil
}
func extractCoverFromMp3(filePath string) (string, error) {
@@ -298,19 +351,71 @@ func extractCoverFromM4AOrFlac(filePath string) (string, error) {
}
func ExtractLyrics(filePath string) (string, error) {
filePath = norm.NFC.String(filePath)
ext := strings.ToLower(pathfilepath.Ext(filePath))
var lyrics string
var err error
switch ext {
case ".mp3":
return extractLyricsFromMp3(filePath)
lyrics, err = extractLyricsFromMp3(filePath)
case ".flac":
return extractLyricsFromFlac(filePath)
lyrics, err = extractLyricsFromFlac(filePath)
case ".m4a":
return "", nil
default:
return "", fmt.Errorf("unsupported file format: %s", ext)
}
if (err != nil || lyrics == "") && ext != ".m4a" {
fmt.Printf("[ExtractLyrics] Library extraction failed for %s, trying ffprobe fallback...\n", filePath)
ffprobeLyrics, ffprobeErr := extractLyricsWithFFprobe(filePath)
if ffprobeErr == nil && ffprobeLyrics != "" {
return ffprobeLyrics, nil
}
}
return lyrics, err
}
func extractLyricsWithFFprobe(filePath string) (string, error) {
ffprobePath, err := GetFFprobePath()
if err != nil {
return "", err
}
cmd := exec.Command(ffprobePath,
"-v", "quiet",
"-show_entries", "format_tags=lyrics:format_tags=unsyncedlyrics:format_tags=lyric",
"-of", "json",
filePath,
)
setHideWindow(cmd)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
var result struct {
Format struct {
Tags map[string]string `json:"tags"`
} `json:"format"`
}
if err := json.Unmarshal(output, &result); err != nil {
return "", err
}
tags := result.Format.Tags
for _, key := range []string{"lyrics", "unsyncedlyrics", "lyric", "LYRICS", "UNSYNCEDLYRICS", "LYRIC"} {
if val, ok := tags[key]; ok && val != "" {
return val, nil
}
}
return "", nil
}
func extractLyricsFromMp3(filePath string) (string, error) {
@@ -688,6 +793,7 @@ func parseLRCTimestamp(timestamp string) int64 {
}
func ExtractFullMetadataFromFile(filePath string) (Metadata, error) {
filePath = norm.NFC.String(filePath)
var metadata Metadata
ffprobePath, err := GetFFprobePath()
@@ -796,6 +902,7 @@ func ExtractFullMetadataFromFile(filePath string) (Metadata, error) {
}
func EmbedMetadataToConvertedFile(filePath string, metadata Metadata, coverPath string) error {
filePath = norm.NFC.String(filePath)
ext := strings.ToLower(pathfilepath.Ext(filePath))
switch ext {