5 Commits

Author SHA1 Message Date
鲁树人
f819726f3e chore: bump version to v0.2.4 2024-10-21 03:59:52 +09:00
鲁树人
fbad7ec450 fix #102: support multi-part kgm extensions (kgm.flac/vpr.flac) 2024-10-21 03:58:21 +09:00
鲁树人
19bc6c466e refactor: allow multi-part extensions (#102) 2024-10-21 03:57:56 +09:00
鲁树人
b9e2a38f82 fix: do not throw error when file already exists 2024-10-21 03:56:52 +09:00
鲁树人
673ea8491f docs: add do not fork notice 2024-10-13 05:45:25 +09:00
4 changed files with 57 additions and 32 deletions

View File

@@ -6,6 +6,9 @@ Original: Web Edition https://git.unlock-music.dev/um/web
- [Release Download](https://git.unlock-music.dev/um/cli/releases/latest)
- [Latest Build](https://git.unlock-music.dev/um/-/packages/generic/cli-build/)
> **WARNING**
> 在本站 fork 不会起到备份的作用,只会浪费服务器储存空间。如无必要请勿 fork 该仓库。
## Features
- [x] All Algorithm Supported By `unlock-music/web`

View File

@@ -18,25 +18,32 @@ type DecoderParams struct {
}
type NewDecoderFunc func(p *DecoderParams) Decoder
type decoderItem struct {
type DecoderFactory struct {
noop bool
decoder NewDecoderFunc
Suffix string
Create NewDecoderFunc
}
var DecoderRegistry = make(map[string][]decoderItem)
var DecoderRegistry []DecoderFactory
func RegisterDecoder(ext string, noop bool, dispatchFunc NewDecoderFunc) {
DecoderRegistry[ext] = append(DecoderRegistry[ext],
decoderItem{noop: noop, decoder: dispatchFunc})
DecoderRegistry = append(DecoderRegistry,
DecoderFactory{noop: noop, Create: dispatchFunc, Suffix: "." + strings.TrimPrefix(ext, ".")})
}
func GetDecoder(filename string, skipNoop bool) (rs []NewDecoderFunc) {
ext := strings.ToLower(strings.TrimLeft(filepath.Ext(filename), "."))
for _, dec := range DecoderRegistry[ext] {
func GetDecoder(filename string, skipNoop bool) []DecoderFactory {
var result []DecoderFactory
// Some extensions contains multiple dots, e.g. ".kgm.flac", hence iterate
// all decoders for each extension.
name := strings.ToLower(filepath.Base(filename))
for _, dec := range DecoderRegistry {
if !strings.HasSuffix(name, dec.Suffix) {
continue
}
if skipNoop && dec.noop {
continue
}
rs = append(rs, dec.decoder)
result = append(result, dec)
}
return
return result
}

View File

@@ -61,4 +61,7 @@ func init() {
common.RegisterDecoder("kgma", false, NewDecoder)
// Viper
common.RegisterDecoder("vpr", false, NewDecoder)
// Kugou Android
common.RegisterDecoder("kgm.flac", false, NewDecoder)
common.RegisterDecoder("vpr.flac", false, NewDecoder)
}

View File

@@ -34,7 +34,7 @@ import (
"unlock-music.dev/cli/internal/utils"
)
var AppVersion = "v0.2.3"
var AppVersion = "v0.2.4"
var logger, _ = logging.NewZapLogger() // TODO: inject logger to application, instead of using global logger
@@ -75,12 +75,21 @@ func main() {
func printSupportedExtensions() {
var exts []string
for ext := range common.DecoderRegistry {
extSet := make(map[string]int)
for _, factory := range common.DecoderRegistry {
ext := strings.TrimPrefix(factory.Suffix, ".")
if n, ok := extSet[ext]; ok {
extSet[ext] = n + 1
} else {
extSet[ext] = 1
}
}
for ext := range extSet {
exts = append(exts, ext)
}
sort.Strings(exts)
for _, ext := range exts {
fmt.Printf("%s: %d\n", ext, len(common.DecoderRegistry[ext]))
fmt.Printf("%s: %d\n", ext, extSet[ext])
}
}
@@ -276,7 +285,19 @@ func (p *processor) processFile(filePath string) error {
return nil
}
func (p *processor) process(inputFile string, allDec []common.NewDecoderFunc) error {
func (p *processor) findDecoder(decoders []common.DecoderFactory, params *common.DecoderParams) (*common.Decoder, *common.DecoderFactory, error) {
for _, factory := range decoders {
dec := factory.Create(params)
err := dec.Validate()
if err == nil {
return &dec, &factory, nil
}
logger.Warn("try decode failed", zap.Error(err))
}
return nil, nil, errors.New("no any decoder can resolve the file")
}
func (p *processor) process(inputFile string, allDec []common.DecoderFactory) error {
file, err := os.Open(inputFile)
if err != nil {
return err
@@ -284,26 +305,16 @@ func (p *processor) process(inputFile string, allDec []common.NewDecoderFunc) er
defer file.Close()
logger := logger.With(zap.String("source", inputFile))
decParams := &common.DecoderParams{
pDec, decoderFactory, err := p.findDecoder(allDec, &common.DecoderParams{
Reader: file,
Extension: filepath.Ext(inputFile),
FilePath: inputFile,
Logger: logger,
})
if err != nil {
return err
}
var dec common.Decoder
for _, decFunc := range allDec {
dec = decFunc(decParams)
if err := dec.Validate(); err == nil {
break
} else {
logger.Warn("try decode failed", zap.Error(err))
dec = nil
}
}
if dec == nil {
return errors.New("no any decoder can resolve the file")
}
dec := *pDec
params := &ffmpeg.UpdateMetadataParams{}
@@ -365,13 +376,14 @@ func (p *processor) process(inputFile string, allDec []common.NewDecoderFunc) er
return fmt.Errorf("get relative dir failed: %w", err)
}
inFilename := strings.TrimSuffix(filepath.Base(inputFile), filepath.Ext(inputFile))
inFilename := strings.TrimSuffix(filepath.Base(inputFile), decoderFactory.Suffix)
outPath := filepath.Join(p.outputDir, inputRelDir, inFilename+params.AudioExt)
if !p.overwriteOutput {
_, err := os.Stat(outPath)
if err == nil {
return fmt.Errorf("output file %s is already exist", outPath)
logger.Warn("output file already exist, skip", zap.String("destination", outPath))
return nil
} else if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("stat output file failed: %w", err)
}