4ddb0774ec
* test(artwork): add benchmark helpers for generating test images * test(artwork): add image decode benchmarks for JPEG/PNG at various sizes * test(artwork): add image resize benchmarks for Lanczos at various sizes * test(artwork): add image encode benchmarks for JPEG quality levels and PNG * test(artwork): add full resize pipeline benchmark (decode+resize+encode) * test(artwork): add tag extraction benchmark for embedded art * test(cache): add file cache benchmarks for read, write, and concurrent access * test(artwork): add E2E benchmarks for artwork.Get with cache on/off and concurrency * fix(test): use absolute path for tag extraction benchmark fixture * test(artwork): add resize alternatives benchmark comparing resamplers * perf(artwork): switch to CatmullRom resampler and JPEG for square images Replace imaging.Lanczos with imaging.CatmullRom for image resizing (30% faster, indistinguishable quality at thumbnail sizes). Stop forcing PNG encoding for square images when the source is JPEG — JPEG is smaller and faster to encode. Square images from JPEG sources went from 52ms to 10ms (80% improvement). Add sync.Pool for encode buffers to reduce GC pressure under concurrent load. * perf(artwork): increase cache warmer concurrency from 2 to 4 workers Resize is CPU-bound, so more workers improve throughput on multi-core systems. Doubled worker count to better utilize available cores during background cache warming. * perf(artwork): switch to xdraw.ApproxBiLinear and always encode as JPEG Replace disintegration/imaging with golang.org/x/image/draw for image resizing. This eliminates ~92K allocations per resize (from imaging's internal goroutine parallelism) down to ~20, reducing GC pressure under concurrent load. Always encode resized artwork as JPEG regardless of source format, since cover art doesn't need transparency. This is ~5x faster than PNG encode and produces much smaller output (e.g. 18KB JPEG vs 124KB PNG). * perf(artwork): skip external API call when artist image URL is cached ArtistImage() was always calling the external agent (Spotify/Last.fm) to get the image URL, even when the artist already had URLs stored in the database. This caused every artist image request to block on an external API call, creating severe serialization when loading artist grids (5-20 seconds for the first page). Now use the stored URL directly when available. Artists with no stored URL still fetch synchronously. Background refresh via UpdateArtistInfo handles TTL-based URL updates. * perf(artwork): increase getCoverArt throttle from NumCPU/3 to NumCPU The previous default of max(2, NumCPU/3) was too aggressive for artist images which are I/O-bound (downloading from external CDNs), not CPU-bound. On an 8-core machine this meant only 2 concurrent requests, causing a staircase pattern where 12 images took ~2.4s wall-clock. Bumping to max(4, NumCPU) cuts wall-clock time by ~50% for artist image grids while still preventing unbounded concurrency for CPU-bound resizes. * perf(artwork): encode resized images as WebP instead of JPEG Switch from JPEG to WebP encoding for resized artwork using gen2brain/webp (libwebp via WASM, no CGo). WebP produces ~74% smaller output at the same quality with only ~25% slower full-pipeline encode time (cached, so only paid once per artwork+size). Use NRGBA image type to preserve alpha channel in WebP output, and transparent padding for square canvas instead of black. Also removes the disintegration/imaging dependency entirely by replacing imaging.Fill in playlist tile generation with a custom fillCenter function using xdraw.ApproxBiLinear. * perf(artwork): switch from ApproxBiLinear to BiLinear scaling for improved image processing Signed-off-by: Deluan <deluan@navidrome.org> * refactor(configuration): rename CoverJpegQuality to CoverArtQuality and update references Signed-off-by: Deluan <deluan@navidrome.org> * feat(artwork): add DevJpegCoverArt option to control JPEG encoding for cover art Signed-off-by: Deluan <deluan@navidrome.org> * fix(artwork): remove redundant transparent fill and handle encode errors in resizeImage Removed a no-op draw.Draw call that filled the NRGBA canvas with transparent pixels — NewNRGBA already zero-initializes to fully transparent. Also added an early return on encode failure to avoid allocating and copying potentially corrupt buffer data before returning the error. * fix(configuration): reorder default agents (deezer is faster) Signed-off-by: Deluan <deluan@navidrome.org> * fix(test): resolve dogsled lint warning in tag extraction benchmark Use all return values from runtime.Caller instead of discarding three with blank identifiers, which triggered the dogsled linter. * fix(artwork): revert cache key format Signed-off-by: Deluan <deluan@navidrome.org> * fix(configuration): remove deprecated CoverJpegQuality field and update references to CoverArtQuality Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org>
155 lines
6.4 KiB
Modula-2
155 lines
6.4 KiB
Modula-2
module github.com/navidrome/navidrome
|
|
|
|
go 1.25.0
|
|
|
|
// Fork to implement raw tags support
|
|
replace go.senan.xyz/taglib => github.com/deluan/go-taglib v0.0.0-20260307161927-168f6e74ada7
|
|
|
|
require (
|
|
github.com/Masterminds/squirrel v1.5.4
|
|
github.com/RaveNoX/go-jsoncommentstrip v1.0.0
|
|
github.com/andybalholm/cascadia v1.3.3
|
|
github.com/bmatcuk/doublestar/v4 v4.10.0
|
|
github.com/bradleyjkemp/cupaloy/v2 v2.8.0
|
|
github.com/deluan/rest v0.0.0-20211102003136-6260bc399cbf
|
|
github.com/deluan/sanitize v0.0.0-20241120162836-fdfd8fdfaa55
|
|
github.com/dexterlb/mpvipc v0.0.0-20241005113212-7cdefca0e933
|
|
github.com/djherbis/atime v1.1.0
|
|
github.com/djherbis/fscache v0.10.2-0.20231127215153-442a07e326c4
|
|
github.com/djherbis/stream v1.4.0
|
|
github.com/djherbis/times v1.6.0
|
|
github.com/dustin/go-humanize v1.0.1
|
|
github.com/extism/go-sdk v1.7.1
|
|
github.com/fatih/structs v1.1.0
|
|
github.com/gen2brain/webp v0.5.5
|
|
github.com/go-chi/chi/v5 v5.2.5
|
|
github.com/go-chi/cors v1.2.2
|
|
github.com/go-chi/httprate v0.15.0
|
|
github.com/go-chi/jwtauth/v5 v5.4.0
|
|
github.com/go-viper/encoding/ini v0.1.1
|
|
github.com/gohugoio/hashstructure v0.6.0
|
|
github.com/google/go-pipeline v0.0.0-20230411140531-6cbedfc1d3fc
|
|
github.com/google/uuid v1.6.0
|
|
github.com/google/wire v0.7.0
|
|
github.com/gorilla/websocket v1.5.3
|
|
github.com/hashicorp/go-multierror v1.1.1
|
|
github.com/jellydator/ttlcache/v3 v3.4.0
|
|
github.com/kardianos/service v1.2.4
|
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
|
github.com/kr/pretty v0.3.1
|
|
github.com/lestrrat-go/jwx/v3 v3.0.13
|
|
github.com/maruel/natural v1.3.0
|
|
github.com/matoous/go-nanoid/v2 v2.1.0
|
|
github.com/mattn/go-sqlite3 v1.14.34
|
|
github.com/microcosm-cc/bluemonday v1.0.27
|
|
github.com/mileusna/useragent v1.3.5
|
|
github.com/onsi/ginkgo/v2 v2.28.1
|
|
github.com/onsi/gomega v1.39.1
|
|
github.com/pelletier/go-toml/v2 v2.2.4
|
|
github.com/pocketbase/dbx v1.12.0
|
|
github.com/pressly/goose/v3 v3.27.0
|
|
github.com/prometheus/client_golang v1.23.2
|
|
github.com/rjeczalik/notify v0.9.3
|
|
github.com/robfig/cron/v3 v3.0.1
|
|
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
|
github.com/sirupsen/logrus v1.9.4
|
|
github.com/spf13/cobra v1.10.2
|
|
github.com/spf13/viper v1.21.0
|
|
github.com/stretchr/testify v1.11.1
|
|
github.com/tetratelabs/wazero v1.11.0
|
|
github.com/unrolled/secure v1.17.0
|
|
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342
|
|
go.senan.xyz/taglib v0.11.1
|
|
go.uber.org/goleak v1.3.0
|
|
golang.org/x/image v0.36.0
|
|
golang.org/x/net v0.51.0
|
|
golang.org/x/sync v0.20.0
|
|
golang.org/x/sys v0.42.0
|
|
golang.org/x/term v0.40.0
|
|
golang.org/x/text v0.34.0
|
|
golang.org/x/time v0.15.0
|
|
gopkg.in/yaml.v3 v3.0.1
|
|
)
|
|
|
|
require (
|
|
dario.cat/mergo v1.0.2 // indirect
|
|
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
|
github.com/atombender/go-jsonschema v0.20.0 // indirect
|
|
github.com/aymerick/douceur v0.2.0 // indirect
|
|
github.com/beorn7/perks v1.0.1 // indirect
|
|
github.com/cespare/reflex v0.3.1 // indirect
|
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
|
github.com/creack/pty v1.1.24 // indirect
|
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect
|
|
github.com/dylibso/observe-sdk/go v0.0.0-20240828172851-9145d8ad07e1 // indirect
|
|
github.com/ebitengine/purego v0.8.3 // indirect
|
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
|
github.com/go-logr/logr v1.4.3 // indirect
|
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
|
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
|
github.com/gobwas/glob v0.2.3 // indirect
|
|
github.com/goccy/go-json v0.10.5 // indirect
|
|
github.com/goccy/go-yaml v1.19.2 // indirect
|
|
github.com/google/go-cmp v0.7.0 // indirect
|
|
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc // indirect
|
|
github.com/google/subcommands v1.2.0 // indirect
|
|
github.com/gorilla/css v1.0.1 // indirect
|
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
|
github.com/ianlancetaylor/demangle v0.0.0-20251118225945-96ee0021ea0f // indirect
|
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
|
github.com/kr/text v0.2.0 // indirect
|
|
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
|
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
|
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
|
|
github.com/lestrrat-go/dsig v1.0.0 // indirect
|
|
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
|
|
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
|
github.com/lestrrat-go/httprc/v3 v3.0.4 // indirect
|
|
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
|
|
github.com/mfridman/interpolate v0.0.2 // indirect
|
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
|
github.com/ogier/pflag v0.0.1 // indirect
|
|
github.com/pkg/errors v0.9.1 // indirect
|
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
|
github.com/prometheus/client_model v0.6.2 // indirect
|
|
github.com/prometheus/common v0.67.5 // indirect
|
|
github.com/prometheus/procfs v0.19.2 // indirect
|
|
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
|
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
|
github.com/sanity-io/litter v1.5.8 // indirect
|
|
github.com/segmentio/asm v1.2.1 // indirect
|
|
github.com/sethvargo/go-retry v0.3.0 // indirect
|
|
github.com/sosodev/duration v1.3.1 // indirect
|
|
github.com/spf13/afero v1.15.0 // indirect
|
|
github.com/spf13/cast v1.10.0 // indirect
|
|
github.com/spf13/pflag v1.0.10 // indirect
|
|
github.com/stretchr/objx v0.5.3 // indirect
|
|
github.com/subosito/gotenv v1.6.0 // indirect
|
|
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
|
|
github.com/valyala/fastjson v1.6.10 // indirect
|
|
github.com/zeebo/xxh3 v1.1.0 // indirect
|
|
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
|
go.uber.org/multierr v1.11.0 // indirect
|
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
|
golang.org/x/crypto v0.48.0 // indirect
|
|
golang.org/x/mod v0.33.0 // indirect
|
|
golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4 // indirect
|
|
golang.org/x/tools v0.42.0 // indirect
|
|
google.golang.org/protobuf v1.36.11 // indirect
|
|
gopkg.in/ini.v1 v1.67.1 // indirect
|
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
|
)
|
|
|
|
tool (
|
|
github.com/atombender/go-jsonschema
|
|
github.com/cespare/reflex
|
|
github.com/google/wire/cmd/wire
|
|
github.com/onsi/ginkgo/v2/ginkgo
|
|
golang.org/x/tools/cmd/goimports
|
|
)
|