@vidpickr/sdk
v0.1.1
Published
Official Node.js SDK for the VidPickr API — download YouTube videos with one function call. No ffmpeg dependency.
Maintainers
Readme
vidpickr
Official Node.js SDK for the VidPickr API. Download YouTube videos with a single function call. No ffmpeg dependency — the SDK bundles a pure-JS MP4 muxer.
import { VidPickr } from '@vidpickr/sdk';
const vp = new VidPickr({ apiKey: process.env.VIDPICKR_API_KEY! });
await vp.download('https://www.youtube.com/watch?v=dQw4w9WgXcQ', {
out: 'video.mp4',
quality: 1080,
});That's it. The SDK:
- Resolves the URL through
/api/v1/info - Picks the best 1080p video track and the highest-bitrate audio track
- Streams both in parallel from the API's
/api/v1/streamendpoint - Muxes them on the fly into one MP4 (no temp files, no ffmpeg)
- Writes the result to
video.mp4
Requirements
- Node.js 18 or newer (the SDK uses global
fetchandWeb Streams) - A VidPickr Plus subscription ($1/mo) and an API key, minted at vidpickr.com/account/api-keys
Install
npm install @vidpickr/sdk
# or
pnpm add @vidpickr/sdk
# or
yarn add @vidpickr/sdkTotal install footprint is ~1 MB. No native dependencies; works on macOS, Linux, Windows.
API
new VidPickr(options)
Construct the client.
| Option | Type | Required | Default |
|----------|-----------------------|----------|----------------------------------------|
| apiKey | string | yes | — |
| baseUrl| string | no | https://vidpickr.com/api/v1 |
| fetch | typeof fetch | no | global fetch |
vp.download(url, options)
Resolve, stream, mux, and write to disk. Returns Promise<void>.
| Option | Type | Required | Description |
|--------------|----------------------------|----------|------------------------------------------------------------------------|
| out | string | yes | Output file path. Parent directory must exist. |
| quality | 'best' \| 'highest' \| 'lowest' \| number | no | Target height in px, or a preset. Default 'best'. |
| videoCodec | 'av1' \| 'vp9' \| 'avc' \| 'hevc' | no | Preferred codec when multiple variants exist at the same height. |
| onProgress | (p) => void | no | Periodic progress callback (phase, videoBytes, audioBytes, …). |
| signal | AbortSignal | no | Cancel mid-download. |
vp.info(url)
Just the resolution step. Returns the full VideoInfo JSON. Useful when you want to inspect format options before deciding what to download.
vp.raw
Low-level access to the HTTP client (info(), openStream()). Use this when you need to build a custom pipeline — e.g. piping the audio track into your own transcription system without writing to disk.
Errors
import { APIError, MuxError, NoFormatError } from '@vidpickr/sdk';
try {
await vp.download(url, { out: 'x.mp4' });
} catch (e) {
if (e instanceof APIError && e.code === 'rate_limited') {
console.log(`Retry in ${e.retryAfter}s`);
} else if (e instanceof APIError && e.code === 'plus_required') {
console.log('Upgrade to Plus first.');
} else if (e instanceof MuxError) {
console.log('Mux failed — usually a YouTube format we haven\'t mapped yet.');
} else {
throw e;
}
}Progress reporting
await vp.download(url, {
out: 'x.mp4',
onProgress(p) {
const pct = p.videoTotal > 0
? Math.round((p.videoBytes / p.videoTotal) * 100)
: 0;
process.stdout.write(`\r${p.phase} · ${pct}% `);
},
});phase values: resolving, fetching, muxing, finalizing, done.
Cancellation
const ac = new AbortController();
setTimeout(() => ac.abort(), 5000);
await vp.download(url, { out: 'x.mp4', signal: ac.signal });Why no ffmpeg?
YouTube serves video and audio as separate tracks for everything above 720p. Joining them is a container operation, not an encoding one — the bytes themselves stay identical; only the wrapping changes. ffmpeg is overkill for this and adds an ~80 MB install dependency. The SDK uses mp4-muxer (the same library powering VidPickr's web app) to do it natively in JavaScript, in a few seconds of wall-clock time.
License
MIT
