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);
});
}
@pmayur
Copy link

pmayur commented Oct 13, 2021

this is amazing, thanks for this script

@anggapw
Copy link

anggapw commented Feb 26, 2022

@abdus I have successfully downloaded the video. But why is there no sound?

WARNING: [generic] Falling back on generic information extractor.
[generic] master: Downloading webpage
[generic] master: Extracting information
[info] master: Downloading 1 format(s): video-cf3328cc+audio-4a1f853e
[dashsegments] Total fragments: 27
[download] Destination: master [master].fvideo-cf3328cc.mp4
[download] 100% of 39.83MiB in 00:24
ERROR: unable to download video data: HTTP Error 403: Forbidden

@Tusko
Copy link

Tusko commented Mar 7, 2022

@ajay-ghub
Copy link

ajay-ghub commented Mar 23, 2022

Easier, if you have youtube-dl installed:

1. copy the `master.json` URL

2. replace `.json?base64_init=1` with `.mpd`

3. provide it to `youtube-dl`: `youtube-dl EDITED_URL`

yt-dl will download the best quality available :)

If you have the Vimeo Video ID with you (which was the case for me), you can also provide website URL and Video ID based URL to youtube-dl: youtube-dl --referer 'Website URL for Video Page' player.vimeo.com/video/<video-id>

This can save the effort of manually finding master.json URL.

@vaibhavbangwal
Copy link

How do I make this work for HTTP?

@DGrv
Copy link

DGrv commented Apr 1, 2022

Easier, if you have youtube-dl installed:

  1. copy the master.json URL
  2. replace .json?base64_init=1 with .mpd
  3. provide it to youtube-dl: youtube-dl EDITED_URL

yt-dl will download the best quality available :)

It's amazing! And just add ffmpeg.exe for automerge mp4 and m4a

This works as well like a charm :)

@koma-xrd
Copy link

thanks

Easier, if you have youtube-dl installed:

  1. copy the master.json URL
  2. replace .json?base64_init=1 with .mpd
  3. provide it to youtube-dl: youtube-dl EDITED_URL

yt-dl will download the best quality available :)

It's amazing! And just add ffmpeg.exe for automerge mp4 and m4a

thanks for the ffmpeg-hint

@kevinaso
Copy link

Hi folks, not a very experienced one. Where am Im supposed to input the master.json url? Also it will work just running the script in visual studio code or is it necessary to set up a project in a dedicated IDE?

@aik099
Copy link

aik099 commented Jul 13, 2022

Hi folks, not a very experienced one. Where am Im supposed to input the master.json url? Also it will work just running the script in visual studio code or is it necessary to set up a project in a dedicated IDE?

In the Terminal.

@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

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