@ytb-dw/sdk
Version:
Official JavaScript SDK for ytb-dw YouTube download service - Download YouTube videos and audio with ease
205 lines (173 loc) • 6.75 kB
JavaScript
class YtbDwClient {
constructor(apiKey, baseUrl = 'https://ytb-dw-api.onrender.com') {
if (!apiKey) {
throw new Error('API key is required');
}
this.apiKey = apiKey;
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
}
/**
* Get video information without downloading
* @param {string} url - YouTube video URL
* @returns {Promise<Object>} Video information
*/
async getVideoInfo(url) {
if (!url) {
throw new Error('YouTube URL is required');
}
try {
const response = await fetch(`${this.baseUrl}/video_info.php?url=${encodeURIComponent(url)}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${this._getErrorMessage(response.status)}`);
}
const data = await response.json();
if (!data.success) {
throw new Error(data.error || 'Unknown error occurred');
}
return data;
} catch (error) {
throw new Error(`Failed to get video info: ${error.message}`);
}
}
/**
* Download a YouTube video
* @param {string} url - YouTube video URL
* @param {Object} options - Download options
* @param {string} options.format - 'audio' or 'video' (default: 'video')
* @param {string} options.quality - '480', '720', '1080', 'best' (default: 'best')
* @returns {Promise<Response>} Download response
*/
async downloadVideo(url, options = {}) {
if (!url) {
throw new Error('YouTube URL is required');
}
const { format = 'video', quality = 'best' } = options;
const params = new URLSearchParams({
api_key: this.apiKey,
url: url,
format: format,
quality: quality
});
try {
const response = await fetch(`${this.baseUrl}/download.php?${params.toString()}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${this._getErrorMessage(response.status)}`);
}
return response;
} catch (error) {
throw new Error(`Failed to download video: ${error.message}`);
}
}
/**
* Download video as audio (MP3)
* @param {string} url - YouTube video URL
* @returns {Promise<Response>} Download response
*/
async downloadAudio(url) {
return this.downloadVideo(url, { format: 'audio' });
}
/**
* Download video in specific quality
* @param {string} url - YouTube video URL
* @param {string} quality - Video quality ('480', '720', '1080', 'best')
* @returns {Promise<Response>} Download response
*/
async downloadVideoQuality(url, quality) {
return this.downloadVideo(url, { format: 'video', quality });
}
/**
* Get download URL (for browser usage)
* @param {string} url - YouTube video URL
* @param {Object} options - Download options
* @returns {string} Download URL
*/
getDownloadUrl(url, options = {}) {
if (!url) {
throw new Error('YouTube URL is required');
}
const { format = 'video', quality = 'best' } = options;
const params = new URLSearchParams({
api_key: this.apiKey,
url: url,
format: format,
quality: quality
});
return `${this.baseUrl}/download.php?${params.toString()}`;
}
/**
* Download and save file (Node.js only)
* @param {string} url - YouTube video URL
* @param {string} filename - Output filename
* @param {Object} options - Download options
* @returns {Promise<void>}
*/
async downloadToFile(url, filename, options = {}) {
// Check if we're in Node.js environment
if (typeof window !== 'undefined') {
throw new Error('downloadToFile is only available in Node.js environment');
}
const fs = require('fs');
const path = require('path');
try {
const response = await this.downloadVideo(url, options);
// Ensure directory exists
const dir = path.dirname(filename);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const fileStream = fs.createWriteStream(filename);
// For Node.js, we need to handle the stream
if (response.body) {
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
fileStream.write(Buffer.from(value));
}
}
fileStream.end();
console.log(`Download completed: ${filename}`);
} catch (error) {
throw new Error(`Failed to download to file: ${error.message}`);
}
}
/**
* Open download in browser (browser only)
* @param {string} url - YouTube video URL
* @param {Object} options - Download options
*/
openDownload(url, options = {}) {
if (typeof window === 'undefined') {
throw new Error('openDownload is only available in browser environment');
}
const downloadUrl = this.getDownloadUrl(url, options);
window.open(downloadUrl, '_blank');
}
/**
* Get error message from HTTP status code
* @private
*/
_getErrorMessage(statusCode) {
const errorMessages = {
400: 'Bad Request - Missing or invalid parameters',
401: 'Unauthorized - Invalid or inactive API key',
403: 'Forbidden - Format not authorized for your account',
404: 'Not Found - Video not found or private',
429: 'Too Many Requests - Daily quota exceeded',
500: 'Internal Server Error - Temporary server error'
};
return errorMessages[statusCode] || 'Unknown error';
}
}
// Export for different environments
if (typeof module !== 'undefined' && module.exports) {
// Node.js
module.exports = YtbDwClient;
} else if (typeof window !== 'undefined') {
// Browser
window.YtbDwClient = YtbDwClient;
}
// Default export for ES6 modules
if (typeof exports !== 'undefined') {
exports.default = YtbDwClient;
}