83 lines
4.2 KiB
Rust
83 lines
4.2 KiB
Rust
//! Constants for `youtube-feeder`.
|
|
|
|
/// User-Agent for outbound HTTP.
|
|
///
|
|
/// ⚠ **Not cosmetic.** Several upstreams reject a generic or absent
|
|
/// User-Agent, and a 403 there looks exactly like a rate-limit — easy to
|
|
/// misdiagnose. Identify the application and carry contact information.
|
|
pub const USER_AGENT: &str = concat!(
|
|
"youtube-feeder/",
|
|
env!("CARGO_PKG_VERSION"),
|
|
" ( https://github.com/worph/meta-feeder-youtube )"
|
|
);
|
|
|
|
/// Piped instances, tried in order, rotating past a dead one.
|
|
///
|
|
/// **A pool, not a hostname — measured.** Of four instances tried during the
|
|
/// study, one returned `502`, two `301`-redirected away, and one answered in
|
|
/// ~1 s. That is the failure profile to design for. It is cheap to survive
|
|
/// because we take only the 11-character video id: a dead instance is a retry,
|
|
/// not a broken stream (contrast the *bytes* argument against Piped in
|
|
/// `youtube-source-integration-study.md` §2.2, which does not apply here).
|
|
pub const PIPED_INSTANCES: &[&str] = &[
|
|
"https://api.piped.private.coffee",
|
|
"https://pipedapi.kavin.rocks",
|
|
"https://pipedapi.adminforge.de",
|
|
"https://api.piped.yt",
|
|
];
|
|
/// Per-request timeout against a Piped instance.
|
|
pub const PIPED_TIMEOUT_SECS: u64 = 15;
|
|
/// Artwork for a YouTube rendition. `hqdefault` exists for every video, unlike
|
|
/// `maxresdefault`, which 404s on anything not uploaded in HD — and a 404 here
|
|
/// is **silent**, gating the record out with no error anywhere.
|
|
pub const YT_THUMB_BASE: &str = "https://i.ytimg.com/vi";
|
|
/// How far a candidate's runtime may sit from the MusicBrainz recording length
|
|
/// and still be the same recording.
|
|
///
|
|
/// ±10 s is what the study measured at, and it is doing two jobs: absorbing
|
|
/// fade-in/out and pre-gap differences between a CD master and an uploaded
|
|
/// Art Track, while staying tight enough to separate a radio edit (249 s) from
|
|
/// an album cut (370 s).
|
|
pub const YT_DURATION_TOLERANCE_SECS: i64 = 10;
|
|
/// Ceiling on Piped `music_songs` candidates examined per track.
|
|
pub const YT_CANDIDATES_PER_TRACK: usize = 8;
|
|
/// How many ranked YouTube references one recording may carry.
|
|
///
|
|
/// §3's mitigation for reference rot: the video **id** is immutable, but its
|
|
/// *availability* is not — takedowns, geo-blocks and embed-disabled uploads all
|
|
/// kill a reference whose CID stays valid forever. One reference per recording
|
|
/// means a takedown kills the track; several let the client fall through.
|
|
///
|
|
/// Three rather than "all of them" because each is a record replicated across
|
|
/// the mesh, and the tail past three is candidates the resolver already ranked
|
|
/// as worse matches.
|
|
pub const MAX_REFS_PER_RECORDING: usize = 3;
|
|
|
|
// MusicBrainz's published rate ceiling, from the crate that owns that client.
|
|
pub use musicbrainz_feeder::consts::{MB_BURST, MB_RATE_PER_SEC, MB_TIMEOUT_SECS};
|
|
|
|
/// Ceiling on raw free-text video hits emitted for one query.
|
|
///
|
|
/// The music paths thin their results with a *verification* — channel identity
|
|
/// plus duration — and refuse everything that fails it. The raw tier has no
|
|
/// such filter by construction, so the only bound available is a count. 20 is a
|
|
/// search page's worth: enough for the section to be useful, few enough that
|
|
/// one query does not pull a hundred thumbnails into the gateway's blockstore
|
|
/// (`poster_url` is fetched **and seeded** by the core, unlike a `cover`
|
|
/// locator, which stays lazy).
|
|
pub const YT_VIDEO_SEARCH_MAX: usize = 20;
|
|
|
|
/// Left half of a raw video tier record id (`yt~<videoId>`).
|
|
///
|
|
/// The music tier keys a record on `<mbRecordingId>~<videoId>` because the same
|
|
/// video can legitimately be the reference for more than one recording. The raw
|
|
/// tier has no such second axis — a video is itself and nothing else — so the
|
|
/// left half is a constant, which makes the id a pure function of the video id
|
|
/// and lets the gateway dedupe the same hit across different search terms.
|
|
///
|
|
/// ⚠ It must stay parseable by [`crate::youtube::split_track_record_id`]: the
|
|
/// `~` split is what keeps `compute_outcomes` a zero-I/O pure function for both
|
|
/// tiers. A left half that could collide with a MusicBrainz id would be a bug;
|
|
/// `yt` cannot, since MBIDs are UUIDs.
|
|
pub const VIDEO_RECORD_NS: &str = "yt";
|