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

aik099 commented Nov 9, 2020

Forked:

  • Downloads highest quality available (@genabasov)
  • Combines audio and video together using ffmpeg (make sure ffmpeg is installed before running) (@aik099)

https://gist.github.com/alexdrean/a027dd89a90a6d0aa54983f87f34a5c4

Nice.

@marcusademola
Copy link

Any ideas how to resolve a timeout error
(there are over 800 seqments in the orginial, note xx refer IP addresses of the video proxy)
throw err;
^
Error: connect ETIMEDOUT 1xx.1xx.xx.xx:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1107:14)

Any hints to resolve the timeout errors are welcomed

@aik099
Copy link

aik099 commented Dec 10, 2020

@marcusademola, since every segment is a new HTTP connection then segment count increase shouldn't make things worse.

You can try adding some console.log to see if it's a particular segment that always fails or the fact, that segments are downloaded too quickly and Vimeo imposes timeout on purpose to avoid DoS attack. Maybe adding a random delay between segment downloads will help.

@abdus
Copy link

abdus commented Jan 1, 2021

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 :)

@Attosius
Copy link

Attosius commented Jan 1, 2021

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

@aik099
Copy link

aik099 commented Jan 2, 2021

@abdus, thanks. I have no idea, that Vimeo has URL to the Manifest file, that Youtube-DL can understand.

@p-try
Copy link

p-try commented Mar 1, 2021

You are a hero Sir, thank you SO much. The script works.

@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

@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