{"record":{"id":"b1478a44f403a073","repo":"tonhowtf/omniget","slug":"cole-a-url-de-um-m3u8-ou-mpd","errorCode":null,"errorMessage":"cole a URL de um .m3u8 ou .mpd","messagePattern":"cole a URL de um \\.m3u8 ou \\.mpd","errorType":"validation","errorClass":"anyhow","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/manifest_dl.rs","lineNumber":62,"sourceCode":"            h.push(e.trim().to_string());\n        }\n    }\n    if h.is_empty() {\n        None\n    } else {\n        Some(h.join(\"\\r\\n\") + \"\\r\\n\")\n    }\n}\n\npub async fn download(\n    opts: ManifestOptions,\n    progress: super::ProgressFn,\n) -> anyhow::Result<ManifestResult> {\n    use tokio::io::{AsyncBufReadExt, BufReader};\n    let ffmpeg = crate::core::dependencies::ensure_ffmpeg().await?;\n    let url = opts.url.trim().to_string();\n    if !(url.contains(\".m3u8\") || url.contains(\".mpd\") || url.starts_with(\"http\")) {\n        return Err(anyhow!(\"cole a URL de um .m3u8 ou .mpd\"));\n    }\n    std::fs::create_dir_all(&opts.dest_dir)?;\n    let mut name = super::sanitize_name(opts.file_name.trim());\n    if !name.to_lowercase().ends_with(\".mp4\") && !name.to_lowercase().ends_with(\".mkv\") {\n        name.push_str(\".mp4\");\n    }\n    let out = PathBuf::from(&opts.dest_dir).join(name);\n    let mut cmd = crate::core::process::command(&ffmpeg);\n    cmd.args([\n        \"-y\",\n        \"-hide_banner\",\n        \"-loglevel\",\n        \"error\",\n        \"-nostats\",\n        \"-progress\",\n        \"pipe:1\",\n    ]);\n    if !opts.user_agent.trim().is_empty() {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/manifest_dl.rs#L44-L80","documentation":"manifest_dl::download validates that the provided URL looks like an HLS (.m3u8) or DASH (.mpd) manifest before invoking ffmpeg. The check requires the URL to contain '.m3u8' or '.mpd' OR start with 'http'; anything else is rejected as invalid input.","triggerScenarios":"Calling download with opts.url empty, a bare filename, a local path, or an http(s) URL lacking .m3u8/.mpd — note the logic: any URL starting with 'http' passes even without an extension, so the error fires mainly for non-http inputs or empty strings.","commonSituations":"User pasted a webpage URL instead of the manifest URL (e.g. a player page); frontend passed an empty string; user pasted a blob: or file: URL; copied a base-only stream link without the manifest path.","solutions":["Paste the direct .m3u8 or .mpd manifest URL (from the network tab of devtools), not the page URL","Ensure opts.url starts with http(s) and points at the manifest, not an HTML page","Trim whitespace/control characters from the pasted URL before calling","If the manifest is behind an auth flow, copy the exact manifest request URL from the browser network panel"],"exampleFix":"// before\nlet opts = ManifestOptions { url: \"https://example.com/player/watch/123\".into(), .. };\n// after\nlet opts = ManifestOptions { url: \"https://example.com/hls/stream/index.m3u8\".into(), .. };","handlingStrategy":"validation","validationCode":"let url = opts.url.trim();\nif !(url.starts_with(\"http\") && (url.contains(\".m3u8\") || url.contains(\".mpd\"))) {\n    return Err(\"URL must be a direct .m3u8 or .mpd manifest\");\n}","typeGuard":"fn is_manifest_url(u: &str) -> bool {\n    let u = u.trim();\n    u.starts_with(\"http\") && (u.contains(\".m3u8\") || u.contains(\".mpd\"))\n}","tryCatchPattern":"if !is_manifest_url(&opts.url) {\n    // ask user for the direct manifest URL (devtools -> network -> .m3u8/.mpd)\n    return;\n}\ndownload(&opts, &progress).await?;","preventionTips":["Copy the manifest URL from the browser network tab, not the page URL","Trim pasted URLs to remove whitespace/control characters","For DASH, ensure the MPD is not DRM-protected before attempting"],"tags":["validation","url","manifest","hls","dash"],"backgroundTag":"invalid-url","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}