Added ability to discern a short from yt-dlp response

This commit is contained in:
Kieran Eglin 2024-03-08 21:57:45 -08:00
parent f50bcb24bf
commit 451c52ae06
No known key found for this signature in database
GPG key ID: 193984967FCF432D
6 changed files with 113 additions and 19 deletions

View file

@ -3,12 +3,22 @@ defmodule Pinchflat.YtDlp.Backend.Media do
Contains utilities for working with singular pieces of media Contains utilities for working with singular pieces of media
""" """
@enforce_keys [
:media_id,
:title,
:description,
:original_url,
:livestream,
:short_form_content
]
defstruct [ defstruct [
:media_id, :media_id,
:title, :title,
:description, :description,
:original_url, :original_url,
:livestream :livestream,
:short_form_content
] ]
alias __MODULE__ alias __MODULE__
@ -57,20 +67,39 @@ defmodule Pinchflat.YtDlp.Backend.Media do
Returns the output template for yt-dlp's indexing command. Returns the output template for yt-dlp's indexing command.
""" """
def indexing_output_template do def indexing_output_template do
"%(.{id,title,was_live,original_url,description})j" "%(.{id,title,was_live,webpage_url,description,aspect_ratio,duration})j"
end end
# TODO: test @doc """
Transforms a response from yt-dlp into a struct. Interprets the response to
determine if the media is short-form content.
Returns %Media{}.
"""
def response_to_struct(response) do def response_to_struct(response) do
%Media{ %Media{
media_id: response["id"], media_id: response["id"],
title: response["title"], title: response["title"],
description: response["description"], description: response["description"],
original_url: response["original_url"], original_url: response["webpage_url"],
livestream: response["was_live"] livestream: response["was_live"],
short_form_content: short_form_content?(response)
} }
end end
defp short_form_content?(response) do
if String.contains?(response["webpage_url"], "/shorts/") do
true
else
# Sometimes shorts are returned without /shorts/ in the URL,
# so we need to do our best to determine if it's a short. This
# WILL returns false positives, but it's a best-effort approach
# that should work for most cases. The aspect_ratio check is
# based on a gut feeling and may need to be tweaked.
response["duration"] <= 60 && response["aspect_ratio"] < 0.8
end
end
defp backend_runner do defp backend_runner do
# This approach lets us mock the command for testing # This approach lets us mock the command for testing
Application.get_env(:pinchflat, :yt_dlp_runner) Application.get_env(:pinchflat, :yt_dlp_runner)

View file

@ -84,9 +84,11 @@ defmodule Pinchflat.Tasks.MediaItemTasksTest do
Phoenix.json_library().encode!(%{ Phoenix.json_library().encode!(%{
id: "video2", id: "video2",
title: "Video 2", title: "Video 2",
original_url: "https://example.com/shorts/video2", webpage_url: "https://example.com/shorts/video2",
was_live: true, was_live: true,
description: "desc2" description: "desc2",
aspect_ratio: 1.67,
duration: 345.67
}) })
{:ok, output} {:ok, output}

View file

@ -229,9 +229,11 @@ defmodule Pinchflat.Tasks.SourceTasksTest do
Phoenix.json_library().encode!(%{ Phoenix.json_library().encode!(%{
id: "video2", id: "video2",
title: "Video 2", title: "Video 2",
original_url: "https://example.com/shorts/video2", webpage_url: "https://example.com/shorts/video2",
was_live: true, was_live: true,
description: "desc2" description: "desc2",
aspect_ratio: 1.67,
duration: 345.67
}) })
File.write(filepath, contents) File.write(filepath, contents)

View file

@ -64,7 +64,7 @@ defmodule Pinchflat.YtDlp.Backend.MediaTest do
assert opts == [:simulate, :skip_download] assert opts == [:simulate, :skip_download]
assert ot == Media.indexing_output_template() assert ot == Media.indexing_output_template()
{:ok, "{}"} {:ok, media_attributes_return_fixture()}
end) end)
assert {:ok, _} = Media.get_media_attributes(@media_url) assert {:ok, _} = Media.get_media_attributes(@media_url)
@ -79,8 +79,61 @@ defmodule Pinchflat.YtDlp.Backend.MediaTest do
describe "indexing_output_template/0" do describe "indexing_output_template/0" do
test "contains all the greatest hits" do test "contains all the greatest hits" do
assert "%(.{id,title,was_live,original_url,description})j" == assert "%(.{id,title,was_live,webpage_url,description,aspect_ratio,duration})j" ==
Media.indexing_output_template() Media.indexing_output_template()
end end
end end
describe "response_to_struct/1" do
test "transforms a response into a struct" do
response = %{
"id" => "TiZPUDkDYbk",
"title" => "Trying to Wheelie Without the Rear Brake",
"description" => "I'm not sure what I expected.",
"webpage_url" => "https://www.youtube.com/watch?v=TiZPUDkDYbk",
"was_live" => false,
"aspect_ratio" => 1.0,
"duration" => 60
}
assert %Media{
media_id: "TiZPUDkDYbk",
title: "Trying to Wheelie Without the Rear Brake",
description: "I'm not sure what I expected.",
original_url: "https://www.youtube.com/watch?v=TiZPUDkDYbk",
livestream: false,
short_form_content: false
} = Media.response_to_struct(response)
end
test "sets short_form_content to true if the URL contains /shorts/" do
response = %{
"webpage_url" => "https://www.youtube.com/shorts/TiZPUDkDYbk",
"aspect_ratio" => 1.0,
"duration" => 61
}
assert %Media{short_form_content: true} = Media.response_to_struct(response)
end
test "sets short_form_content to true if the aspect ratio are duration are right" do
response = %{
"webpage_url" => "https://www.youtube.com/watch?v=TiZPUDkDYbk",
"aspect_ratio" => 0.5,
"duration" => 59
}
assert %Media{short_form_content: true} = Media.response_to_struct(response)
end
test "sets short_form_content to false otherwise" do
response = %{
"webpage_url" => "https://www.youtube.com/watch?v=TiZPUDkDYbk",
"aspect_ratio" => 1.0,
"duration" => 61
}
assert %Media{short_form_content: false} = Media.response_to_struct(response)
end
end
end end

View file

@ -71,9 +71,11 @@ defmodule Pinchflat.MediaFixtures do
media_attributes = %{ media_attributes = %{
id: "video1", id: "video1",
title: "Video 1", title: "Video 1",
original_url: "https://example.com/video1", webpage_url: "https://example.com/video1",
was_live: false, was_live: false,
description: "desc1" description: "desc1",
aspect_ratio: 1.67,
duration: 123.45
} }
Phoenix.json_library().encode!(media_attributes) Phoenix.json_library().encode!(media_attributes)

View file

@ -35,23 +35,29 @@ defmodule Pinchflat.SourcesFixtures do
%{ %{
id: "video1", id: "video1",
title: "Video 1", title: "Video 1",
original_url: "https://example.com/video1", webpage_url: "https://example.com/video1",
was_live: false, was_live: false,
description: "desc1" description: "desc1",
aspect_ratio: 1.67,
duration: 12.34
}, },
%{ %{
id: "video2", id: "video2",
title: "Video 2", title: "Video 2",
original_url: "https://example.com/video2", webpage_url: "https://example.com/video2",
was_live: true, was_live: true,
description: "desc2" description: "desc2",
aspect_ratio: 1.67,
duration: 345.67
}, },
%{ %{
id: "video3", id: "video3",
title: "Video 3", title: "Video 3",
original_url: "https://example.com/video3", webpage_url: "https://example.com/video3",
was_live: false, was_live: false,
description: "desc3" description: "desc3",
aspect_ratio: 1.0,
duration: 678.90
} }
] ]