Last active
April 1, 2024 13:13
-
-
Save Maxim-Mazurok/b33271b3b72b60ff0f900c67033ff74e to your computer and use it in GitHub Desktop.
Private Vimeo / Akamai CDN long video downloader
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
// NOTE: you might have to run it a few times if it doesn't download the full video from the first try, I guess it needs to be cached or something.. | |
const { appendFileSync, writeFileSync } = require("fs"); | |
const https = require("https"); | |
// find that URL in devtools, search for akamai, there's also manifest with different names based on quality (remove &range from it) | |
const URL = `https://xxxxx-adaptive.akamaized.net/exp=0000000000~xxx=xxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxx~xxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/parcel/video/xxxxxxxx.mp4?r=xxxxxxxxxxxxxxxxxx`; | |
const rangeWidth = 1000000000; // using smaller range will be slower, but might result in more stable/reliable download success | |
let foundEnd = false; | |
let currentStart = 0; | |
let gotData = 0; | |
const fileName = "video.mp4"; | |
currentStart === 0 && writeFileSync(fileName, ""); | |
let data = []; | |
const getNextChunk = () => { | |
const currentUrl = `${URL}&range=${currentStart}-${currentStart + rangeWidth}`; | |
console.log(currentUrl); | |
const request = https.get(currentUrl, (response) => { | |
data = []; | |
if (response.statusCode !== 200) { | |
console.log({ statusCode: response.statusCode }); | |
foundEnd = true; | |
process.exit(); | |
} | |
response.on("data", (chunk) => { | |
gotData++; | |
gotData % 1000 === 1 && console.log("got data", chunk); | |
data.push(chunk); | |
}); | |
response.on("end", () => { | |
console.log("end of chunk"); | |
for (const datum of data) { | |
appendFileSync(fileName, datum); | |
} | |
if (!foundEnd) { | |
currentStart += rangeWidth + 1; | |
getNextChunk(); | |
} | |
}); | |
response.on("close", (x) => console.log("close", x)); | |
response.on("error", (x) => console.log("error", x)); | |
response.on("pause", (x) => console.log("pause", x)); | |
}); | |
request.on("error", (error) => { | |
console.error("found error/end", error); | |
foundEnd = true; | |
}); | |
}; | |
getNextChunk(); |
Also if it fails with connection reset - see last URL in log and change currentStart
to the starting range from the last URL that was unsuccessful.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is URL to copy, shows up when you press play:

This is manifest with different qualities:

This time
1000000000
didn't work, got "connection reset". Lowering to1000000
seems to have helped.