Adds options + option builder + metadata parsing for media thumbnails
This commit is contained in:
parent
ca01f17b58
commit
3e5faa0503
9 changed files with 281 additions and 48 deletions
|
|
@ -11,12 +11,13 @@ defmodule Pinchflat.Media.MediaItem do
|
||||||
alias Pinchflat.Media.MediaMetadata
|
alias Pinchflat.Media.MediaMetadata
|
||||||
|
|
||||||
@required_fields ~w(media_id source_id)a
|
@required_fields ~w(media_id source_id)a
|
||||||
@allowed_fields ~w(title media_id media_filepath source_id subtitle_filepaths)a
|
@allowed_fields ~w(title media_id media_filepath source_id subtitle_filepaths thumbnail_filepath)a
|
||||||
|
|
||||||
schema "media_items" do
|
schema "media_items" do
|
||||||
field :title, :string
|
field :title, :string
|
||||||
field :media_id, :string
|
field :media_id, :string
|
||||||
field :media_filepath, :string
|
field :media_filepath, :string
|
||||||
|
field :thumbnail_filepath, :string
|
||||||
# This is an array of [iso-2 language, filepath] pairs. Probably could
|
# This is an array of [iso-2 language, filepath] pairs. Probably could
|
||||||
# be an associated record, but I don't see the benefit right now.
|
# be an associated record, but I don't see the benefit right now.
|
||||||
# Will very likely revisit because I can't leave well-enough alone.
|
# Will very likely revisit because I can't leave well-enough alone.
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MetadataParser do
|
||||||
metadata_attrs
|
metadata_attrs
|
||||||
|> Map.merge(parse_media_metadata(metadata))
|
|> Map.merge(parse_media_metadata(metadata))
|
||||||
|> Map.merge(parse_subtitle_metadata(metadata))
|
|> Map.merge(parse_subtitle_metadata(metadata))
|
||||||
|
|> Map.merge(parse_thumbnail_metadata(metadata))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp parse_media_metadata(metadata) do
|
defp parse_media_metadata(metadata) do
|
||||||
|
|
@ -35,10 +36,9 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MetadataParser do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp parse_subtitle_metadata(metadata) do
|
defp parse_subtitle_metadata(metadata) do
|
||||||
subtitle_map = metadata["requested_subtitles"] || %{}
|
|
||||||
# IDEA: if needed, consider filtering out subtitles that don't exist on-disk
|
# IDEA: if needed, consider filtering out subtitles that don't exist on-disk
|
||||||
subtitle_filepaths =
|
subtitle_filepaths =
|
||||||
subtitle_map
|
(metadata["requested_subtitles"] || %{})
|
||||||
|> Enum.map(fn {lang, attrs} -> [lang, attrs["filepath"]] end)
|
|> Enum.map(fn {lang, attrs} -> [lang, attrs["filepath"]] end)
|
||||||
|> Enum.sort(fn [lang_a, _], [lang_b, _] -> lang_a < lang_b end)
|
|> Enum.sort(fn [lang_a, _], [lang_b, _] -> lang_a < lang_b end)
|
||||||
|
|
||||||
|
|
@ -46,4 +46,18 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MetadataParser do
|
||||||
subtitle_filepaths: subtitle_filepaths
|
subtitle_filepaths: subtitle_filepaths
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp parse_thumbnail_metadata(metadata) do
|
||||||
|
thumbnail_filepath =
|
||||||
|
(metadata["thumbnails"] || %{})
|
||||||
|
# Reverse so that higher resolution thumbnails come first.
|
||||||
|
# This _shouldn't_ matter yet, but I'd rather default to the best
|
||||||
|
# in case I'm wrong.
|
||||||
|
|> Enum.reverse()
|
||||||
|
|> Enum.find_value(fn attrs -> attrs["filepath"] end)
|
||||||
|
|
||||||
|
%{
|
||||||
|
thumbnail_filepath: thumbnail_filepath
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ defmodule Pinchflat.Profiles.MediaProfile do
|
||||||
download_auto_subs
|
download_auto_subs
|
||||||
embed_subs
|
embed_subs
|
||||||
sub_langs
|
sub_langs
|
||||||
|
download_thumbnail
|
||||||
|
embed_thumbnail
|
||||||
)a
|
)a
|
||||||
|
|
||||||
@required_fields ~w(name output_path_template)a
|
@required_fields ~w(name output_path_template)a
|
||||||
|
|
@ -22,11 +24,15 @@ defmodule Pinchflat.Profiles.MediaProfile do
|
||||||
schema "media_profiles" do
|
schema "media_profiles" do
|
||||||
field :name, :string
|
field :name, :string
|
||||||
field :output_path_template, :string
|
field :output_path_template, :string
|
||||||
|
|
||||||
field :download_subs, :boolean, default: true
|
field :download_subs, :boolean, default: true
|
||||||
field :download_auto_subs, :boolean, default: true
|
field :download_auto_subs, :boolean, default: true
|
||||||
field :embed_subs, :boolean, default: true
|
field :embed_subs, :boolean, default: true
|
||||||
field :sub_langs, :string, default: "en"
|
field :sub_langs, :string, default: "en"
|
||||||
|
|
||||||
|
field :download_thumbnail, :boolean, default: true
|
||||||
|
field :embed_thumbnail, :boolean, default: true
|
||||||
|
|
||||||
has_many :sources, Source
|
has_many :sources, Source
|
||||||
|
|
||||||
timestamps(type: :utc_datetime)
|
timestamps(type: :utc_datetime)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ defmodule Pinchflat.Profiles.Options.YtDlp.OptionBuilder do
|
||||||
built_options =
|
built_options =
|
||||||
default_options() ++
|
default_options() ++
|
||||||
subtitle_options(media_profile) ++
|
subtitle_options(media_profile) ++
|
||||||
|
thumbnail_options(media_profile) ++
|
||||||
output_options(media_profile)
|
output_options(media_profile)
|
||||||
|
|
||||||
{:ok, built_options}
|
{:ok, built_options}
|
||||||
|
|
@ -33,7 +34,6 @@ defmodule Pinchflat.Profiles.Options.YtDlp.OptionBuilder do
|
||||||
defp default_options do
|
defp default_options do
|
||||||
[
|
[
|
||||||
:embed_metadata,
|
:embed_metadata,
|
||||||
:embed_thumbnail,
|
|
||||||
:no_progress
|
:no_progress
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
@ -65,6 +65,18 @@ defmodule Pinchflat.Profiles.Options.YtDlp.OptionBuilder do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp thumbnail_options(media_profile) do
|
||||||
|
mapped_struct = Map.from_struct(media_profile)
|
||||||
|
|
||||||
|
Enum.reduce(mapped_struct, [], fn attr, acc ->
|
||||||
|
case attr do
|
||||||
|
{:download_thumbnail, true} -> acc ++ [:write_thumbnail]
|
||||||
|
{:embed_thumbnail, true} -> acc ++ [:embed_thumbnail]
|
||||||
|
_ -> acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defp output_options(media_profile) do
|
defp output_options(media_profile) do
|
||||||
{:ok, output_path} = OutputPathBuilder.build(media_profile.output_path_template)
|
{:ok, output_path} = OutputPathBuilder.build(media_profile.output_path_template)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
defmodule Pinchflat.Repo.Migrations.AddThumbnailOptionsToMediaProfiles do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:media_profiles) do
|
||||||
|
add :download_thumbnail, :boolean, default: true, null: false
|
||||||
|
add :embed_thumbnail, :boolean, default: true, null: false
|
||||||
|
end
|
||||||
|
|
||||||
|
alter table(:media_items) do
|
||||||
|
add :thumbnail_filepath, :string
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -83,4 +83,28 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaParserTest do
|
||||||
assert result.subtitle_filepaths == []
|
assert result.subtitle_filepaths == []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "parse_for_media_item/1 when testing thumbnail metadata" do
|
||||||
|
test "extracts the thumbnail filepath", %{metadata: metadata} do
|
||||||
|
result = Parser.parse_for_media_item(metadata)
|
||||||
|
|
||||||
|
assert String.ends_with?(result.thumbnail_filepath, ".webp")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "doesn't freak out if the video has no thumbnails", %{metadata: metadata} do
|
||||||
|
metadata = Map.put(metadata, "thumbnails", %{})
|
||||||
|
|
||||||
|
result = Parser.parse_for_media_item(metadata)
|
||||||
|
|
||||||
|
assert result.thumbnail_filepath == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "doesn't freak out if the thumbnails key is missing", %{metadata: metadata} do
|
||||||
|
metadata = Map.delete(metadata, "thumbnails")
|
||||||
|
|
||||||
|
result = Parser.parse_for_media_item(metadata)
|
||||||
|
|
||||||
|
assert result.thumbnail_filepath == nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,18 @@ defmodule Pinchflat.MediaClient.VideoDownloaderTest do
|
||||||
{:ok, render_metadata(:media_metadata)}
|
{:ok, render_metadata(:media_metadata)}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
assert %{media_filepath: nil, title: nil, subtitle_filepaths: []} = media_item
|
assert %{
|
||||||
|
media_filepath: nil,
|
||||||
|
title: nil,
|
||||||
|
subtitle_filepaths: [],
|
||||||
|
thumbnail_filepath: nil
|
||||||
|
} = media_item
|
||||||
|
|
||||||
assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item)
|
assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item)
|
||||||
assert updated_media_item.media_filepath
|
assert updated_media_item.media_filepath
|
||||||
assert updated_media_item.title
|
assert updated_media_item.title
|
||||||
assert length(updated_media_item.subtitle_filepaths) > 0
|
assert length(updated_media_item.subtitle_filepaths) > 0
|
||||||
|
assert updated_media_item.thumbnail_filepath
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it saves the metadata to the database", %{media_item: media_item} do
|
test "it saves the metadata to the database", %{media_item: media_item} do
|
||||||
|
|
|
||||||
|
|
@ -94,4 +94,35 @@ defmodule Pinchflat.Profiles.Options.YtDlp.OptionBuilderTest do
|
||||||
refute {:id, -1} in res
|
refute {:id, -1} in res
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "build/1 when testing thumbnail options" do
|
||||||
|
test "includes :write_thumbnail option when specified" do
|
||||||
|
media_profile = %MediaProfile{@media_profile | download_thumbnail: true}
|
||||||
|
|
||||||
|
assert {:ok, res} = OptionBuilder.build(media_profile)
|
||||||
|
|
||||||
|
assert :write_thumbnail in res
|
||||||
|
end
|
||||||
|
|
||||||
|
test "includes :embed_thumbnail option when specified" do
|
||||||
|
media_profile = %MediaProfile{@media_profile | embed_thumbnail: true}
|
||||||
|
|
||||||
|
assert {:ok, res} = OptionBuilder.build(media_profile)
|
||||||
|
|
||||||
|
assert :embed_thumbnail in res
|
||||||
|
end
|
||||||
|
|
||||||
|
test "doesn't include these options when not specified" do
|
||||||
|
media_profile = %MediaProfile{
|
||||||
|
@media_profile
|
||||||
|
| embed_thumbnail: false,
|
||||||
|
download_thumbnail: false
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = OptionBuilder.build(media_profile)
|
||||||
|
|
||||||
|
refute :write_thumbnail in res
|
||||||
|
refute :embed_thumbnail in res
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1389,42 +1389,138 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"thumbnails": [
|
"thumbnails": [
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/3.jpg", "preference": -37, "id": "0" },
|
{
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/3.webp", "preference": -36, "id": "1" },
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/3.jpg",
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/2.jpg", "preference": -35, "id": "2" },
|
"preference": -37,
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/2.webp", "preference": -34, "id": "3" },
|
"id": "0"
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/1.jpg", "preference": -33, "id": "4" },
|
},
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/1.webp", "preference": -32, "id": "5" },
|
{
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mq3.jpg", "preference": -31, "id": "6" },
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/3.webp",
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mq3.webp", "preference": -30, "id": "7" },
|
"preference": -36,
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mq2.jpg", "preference": -29, "id": "8" },
|
"id": "1"
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mq2.webp", "preference": -28, "id": "9" },
|
},
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mq1.jpg", "preference": -27, "id": "10" },
|
{
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mq1.webp", "preference": -26, "id": "11" },
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/2.jpg",
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq3.jpg", "preference": -25, "id": "12" },
|
"preference": -35,
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq3.webp", "preference": -24, "id": "13" },
|
"id": "2"
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq2.jpg", "preference": -23, "id": "14" },
|
},
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq2.webp", "preference": -22, "id": "15" },
|
{
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq1.jpg", "preference": -21, "id": "16" },
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/2.webp",
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq1.webp", "preference": -20, "id": "17" },
|
"preference": -34,
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sd3.jpg", "preference": -19, "id": "18" },
|
"id": "3"
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sd3.webp", "preference": -18, "id": "19" },
|
},
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sd2.jpg", "preference": -17, "id": "20" },
|
{
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sd2.webp", "preference": -16, "id": "21" },
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/1.jpg",
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sd1.jpg", "preference": -15, "id": "22" },
|
"preference": -33,
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sd1.webp", "preference": -14, "id": "23" },
|
"id": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/1.webp",
|
||||||
|
"preference": -32,
|
||||||
|
"id": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mq3.jpg",
|
||||||
|
"preference": -31,
|
||||||
|
"id": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mq3.webp",
|
||||||
|
"preference": -30,
|
||||||
|
"id": "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mq2.jpg",
|
||||||
|
"preference": -29,
|
||||||
|
"id": "8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mq2.webp",
|
||||||
|
"preference": -28,
|
||||||
|
"id": "9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mq1.jpg",
|
||||||
|
"preference": -27,
|
||||||
|
"id": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mq1.webp",
|
||||||
|
"preference": -26,
|
||||||
|
"id": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq3.jpg",
|
||||||
|
"preference": -25,
|
||||||
|
"id": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq3.webp",
|
||||||
|
"preference": -24,
|
||||||
|
"id": "13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq2.jpg",
|
||||||
|
"preference": -23,
|
||||||
|
"id": "14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq2.webp",
|
||||||
|
"preference": -22,
|
||||||
|
"id": "15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq1.jpg",
|
||||||
|
"preference": -21,
|
||||||
|
"id": "16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq1.webp",
|
||||||
|
"preference": -20,
|
||||||
|
"id": "17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sd3.jpg",
|
||||||
|
"preference": -19,
|
||||||
|
"id": "18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sd3.webp",
|
||||||
|
"preference": -18,
|
||||||
|
"id": "19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sd2.jpg",
|
||||||
|
"preference": -17,
|
||||||
|
"id": "20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sd2.webp",
|
||||||
|
"preference": -16,
|
||||||
|
"id": "21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sd1.jpg",
|
||||||
|
"preference": -15,
|
||||||
|
"id": "22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sd1.webp",
|
||||||
|
"preference": -14,
|
||||||
|
"id": "23"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/default.jpg",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/default.jpg",
|
||||||
"height": 90,
|
|
||||||
"width": 120,
|
|
||||||
"preference": -13,
|
"preference": -13,
|
||||||
"id": "24",
|
"id": "24"
|
||||||
"resolution": "120x90"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/default.webp",
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/default.webp",
|
||||||
|
"height": 90,
|
||||||
|
"width": 120,
|
||||||
"preference": -12,
|
"preference": -12,
|
||||||
"id": "25"
|
"id": "25",
|
||||||
|
"resolution": "120x90"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mqdefault.jpg",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/mqdefault.jpg",
|
||||||
|
|
@ -1436,13 +1532,24 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mqdefault.webp",
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/mqdefault.webp",
|
||||||
|
"height": 180,
|
||||||
|
"width": 320,
|
||||||
"preference": -10,
|
"preference": -10,
|
||||||
"id": "27"
|
"id": "27",
|
||||||
|
"resolution": "320x180"
|
||||||
},
|
},
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/0.jpg", "preference": -9, "id": "28" },
|
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/0.webp", "preference": -8, "id": "29" },
|
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCfnqZqzf3SpMWSBlr5eEkYrRbeOw",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/0.jpg",
|
||||||
|
"preference": -9,
|
||||||
|
"id": "28"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/0.webp",
|
||||||
|
"preference": -8,
|
||||||
|
"id": "29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDmfPp_bFp43fLeDiG7JmFAldoFLA",
|
||||||
"height": 94,
|
"height": 94,
|
||||||
"width": 168,
|
"width": 168,
|
||||||
"preference": -7,
|
"preference": -7,
|
||||||
|
|
@ -1450,7 +1557,7 @@
|
||||||
"resolution": "168x94"
|
"resolution": "168x94"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAnj5wtnbYGzZX9gerMKQ-FS5sSeA",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCGAiCuOy3Tmz9U9iGo3YF5dM57bQ",
|
||||||
"height": 110,
|
"height": 110,
|
||||||
"width": 196,
|
"width": 196,
|
||||||
"preference": -7,
|
"preference": -7,
|
||||||
|
|
@ -1458,7 +1565,7 @@
|
||||||
"resolution": "196x110"
|
"resolution": "196x110"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLC5fmbFoduOVcifLAMu006pXlcicQ",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDcSQOIb-t1Aug8y0A-_M2jNehcRw",
|
||||||
"height": 138,
|
"height": 138,
|
||||||
"width": 246,
|
"width": 246,
|
||||||
"preference": -7,
|
"preference": -7,
|
||||||
|
|
@ -1466,7 +1573,7 @@
|
||||||
"resolution": "246x138"
|
"resolution": "246x138"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDISoJqnSXFGgqsSCMRd9NCiV5Dyg",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAT65DjLaxTpghDUrIAQEclNUUJog",
|
||||||
"height": 188,
|
"height": 188,
|
||||||
"width": 336,
|
"width": 336,
|
||||||
"preference": -7,
|
"preference": -7,
|
||||||
|
|
@ -1483,8 +1590,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hqdefault.webp",
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hqdefault.webp",
|
||||||
|
"height": 360,
|
||||||
|
"width": 480,
|
||||||
"preference": -6,
|
"preference": -6,
|
||||||
"id": "35"
|
"id": "35",
|
||||||
|
"resolution": "480x360"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sddefault.jpg",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/sddefault.jpg",
|
||||||
|
|
@ -1496,23 +1606,37 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sddefault.webp",
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/sddefault.webp",
|
||||||
|
"height": 480,
|
||||||
|
"width": 640,
|
||||||
"preference": -4,
|
"preference": -4,
|
||||||
"id": "37"
|
"id": "37",
|
||||||
|
"resolution": "640x480"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq720.jpg",
|
||||||
|
"preference": -3,
|
||||||
|
"id": "38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq720.webp",
|
||||||
|
"preference": -2,
|
||||||
|
"id": "39"
|
||||||
},
|
},
|
||||||
{ "url": "https://i.ytimg.com/vi/bwRHIkYqYJo/hq720.jpg", "preference": -3, "id": "38" },
|
|
||||||
{ "url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/hq720.webp", "preference": -2, "id": "39" },
|
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/maxresdefault.jpg",
|
"url": "https://i.ytimg.com/vi/bwRHIkYqYJo/maxresdefault.jpg",
|
||||||
"height": 1080,
|
"height": 720,
|
||||||
"width": 1920,
|
"width": 1280,
|
||||||
"preference": -1,
|
"preference": -1,
|
||||||
"id": "40",
|
"id": "40",
|
||||||
"resolution": "1920x1080"
|
"resolution": "1280x720"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/maxresdefault.webp",
|
"url": "https://i.ytimg.com/vi_webp/bwRHIkYqYJo/maxresdefault.webp",
|
||||||
|
"height": 1080,
|
||||||
|
"width": 1920,
|
||||||
"preference": 0,
|
"preference": 0,
|
||||||
"id": "41",
|
"id": "41",
|
||||||
|
"resolution": "1920x1080",
|
||||||
"filepath": "/app/tmp/videos/bwRHIkYqYJo/Trying to Wheelie Without the Rear Brake-bwRHIkYqYJo.webp"
|
"filepath": "/app/tmp/videos/bwRHIkYqYJo/Trying to Wheelie Without the Rear Brake-bwRHIkYqYJo.webp"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue