mirror of
https://github.com/mudler/LocalAI.git
synced 2026-05-16 20:52:08 -04:00
feat(audio): set audio content type (#8416)
* feat(audio): set audio content type Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * chore: add tests Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
committed by
GitHub
parent
218d0526cb
commit
697f6aa71c
130
pkg/audio/identify.go
Normal file
130
pkg/audio/identify.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package audio
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dhowden/tag"
|
||||
"github.com/mudler/xlog"
|
||||
)
|
||||
|
||||
// extensionFromFileType returns the file extension for tag.FileType.
|
||||
func extensionFromFileType(ft tag.FileType) string {
|
||||
switch ft {
|
||||
case tag.FLAC:
|
||||
return "flac"
|
||||
case tag.MP3:
|
||||
return "mp3"
|
||||
case tag.OGG:
|
||||
return "ogg"
|
||||
case tag.M4A:
|
||||
return "m4a"
|
||||
case tag.M4B:
|
||||
return "m4b"
|
||||
case tag.M4P:
|
||||
return "m4p"
|
||||
case tag.ALAC:
|
||||
return "m4a"
|
||||
case tag.DSF:
|
||||
return "dsf"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// contentTypeFromFileType returns the MIME type for tag.FileType.
|
||||
func contentTypeFromFileType(ft tag.FileType) string {
|
||||
switch ft {
|
||||
case tag.FLAC:
|
||||
return "audio/flac"
|
||||
case tag.MP3:
|
||||
return "audio/mpeg"
|
||||
case tag.OGG:
|
||||
return "audio/ogg"
|
||||
case tag.M4A, tag.M4B, tag.M4P, tag.ALAC:
|
||||
return "audio/mp4"
|
||||
case tag.DSF:
|
||||
return "audio/dsd"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Identify reads from r and returns the detected audio extension and Content-Type.
|
||||
// It uses github.com/dhowden/tag to identify the format from the stream.
|
||||
// Returns ("", "", err) if the format could not be identified.
|
||||
func Identify(r io.ReadSeeker) (ext string, contentType string, err error) {
|
||||
_, fileType, err := tag.Identify(r)
|
||||
if err != nil || fileType == tag.UnknownFileType {
|
||||
return "", "", err
|
||||
}
|
||||
ext = extensionFromFileType(fileType)
|
||||
contentType = contentTypeFromFileType(fileType)
|
||||
if ext == "" || contentType == "" {
|
||||
return "", "", nil
|
||||
}
|
||||
return ext, contentType, nil
|
||||
}
|
||||
|
||||
// ContentTypeFromExtension returns the MIME type for common audio file extensions.
|
||||
// Use as a fallback when Identify fails or when the file is not openable.
|
||||
func ContentTypeFromExtension(path string) string {
|
||||
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(path), "."))
|
||||
switch ext {
|
||||
case "flac":
|
||||
return "audio/flac"
|
||||
case "mp3":
|
||||
return "audio/mpeg"
|
||||
case "wav":
|
||||
return "audio/wav"
|
||||
case "ogg":
|
||||
return "audio/ogg"
|
||||
case "m4a", "m4b", "m4p":
|
||||
return "audio/mp4"
|
||||
case "webm":
|
||||
return "audio/webm"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// NormalizeAudioFile opens the file at path, identifies its format with tag.Identify,
|
||||
// and renames the file to have the correct extension if the current one does not match.
|
||||
// It returns the path to use (possibly the renamed file) and the Content-Type to set.
|
||||
// If identification fails, returns (path, ContentTypeFromExtension(path)).
|
||||
func NormalizeAudioFile(path string) (finalPath string, contentType string) {
|
||||
finalPath = path
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
contentType = ContentTypeFromExtension(path)
|
||||
return finalPath, contentType
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
ext, ct, identifyErr := Identify(f)
|
||||
if identifyErr != nil || ext == "" || ct == "" {
|
||||
contentType = ContentTypeFromExtension(path)
|
||||
return finalPath, contentType
|
||||
}
|
||||
contentType = ct
|
||||
|
||||
currentExt := strings.ToLower(strings.TrimPrefix(filepath.Ext(path), "."))
|
||||
if currentExt == ext {
|
||||
return finalPath, contentType
|
||||
}
|
||||
|
||||
dir := filepath.Dir(path)
|
||||
base := filepath.Base(path)
|
||||
baseNoExt := strings.TrimSuffix(base, filepath.Ext(base))
|
||||
if baseNoExt == "" {
|
||||
baseNoExt = base
|
||||
}
|
||||
newPath := filepath.Join(dir, baseNoExt+"."+ext)
|
||||
if renameErr := os.Rename(path, newPath); renameErr != nil {
|
||||
xlog.Debug("Could not rename audio file to match type", "from", path, "to", newPath, "error", renameErr)
|
||||
return finalPath, contentType
|
||||
}
|
||||
return newPath, contentType
|
||||
}
|
||||
Reference in New Issue
Block a user