mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-07 00:12:16 +02:00
Enhanced Metadata Resolution, Stream Analysis & Improved STRM-Output. Added connection priority management.
**Description:**
This PR introduces a major overhaul of how streams are analyzed and connections are managed. It integrates `ffprobe` for deep stream analysis, adds a background task queue for metadata resolution to prevent UI blocking, introduces a connection priority system, and adds support for Live TV probing.
### 🚀 Key Features
* **FFprobe Integration & Live TV Probing**:
* Automatically probes streams (VOD/Series **and now Live TV**) to determine resolution, codecs (HEVC/AV1), dynamic range (HDR/DV), bit depth, and audio channels.
* **Safe Probing**: Probing strictly respects the provider's `max_connections` limit.
* Docker images now include static `ffmpeg/ffprobe` binaries.
* **Smart Connection Management (Priority System)**:
* Introduced a priority system for connections to manage provider limits intelligently.
* **Preemption**: Users with higher priority can preempt (kick) lower priority connections when provider slots are full.
* **Background Queue**: Metadata resolution and stream analysis run as background tasks (Priority 0). They only run when connection slots are idle and yield immediately if a real user needs to stream.
* **Enhanced Metadata Resolution**:
* **Fallback Logic**: If a provider is missing the TMDB ID or Release Date, the system resolves them via the TMDB API.
* **Smart Title Cleaning**: Implemented a centralized cleaner to strip common IPTV prefixes before attempting metadata matches or generating filenames, significantly improving match rates.
* **Improved Output**:
* **Quality Tags**: Filenames in STRM files now include detailed tags (e.g., `Movie - [4K HEVC HDR].strm`).
* **Flat Grouping**: `flat: true` now correctly groups multi-version movies into single folders based on TMDB ID.
* **Global Series Date**: Ensures consistent series folder naming even if episodes have different years.
This commit is contained in:
@@ -1,29 +1,76 @@
|
||||
pub mod playlist;
|
||||
mod playlist;
|
||||
mod xtream;
|
||||
// mod affix;
|
||||
mod xtream_vod;
|
||||
mod xtream_series;
|
||||
pub mod epg;
|
||||
mod epg;
|
||||
mod sort;
|
||||
pub mod trakt;
|
||||
mod trakt;
|
||||
mod library;
|
||||
mod stream_probe;
|
||||
pub use self::playlist::*;
|
||||
pub use self::epg::*;
|
||||
pub use self::xtream::*;
|
||||
pub use self::xtream_vod::*;
|
||||
pub use self::xtream_series::*;
|
||||
pub use self::stream_probe::*;
|
||||
use shared::create_bit_set;
|
||||
|
||||
create_bit_set!(u16, ResolveOptionsFlags, Resolve, TmdbMissing, Probe, Background);
|
||||
|
||||
pub struct ResolveOptions {
|
||||
pub flags: ResolveOptionsFlagsSet,
|
||||
pub resolve_delay: u16,
|
||||
}
|
||||
|
||||
impl Default for ResolveOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
flags: ResolveOptionsFlagsSet::from_variants(&[ResolveOptionsFlags::Background]),
|
||||
resolve_delay: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// fn get_resolve_<cluster>_options(target: &ConfigTarget, fpl: &FetchedPlaylist) -> (bool, u16)
|
||||
// fn get_resolve_<cluster>_options(target: &ConfigTarget, fpl: &FetchedPlaylist) -> bool
|
||||
//
|
||||
#[macro_export]
|
||||
macro_rules! create_resolve_options_function_for_xtream_target {
|
||||
($cluster:ident) => {
|
||||
paste::paste! {
|
||||
fn [<get_resolve_ $cluster _options>](target: &ConfigTarget, fpl: &FetchedPlaylist) -> (bool, u16) {
|
||||
fn [<get_resolve_ $cluster _options>](target: &ConfigTarget, fpl: &FetchedPlaylist) -> $crate::processing::processor::ResolveOptions {
|
||||
// Get input options
|
||||
let (resolve_tmdb_missing, probe_requested) = fpl.input.options.as_ref().map_or_else(||(false, false), |o| (o.resolve_tmdb, o.probe_stream));
|
||||
match target.get_xtream_output() {
|
||||
Some(xtream_output) => (xtream_output.[<resolve_ $cluster>] && fpl.input.input_type == InputType::Xtream,
|
||||
xtream_output.[<resolve_ $cluster _delay>]),
|
||||
None => (false, 0)
|
||||
Some(xtream_output) => {
|
||||
let mut flags = $crate::processing::processor::ResolveOptionsFlagsSet::new();
|
||||
// Map config flags to resolve options flags
|
||||
if xtream_output.flags.contains($crate::model::XtreamTargetFlags::[<Resolve $cluster:camel>]) && fpl.input.input_type.is_xtream() {
|
||||
flags.add($crate::processing::processor::ResolveOptionsFlags::Resolve);
|
||||
}
|
||||
if resolve_tmdb_missing {
|
||||
flags.add($crate::processing::processor::ResolveOptionsFlags::TmdbMissing);
|
||||
}
|
||||
if probe_requested
|
||||
&& fpl.input.input_type.is_xtream()
|
||||
&& xtream_output.flags.contains($crate::model::XtreamTargetFlags::[<Probe $cluster:camel>]) {
|
||||
flags.add($crate::processing::processor::ResolveOptionsFlags::Probe);
|
||||
}
|
||||
if xtream_output.flags.contains($crate::model::XtreamTargetFlags::ResolveBackground) {
|
||||
flags.add($crate::processing::processor::ResolveOptionsFlags::Background);
|
||||
}
|
||||
|
||||
$crate::processing::processor::ResolveOptions {
|
||||
flags,
|
||||
resolve_delay: xtream_output.resolve_delay,
|
||||
}
|
||||
},
|
||||
None => $crate::processing::processor::ResolveOptions::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
use create_resolve_options_function_for_xtream_target;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user