diff --git a/Cargo.lock b/Cargo.lock index 1002308b..7f70197c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -533,7 +533,7 @@ dependencies = [ "rustc-hash 1.1.0", "shlex", "syn 2.0.87", - "which", + "which 4.4.2", ] [[package]] @@ -2014,7 +2014,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f364860e764787163c8c8f58231003839be31276e821e2ad2092ddf496b1aa09" dependencies = [ "tempfile", - "which", + "which 4.4.2", ] [[package]] @@ -4813,6 +4813,7 @@ dependencies = [ "tracing", "uuid", "vergen-gix", + "which 7.0.0", ] [[package]] @@ -7848,6 +7849,19 @@ dependencies = [ "rustix", ] +[[package]] +name = "which" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" +dependencies = [ + "either", + "home", + "rustix", + "tracing", + "winsafe", +] + [[package]] name = "whoami" version = "1.5.2" @@ -8443,6 +8457,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "write16" version = "1.0.0" diff --git a/libplatune/player/src/resolver/yt_dlp.rs b/libplatune/player/src/resolver/yt_dlp.rs index 4b20a1c6..ba5ca9fa 100644 --- a/libplatune/player/src/resolver/yt_dlp.rs +++ b/libplatune/player/src/resolver/yt_dlp.rs @@ -1,5 +1,6 @@ use std::cmp::Ordering; use std::collections::HashSet; +use std::env; use std::num::NonZeroUsize; use std::time::Duration; @@ -16,7 +17,7 @@ use stream_download::storage::temp::TempStorageProvider; use stream_download::{Settings, StreamDownload}; use tap::TapFallible; use tokio_util::sync::CancellationToken; -use tracing::{error, info}; +use tracing::{error, info, warn}; use youtube_dl::{YoutubeDl, YoutubeDlOutput}; macro_rules! url_regex { @@ -42,6 +43,12 @@ fn ytdl_rules() -> Vec { ] } +fn ytdl_exe() -> String { + let path = env::var("YT_DLP_PATH").unwrap_or_else(|_| "yt-dlp".to_string()); + info!("Using yt-dlp path: {path:?}"); + path +} + pub(crate) struct YtDlpUrlResolver { rules: Vec, skip_flat_playlist: HashSet<&'static str>, @@ -50,6 +57,8 @@ pub(crate) struct YtDlpUrlResolver { impl YtDlpUrlResolver { pub(crate) fn new() -> Self { let mut skip = HashSet::new(); + // some sites don't populate urls when using --flat-playlist so we need to explicitly skip + // it skip.insert("audius.co"); Self { rules: ytdl_rules(), @@ -74,6 +83,7 @@ impl RegistryEntry>> for YtDlpUrlResolver { .skip_flat_playlist .contains(input.source.clone().into_url().domain().unwrap_or_default()); let mut command = YoutubeDl::new(input.source.clone()); + command.youtube_dl_path(ytdl_exe()); if flat_playlist { // --flat-playlist prevents it from enumerating all videos in the playlist, which could // take a long time @@ -149,9 +159,6 @@ impl RegistryEntry, CancellationToken)>> for YtDlpSource info!("extracting video metadata - this may take a few seconds"); let output = YoutubeDl::new(input.source.clone()) .extract_audio(true) - // --flat-playlist prevents it from enumerating all videos in the playlist, which could - // take a long time - .extra_arg("--flat-playlist") .run_async() .await?; info!("metadata extraction complete"); @@ -179,11 +186,14 @@ impl RegistryEntry, CancellationToken)>> for YtDlpSource valid_formats.pop() } YoutubeDlOutput::Playlist(playlist) => { - info!("found playlist: {:?}", playlist.title); + // This shouldn't happen since we're enumerating playlists in the URL resolver + warn!("found playlist in source resolver: {:?}", playlist.title); None } }; - let cmd = YtDlpCommand::new(input.source).extract_audio(true); + let cmd = YtDlpCommand::new(input.source) + .yt_dlp_path(ytdl_exe()) + .extract_audio(true); let params = if let Some(format) = &found_format { info!("source quality: {:?}", format.quality); diff --git a/platuned/server/Cargo.toml b/platuned/server/Cargo.toml index 9c9d25a3..d6f7eada 100644 --- a/platuned/server/Cargo.toml +++ b/platuned/server/Cargo.toml @@ -43,6 +43,7 @@ tracing = "0.1.40" uuid = { version = "1.11.0", features = ["v4"] } vergen-gix = { version = "1.0.2" } console = "0.15.8" +which = { version = "7.0.0", features = ["tracing"] } [features] default = ["management", "player"] diff --git a/platuned/server/src/bin/platunectl.rs b/platuned/server/src/bin/platunectl.rs index dd8e2098..b3d8ef85 100644 --- a/platuned/server/src/bin/platunectl.rs +++ b/platuned/server/src/bin/platunectl.rs @@ -19,6 +19,7 @@ use daemon_slayer::logging::cli::LoggingCliProvider; use daemon_slayer::logging::tracing_subscriber::util::SubscriberInitExt; use daemon_slayer::process::cli::ProcessCliProvider; use platuned::{build_info, clap_base_command, main_server_port, service_label}; +use which::which; #[tokio::main] async fn main() -> Result<(), ErrorSink> { @@ -66,6 +67,10 @@ async fn run() -> Result<(), BoxedError> { .with_environment_variable_if_exists("PLATUNE_MTLS_CLIENT_CERT_PATH") .with_environment_variable_if_exists("PLATUNE_MTLS_CLIENT_KEY_PATH"); } + if let Ok(yt_dlp) = which("yt-dlp") { + manager_builder = + manager_builder.with_environment_variable("YT_DLP_PATH", yt_dlp.to_string_lossy()); + } let manager = manager_builder.build().await.unwrap(); let logger_builder = LoggerBuilder::new(label.clone());