diff --git a/config/test.exs b/config/test.exs index 790f2be4..641b1ed8 100644 --- a/config/test.exs +++ b/config/test.exs @@ -101,6 +101,8 @@ config :music_library, OpenAI, config :phoenix_test, :endpoint, MusicLibraryWeb.Endpoint +config :music_library, color_extractor: MusicLibrary.Colors.FakeColorExtractor + config :music_library, Oban, testing: :manual config :music_library, MusicLibrary.Mailer, adapter: Swoosh.Adapters.Test diff --git a/lib/music_library/colors/extractor.ex b/lib/music_library/colors/extractor.ex new file mode 100644 index 00000000..8aefe9e4 --- /dev/null +++ b/lib/music_library/colors/extractor.ex @@ -0,0 +1,9 @@ +defmodule MusicLibrary.Colors.Extractor do + @moduledoc """ + Behaviour that defines the functions necessary to implement a dominant colors + extractor. + """ + + @callback extract_dominant_colors(binary(), pos_integer()) :: + {:ok, [String.t()]} | {:error, term()} +end diff --git a/lib/music_library/colors/k_means_extractor.ex b/lib/music_library/colors/k_means_extractor.ex index 4219e92f..883a2237 100644 --- a/lib/music_library/colors/k_means_extractor.ex +++ b/lib/music_library/colors/k_means_extractor.ex @@ -3,9 +3,11 @@ defmodule MusicLibrary.Colors.KMeansExtractor do Extracts dominant colors from images using K-Means clustering via the dominant_colors library. """ + @behaviour MusicLibrary.Colors.Extractor + alias Vix.Vips.Image - @spec extract_dominant_colors(binary(), pos_integer()) :: {:ok, [String.t()]} | {:error, term()} + @impl true def extract_dominant_colors(image_data, num_colors \\ 5) do :telemetry.span( [:music_library, :colors, :extract], diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index f9225eeb..fa616726 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -7,10 +7,15 @@ defmodule MusicLibrary.Records do alias MusicLibrary.Artists alias MusicLibrary.Assets - alias MusicLibrary.Colors.KMeansExtractor alias MusicLibrary.Records.{ArtistRecord, Record, SearchIndex, SearchParser} alias MusicLibrary.{Repo, Worker} + @color_extractor Application.compile_env( + :music_library, + :color_extractor, + MusicLibrary.Colors.KMeansExtractor + ) + @type import_opts :: [ format: atom(), purchased_at: DateTime.t() | nil, @@ -305,7 +310,7 @@ defmodule MusicLibrary.Records do def extract_colors(record) do asset = Assets.get!(record.cover_hash) - with {:ok, colors} <- KMeansExtractor.extract_dominant_colors(asset.content) do + with {:ok, colors} <- @color_extractor.extract_dominant_colors(asset.content) do update_record(record, %{dominant_colors: colors}) end end diff --git a/test/support/fake_color_extractor.ex b/test/support/fake_color_extractor.ex new file mode 100644 index 00000000..37706395 --- /dev/null +++ b/test/support/fake_color_extractor.ex @@ -0,0 +1,14 @@ +defmodule MusicLibrary.Colors.FakeColorExtractor do + @moduledoc """ + Test stub for `MusicLibrary.Colors.KMeansExtractor`. + + Returns hardcoded colors to avoid CPU-intensive K-means clustering in tests. + """ + + @behaviour MusicLibrary.Colors.Extractor + + @impl true + def extract_dominant_colors(_image_data, _num_colors \\ 5) do + {:ok, ["#000000", "#c0c0c0", "#c08080", "#404000", "#804040"]} + end +end