feat(media): fallback to lower quality if requested format is unavailable

This commit is contained in:
Mathis Maquenne
2025-08-06 22:09:06 +02:00
parent b4f69396af
commit 50fde9dfa9
4 changed files with 16 additions and 18 deletions
+3
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"strings"
"time" "time"
"github.com/mathismqn/godeez/internal/config" "github.com/mathismqn/godeez/internal/config"
@@ -53,6 +54,8 @@ func newDownloadCmd(resourceType string) *cobra.Command {
} }
cmd.SetContext(context.WithValue(cmd.Context(), "appConfig", appConfig)) cmd.SetContext(context.WithValue(cmd.Context(), "appConfig", appConfig))
opts.Quality = strings.ToLower(opts.Quality)
return opts.Validate() return opts.Validate()
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
+2 -4
View File
@@ -98,10 +98,8 @@ func (c *Client) FetchMedia(ctx context.Context, song *Song, quality string) (*M
case "mp3_128": case "mp3_128":
formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]` formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]`
case "mp3_320": case "mp3_320":
formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_320"}]` formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_320"},{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]`
case "flac": case "flac", "best":
formats = `[{"cipher":"BF_CBC_STRIPE","format":"FLAC"}]`
case "best":
formats = `[{"cipher":"BF_CBC_STRIPE","format":"FLAC"},{"cipher":"BF_CBC_STRIPE","format":"MP3_320"},{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]` formats = `[{"cipher":"BF_CBC_STRIPE","format":"FLAC"},{"cipher":"BF_CBC_STRIPE","format":"MP3_320"},{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]`
} }
+1 -9
View File
@@ -36,15 +36,7 @@ func (m *Media) GetURL() (string, error) {
return "", fmt.Errorf("no media sources found") return "", fmt.Errorf("no media sources found")
} }
url := m.Data[0].Media[0].Sources[0].URL return m.Data[0].Media[0].Sources[0].URL, nil
for _, source := range m.Data[0].Media[0].Sources {
if source.Provider == "ak" {
url = source.URL
break
}
}
return url, nil
} }
func (m *Media) GetFormat() (string, error) { func (m *Media) GetFormat() (string, error) {
+10 -5
View File
@@ -7,6 +7,7 @@ import (
"io" "io"
"os" "os"
"path" "path"
"strings"
"sync" "sync"
"time" "time"
@@ -168,7 +169,7 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son
media, err := c.deezerClient.FetchMedia(ctx, song, opts.Quality) media, err := c.deezerClient.FetchMedia(ctx, song, opts.Quality)
if err != nil { if err != nil {
return warnings, fmt.Errorf("failed to fetch media: %w", err) return nil, fmt.Errorf("failed to fetch media: %w", err)
} }
fileName := song.GetFileName(c.resourceType, song, media) fileName := song.GetFileName(c.resourceType, song, media)
@@ -176,11 +177,11 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son
mediaFormat, err := media.GetFormat() mediaFormat, err := media.GetFormat()
if err != nil { if err != nil {
return warnings, fmt.Errorf("failed to get media format: %w", err) return nil, fmt.Errorf("failed to get media format: %w", err)
} }
if path, skip := c.shouldSkipDownload(ctx, song.ID, mediaFormat); skip { if path, skip := c.shouldSkipDownload(ctx, song.ID, mediaFormat); skip {
return warnings, SkipError{Path: path} return nil, SkipError{Path: path}
} }
var metricsChan chan *bpm.Metrics var metricsChan chan *bpm.Metrics
@@ -201,7 +202,7 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son
stream, err := c.deezerClient.GetMediaStream(ctx, media, song.ID) stream, err := c.deezerClient.GetMediaStream(ctx, media, song.ID)
if err != nil { if err != nil {
return warnings, fmt.Errorf("failed to get media stream: %w", err) return nil, fmt.Errorf("failed to get media stream: %w", err)
} }
dlCtx, cancel := context.WithTimeout(ctx, opts.Timeout) dlCtx, cancel := context.WithTimeout(ctx, opts.Timeout)
@@ -211,7 +212,11 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son
if err := c.streamToFile(dlCtx, stream, outputPath, key); err != nil { if err := c.streamToFile(dlCtx, stream, outputPath, key); err != nil {
fileutil.DeleteFile(outputPath) fileutil.DeleteFile(outputPath)
return warnings, fmt.Errorf("failed to stream to file: %w", err) return nil, fmt.Errorf("failed to stream to file: %w", err)
}
if opts.Quality != strings.ToLower(mediaFormat) {
warnings = append(warnings, fmt.Sprintf("requested quality '%s' not available, using '%s' instead", opts.Quality, strings.ToLower(mediaFormat)))
} }
metrics := &bpm.Metrics{} metrics := &bpm.Metrics{}