Renamed column; added format options and tests

This commit is contained in:
Kieran Eglin 2024-11-27 09:41:53 -08:00
parent 4bc03c16e9
commit fa22580094
No known key found for this signature in database
GPG key ID: 193984967FCF432D
6 changed files with 73 additions and 20 deletions

View file

@ -1,19 +1,31 @@
defmodule Pinchflat.Downloading.QualityOptionBuilder do
@moduledoc """
A standalone builder module for building quality-related options for yt-dlp to download media.
Currently exclusively used in DownloadOptionBuilder since this logic is too complex to just
place in the main module.
"""
alias Pinchflat.Settings
alias Pinchflat.Profiles.MediaProfile
# TODO: test
def build(%MediaProfile{preferred_resolution: :audio, media_container: container}) do
@doc """
Builds the quality-related options for yt-dlp to download media based on the given media profile
Includes things like container, preferred format/codec, and audio track options.
"""
def build(%MediaProfile{preferred_resolution: :audio, media_container: container} = media_profile) do
acodec = Settings.get!(:audio_codec_preference)
[
:extract_audio,
format_sort: "+acodec:#{acodec}",
audio_format: container || "best"
] ++ build_format_string(nil)
audio_format: container || "best",
format: build_format_string(media_profile)
]
end
def build(%MediaProfile{preferred_resolution: resolution_atom, media_container: container}) do
def build(%MediaProfile{preferred_resolution: resolution_atom, media_container: container} = media_profile) do
vcodec = Settings.get!(:video_codec_preference)
acodec = Settings.get!(:audio_codec_preference)
{resolution_string, _} = resolution_atom |> Atom.to_string() |> Integer.parse()
@ -21,22 +33,27 @@ defmodule Pinchflat.Downloading.QualityOptionBuilder do
[
# Since Plex doesn't support reading metadata from MKV
remux_video: container || "mp4",
format_sort: "res:#{resolution_string},+codec:#{vcodec}:#{acodec}"
] ++ build_format_string(nil)
format_sort: "res:#{resolution_string},+codec:#{vcodec}:#{acodec}",
format: build_format_string(media_profile)
]
end
# TODO: pass in the entire media profile once we have the language preference column
# TODO: test
# TODO: Set to ba/b if it's audio-only
defp build_format_string(language_preference) do
if language_preference do
["bestvideo+bestaudio[#{build_format_modifier(language_preference)}]/bestvideo*+bestaudio/best"]
defp build_format_string(%MediaProfile{preferred_resolution: :audio, audio_track: audio_track}) do
if audio_track do
"bestaudio[#{build_format_modifier(audio_track)}]/bestaudio/best"
else
["bestvideo*+bestaudio/best"]
"bestaudio/best"
end
end
defp build_format_string(%MediaProfile{audio_track: audio_track}) do
if audio_track do
"bestvideo+bestaudio[#{build_format_modifier(audio_track)}]/bestvideo*+bestaudio/best"
else
"bestvideo*+bestaudio/best"
end
end
# TODO: test
defp build_format_modifier("original"), do: "format_note*=original"
defp build_format_modifier("default"), do: "format_note*=(default)"
# This uses the carat to anchor the language to the beginning of the string

View file

@ -26,7 +26,7 @@ defmodule Pinchflat.Profiles.MediaProfile do
sponsorblock_categories
shorts_behaviour
livestream_behaviour
audio_lang
audio_track
preferred_resolution
media_container
redownload_delay_days
@ -66,7 +66,7 @@ defmodule Pinchflat.Profiles.MediaProfile do
# See `build_format_clauses` in the Media context for more.
field :shorts_behaviour, Ecto.Enum, values: ~w(include exclude only)a, default: :include
field :livestream_behaviour, Ecto.Enum, values: ~w(include exclude only)a, default: :include
field :audio_lang, :string
field :audio_track, :string
field :preferred_resolution, Ecto.Enum, values: ~w(4320p 2160p 1080p 720p 480p 360p audio)a, default: :"1080p"
field :media_container, :string, default: nil

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

After

Width:  |  Height:  |  Size: 438 KiB

View file

@ -3,7 +3,7 @@ defmodule Pinchflat.Repo.Migrations.AddAudioLangToMediaProfiles do
def change do
alter table(:media_profiles) do
add :audio_lang, :string
add :audio_track, :string
end
end
end

View file

@ -6,7 +6,6 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilderTest do
alias Pinchflat.Sources
alias Pinchflat.Profiles
alias Pinchflat.Settings
alias Pinchflat.Utils.FilesystemUtils
alias Pinchflat.Downloading.DownloadOptionBuilder

View file

@ -6,7 +6,32 @@ defmodule Pinchflat.Downloading.QualityOptionBuilderTest do
alias Pinchflat.Settings
alias Pinchflat.Downloading.QualityOptionBuilder
# TODO: this basically tests the existing logic but doesn't test any of the new stuff. Add those tests.
describe "build/1" do
test "includes format options if audio_track is set to original" do
media_profile = media_profile_fixture(%{audio_track: "original"})
assert res = QualityOptionBuilder.build(media_profile)
assert {:format, "bestvideo+bestaudio[format_note*=original]/bestvideo*+bestaudio/best"} in res
end
test "includes format options if audio_track is set to default" do
media_profile = media_profile_fixture(%{audio_track: "default"})
assert res = QualityOptionBuilder.build(media_profile)
assert {:format, "bestvideo+bestaudio[format_note*=(default)]/bestvideo*+bestaudio/best"} in res
end
test "includes format options if audio_track is set to a language code" do
media_profile = media_profile_fixture(%{audio_track: "en"})
assert res = QualityOptionBuilder.build(media_profile)
assert {:format, "bestvideo+bestaudio[language^=en]/bestvideo*+bestaudio/best"} in res
end
end
describe "build/1 when testing audio profiles" do
setup do
{:ok, media_profile: media_profile_fixture(%{preferred_resolution: :audio})}
@ -29,6 +54,12 @@ defmodule Pinchflat.Downloading.QualityOptionBuilderTest do
assert {:audio_format, "flac"} in res
end
test "includes custom format options", %{media_profile: media_profile} do
assert res = QualityOptionBuilder.build(media_profile)
assert {:format, "bestaudio/best"} in res
end
end
describe "build/1 when testing non-audio profiles" do
@ -68,5 +99,11 @@ defmodule Pinchflat.Downloading.QualityOptionBuilderTest do
assert {:remux_video, "mkv"} in res
end
test "includes custom format options", %{media_profile: media_profile} do
assert res = QualityOptionBuilder.build(media_profile)
assert {:format, "bestvideo*+bestaudio/best"} in res
end
end
end