Add YT_DLP_VERSION env var for version management

Allows configuring yt-dlp update behavior via environment variable:
- "stable" (default): updates to latest stable release daily
- "nightly": updates to latest nightly build daily
- "master": updates to latest master build daily
- "pinned" or "none": disables automatic updates
- Specific version (e.g. "2025.12.08"): pins to that version
This commit is contained in:
Daniel Da Cunha 2025-12-15 13:24:05 +08:00
parent 67d8bd5598
commit 23381ed8d9
5 changed files with 56 additions and 6 deletions

View file

@ -177,6 +177,7 @@ If you change this setting and it works well for you, please leave a comment on
| `TZ_DATA_DIR` | No | `/etc/elixir_tzdata_data` | The container path where the timezone database is stored |
| `BASE_ROUTE_PATH` | No | `/` | The base path for route generation. Useful when running behind certain reverse proxies - prefixes must be stripped. |
| `YT_DLP_WORKER_CONCURRENCY` | No | `2` | The number of concurrent workers that use `yt-dlp` _per queue_. Set to 1 if you're getting IP limited, otherwise don't touch it |
| `YT_DLP_VERSION` | No | `stable` | Controls yt-dlp updates: `stable`, `nightly`, `master`, `pinned`/`none` (disable), or a specific version like `2025.12.08` |
| `ENABLE_PROMETHEUS` | No | `false` | Setting to _any_ non-blank value will enable Prometheus. See [docs](https://github.com/kieraneglin/pinchflat/wiki/Prometheus-and-Grafana) |
### Reverse Proxies

View file

@ -43,6 +43,18 @@ config :pinchflat, Pinchflat.Repo,
# Some users may want to increase the number of workers that use yt-dlp to improve speeds
# Others may want to decrease the number of these workers to lessen the chance of an IP ban
{yt_dlp_worker_count, _} = Integer.parse(System.get_env("YT_DLP_WORKER_CONCURRENCY", "2"))
# Controls yt-dlp version management. Supported values:
# - "stable" (default) - updates to latest stable release daily
# - "nightly" - updates to latest nightly build daily
# - "master" - updates to latest master build daily
# - "pinned" or "none" - disables automatic updates entirely
# - A specific version like "2025.12.08" - pins to that exact version
yt_dlp_version_channel = System.get_env("YT_DLP_VERSION", "stable")
config :pinchflat,
yt_dlp_version_channel: yt_dlp_version_channel
# Used to set the cron for the yt-dlp update worker. The reason for this is
# to avoid all instances of PF updating yt-dlp at the same time, which 1)
# could result in rate limiting and 2) gives me time to react if an update

View file

@ -77,15 +77,22 @@ defmodule Pinchflat.YtDlp.CommandRunner do
end
@doc """
Updates yt-dlp to the latest version
Updates yt-dlp to the specified version channel or specific version.
The version_target can be:
- "stable" - updates to latest stable release (default)
- "nightly" - updates to latest nightly build
- "master" - updates to latest master build
- A specific version like "2025.12.08" - pins to that exact version
Returns {:ok, binary()} | {:error, binary()}
"""
@impl YtDlpCommandRunner
def update do
def update(version_target \\ "stable") do
command = backend_executable()
args = build_update_args(version_target)
case CliUtils.wrap_cmd(command, ["--update"]) do
case CliUtils.wrap_cmd(command, args) do
{output, 0} ->
{:ok, String.trim(output)}
@ -94,6 +101,11 @@ defmodule Pinchflat.YtDlp.CommandRunner do
end
end
defp build_update_args("stable"), do: ["--update"]
defp build_update_args("nightly"), do: ["--update-to", "nightly"]
defp build_update_args("master"), do: ["--update-to", "master"]
defp build_update_args(specific_version), do: ["--update-to", "yt-dlp/yt-dlp@#{specific_version}"]
defp generate_output_filepath(addl_opts) do
case Keyword.get(addl_opts, :output_filepath) do
nil -> FSUtils.generate_metadata_tmpfile(:json)

View file

@ -1,5 +1,14 @@
defmodule Pinchflat.YtDlp.UpdateWorker do
@moduledoc false
@moduledoc """
Handles automatic yt-dlp updates based on the YT_DLP_VERSION environment variable.
Supported values for YT_DLP_VERSION:
- "stable" (default) - updates to latest stable release daily
- "nightly" - updates to latest nightly build daily
- "master" - updates to latest master build daily
- "pinned" or "none" - disables automatic updates entirely
- A specific version like "2025.12.08" - pins to that exact version
"""
use Oban.Worker,
queue: :local_data,
@ -23,14 +32,22 @@ defmodule Pinchflat.YtDlp.UpdateWorker do
Updates yt-dlp and saves the version to the settings.
This worker is scheduled to run via the Oban Cron plugin as well as on app boot.
The update behavior is controlled by the YT_DLP_VERSION environment variable.
Returns :ok
"""
@impl Oban.Worker
def perform(%Oban.Job{}) do
Logger.info("Updating yt-dlp")
version_setting = get_version_setting()
yt_dlp_runner().update()
case version_setting do
setting when setting in ["pinned", "none"] ->
Logger.info("yt-dlp auto-update disabled (YT_DLP_VERSION=#{setting})")
version_target ->
Logger.info("Updating yt-dlp to #{version_target}")
yt_dlp_runner().update(version_target)
end
{:ok, yt_dlp_version} = yt_dlp_runner().version()
Settings.set(yt_dlp_version: yt_dlp_version)
@ -38,6 +55,13 @@ defmodule Pinchflat.YtDlp.UpdateWorker do
:ok
end
@doc """
Returns the configured yt-dlp version setting from environment.
"""
def get_version_setting do
Application.get_env(:pinchflat, :yt_dlp_version_channel, "stable")
end
defp yt_dlp_runner do
Application.get_env(:pinchflat, :yt_dlp_runner)
end

View file

@ -10,4 +10,5 @@ defmodule Pinchflat.YtDlp.YtDlpCommandRunner do
@callback run(binary(), atom(), keyword(), binary(), keyword()) :: {:ok, binary()} | {:error, binary(), integer()}
@callback version() :: {:ok, binary()} | {:error, binary()}
@callback update() :: {:ok, binary()} | {:error, binary()}
@callback update(binary()) :: {:ok, binary()} | {:error, binary()}
end