Skip to content

Instantly share code, notes, and snippets.

@mistic100
Created September 15, 2018 09:01
Show Gist options
  • Save mistic100/895f6d17b1e193334882a4c37d0d7748 to your computer and use it in GitHub Desktop.
Save mistic100/895f6d17b1e193334882a4c37d0d7748 to your computer and use it in GitHub Desktop.
Download video from Vimeo (chopped m4s files)
// 1. Open the browser developper console on the network tab
// 2. Start the video
// 3. In the dev tab, locate the load of the "master.json" file, copy its full URL
// 4. Run: node vimeo-downloader.js "<URL>"
// 5. Combine the m4v and m4a files with mkvmerge
const fs = require('fs');
const url = require('url');
const https = require('https');
let masterUrl = process.argv[2];
if (!masterUrl.endsWith('?base64_init=1')) {
masterUrl+= '?base64_init=1';
}
getJson(masterUrl, (err, json) => {
if (err) {
throw err;
}
const videoData = json.video.pop();
const audioData = json.audio.pop();
const videoBaseUrl = url.resolve(url.resolve(masterUrl, json.base_url), videoData.base_url);
const audioBaseUrl = url.resolve(url.resolve(masterUrl, json.base_url), audioData.base_url);
processFile('video', videoBaseUrl, videoData.init_segment, videoData.segments, json.clip_id + '.m4v', (err) => {
if (err) {
throw err;
}
processFile('audio', audioBaseUrl, audioData.init_segment, audioData.segments, json.clip_id + '.m4a', (err) => {
if (err) {
throw err;
}
});
});
});
function processFile(type, baseUrl, initData, segments, filename, cb) {
if (fs.existsSync(filename)) {
console.log(`${type} already exists`);
return cb();
}
const segmentsUrl = segments.map((seg) => baseUrl + seg.url);
const initBuffer = Buffer.from(initData, 'base64');
fs.writeFileSync(filename, initBuffer);
const output = fs.createWriteStream(filename, {flags: 'a'});
combineSegments(type, 0, segmentsUrl, output, (err) => {
if (err) {
return cb(err);
}
output.end();
cb();
});
}
function combineSegments(type, i, segmentsUrl, output, cb) {
if (i >= segmentsUrl.length) {
console.log(`${type} done`);
return cb();
}
console.log(`Download ${type} segment ${i}`);
https.get(segmentsUrl[i], (res) => {
res.on('data', (d) => output.write(d));
res.on('end', () => combineSegments(type, i+1, segmentsUrl, output, cb));
}).on('error', (e) => {
cb(e);
});
}
function getJson(url, cb) {
let data = '';
https.get(url, (res) => {
res.on('data', (d) => data+= d);
res.on('end', () => cb(null, JSON.parse(data)));
}).on('error', (e) => {
cb(e);
});
}
@pencilcheck
Copy link

pencilcheck commented Aug 13, 2023

youtube-dl....

This works! I just need to run
ffmpeg -i video_file -i audio_file -c:v copy -c:a copy out_file.mp4 to merge the files after the download then it is a proper mp4 with audio!!

@huizqcolin
Copy link

Hi there, thanks for your script! Might I suggest modifying the code to use multi-threading to speed up the download? thank you.

@MikeBlueberry
Copy link

What if there is no master.json? The only json files available are a manifest.json and a playlist.json

@Tusko
Copy link

Tusko commented Sep 8, 2024

@MikeBlueberry it's impossible. please provide the screenshot

@MikeBlueberry
Copy link

@MikeBlueberry it's impossible. please provide the screenshot

This is a protected Vimeo video, Edge Dev Tools (F12) > Network tab:
Captura de ecrã 2024-09-09 023432

@sickrandir
Copy link

Hi have the same situation as @MikeBlueberry. Any chance this can still be downloaded? Or should I just resort to screen recording it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment