Last active
January 9, 2026 21:17
-
-
Save shalakolee/8618eb479b5b01d89f18aab286acde20 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (async () => { | |
| const match = window.location.pathname.match(/video\/([a-zA-Z0-9]+)/); | |
| if (!match) { | |
| console.log("Video ID not found in URL."); | |
| return; | |
| } | |
| const videoId = match[1]; | |
| const metaUrl = `https://www.dailymotion.com/player/metadata/video/${videoId}?embedder=${location.hostname}`; | |
| const absolutize = (base, relative) => { | |
| try { return new URL(relative, base).toString(); } catch { return relative; } | |
| }; | |
| try { | |
| const metaRes = await fetch(metaUrl); | |
| const data = await metaRes.json(); | |
| if (!data?.qualities) { | |
| console.log("No qualities object found in metadata."); | |
| return; | |
| } | |
| // 1) Print whatever qualities are directly listed in metadata (sometimes MP4/progressive appear here) | |
| console.log("=== Metadata qualities (direct) ==="); | |
| for (const q of Object.keys(data.qualities)) { | |
| const arr = data.qualities[q]; | |
| if (!Array.isArray(arr)) continue; | |
| arr.forEach((s, i) => { | |
| if (s?.url) console.log(`${q}[${i}]: ${s.url}`); | |
| }); | |
| } | |
| // 2) If only "auto" exists, it's usually a master HLS playlist containing all variants. | |
| const masterUrl = data?.qualities?.auto?.[0]?.url; | |
| if (!masterUrl) { | |
| console.log("No auto/master m3u8 found at data.qualities.auto[0].url"); | |
| return; | |
| } | |
| console.log("\n=== Parsing HLS master playlist (auto) for variants ==="); | |
| console.log("Master m3u8:", masterUrl); | |
| const m3u8Res = await fetch(masterUrl); | |
| const m3u8Text = await m3u8Res.text(); | |
| // Parse #EXT-X-STREAM-INF blocks | |
| // Format: | |
| // #EXT-X-STREAM-INF:BANDWIDTH=...,RESOLUTION=WxH,CODECS="..." | |
| // <variant-playlist-url> | |
| const lines = m3u8Text.split("\n").map(l => l.trim()).filter(Boolean); | |
| const variants = []; | |
| for (let i = 0; i < lines.length; i++) { | |
| const line = lines[i]; | |
| if (line.startsWith("#EXT-X-STREAM-INF:")) { | |
| const attrs = line.substring("#EXT-X-STREAM-INF:".length); | |
| const bw = (attrs.match(/BANDWIDTH=(\d+)/) || [])[1] || ""; | |
| const res = (attrs.match(/RESOLUTION=(\d+x\d+)/) || [])[1] || ""; | |
| const codecs = (attrs.match(/CODECS="([^"]+)"/) || [])[1] || ""; | |
| const next = lines[i + 1]; // usually the URL line | |
| if (next && !next.startsWith("#")) { | |
| variants.push({ | |
| bandwidth: bw, | |
| resolution: res, | |
| codecs, | |
| url: absolutize(masterUrl, next), | |
| }); | |
| } | |
| } | |
| } | |
| if (!variants.length) { | |
| console.log("No variant streams found in master playlist. (It may be a single-level playlist.)"); | |
| return; | |
| } | |
| // Sort: highest resolution (height) first, fallback to bandwidth | |
| variants.sort((a, b) => { | |
| const ah = a.resolution ? parseInt(a.resolution.split("x")[1], 10) : 0; | |
| const bh = b.resolution ? parseInt(b.resolution.split("x")[1], 10) : 0; | |
| if (bh !== ah) return bh - ah; | |
| return (parseInt(b.bandwidth, 10) || 0) - (parseInt(a.bandwidth, 10) || 0); | |
| }); | |
| console.table(variants); | |
| // Also print as copy-friendly text | |
| console.log("\nCopy-friendly list:"); | |
| console.log( | |
| variants | |
| .map(v => `${v.resolution || "?"} ${v.bandwidth ? `(${v.bandwidth})` : ""}: ${v.url}`) | |
| .join("\n") | |
| ); | |
| } catch (e) { | |
| console.error("Failed:", e); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment