video-to-gif
Version:
A Node.js module that searches YouTube videos by song name and converts clips to animated GIFs
222 lines (189 loc) โข 6.58 kB
JavaScript
import path from 'path';
import fs from 'fs';
import { searchYouTube } from './lib/youtube-search.js';
import { downloadVideo } from './lib/video-downloader.js';
import { extractAndConvertToGif } from './lib/video-processor.js';
import { createDirectories, cleanupTempFiles, formatDuration } from './lib/utils.js';
/**
* YouTube to GIF converter module
* @class YTGifConverter
*/
class YTGifConverter {
constructor(options = {}) {
this.options = {
outputDir: options.outputDir || './output',
tempDir: options.tempDir || './temp',
quality: options.quality || 'high',
duration: options.duration || 10,
cleanup: options.cleanup !== false, // Default to true
...options
};
}
/**
* Convert a YouTube video to GIF by song name
* @param {string} songName - The song name to search for
* @param {Object} customOptions - Override default options for this conversion
* @returns {Promise<Object>} Result object with GIF path and video info
*/
async convertByName(songName, customOptions = {}) {
const options = { ...this.options, ...customOptions };
try {
console.log(`๐ต Searching for: "${songName}"`);
// Ensure directories exist
await createDirectories([options.outputDir, options.tempDir]);
// Search for the song on YouTube
const searchResults = await searchYouTube(songName);
if (!searchResults || searchResults.length === 0) {
console.log('No videos found for the given song name');
}
const video = searchResults[0];
// Download the video
const videoPath = await downloadVideo(video.videoId, options.tempDir, options.quality);
// Extract clip and convert to GIF
console.log('๐ฌ Extracting clip and converting to GIF...');
const gifPath = await extractAndConvertToGif(
videoPath,
options.outputDir,
parseInt(options.duration),
video.title
);
console.log(`๐ GIF created successfully: ${gifPath}`);
// Cleanup temporary files if enabled
if (options.cleanup) {
await cleanupTempFiles(options.tempDir);
console.log('๐งน Temporary files cleaned up');
}
return {
success: true,
gifPath,
videoInfo: video,
outputDir: options.outputDir,
tempDir: options.tempDir
};
} catch (error) {
console.log('โ Error:', error.message);
// Cleanup on error if enabled
if (options.cleanup) {
try {
await cleanupTempFiles(options.tempDir);
} catch (cleanupError) {
console.error('โ ๏ธ Failed to cleanup temporary files:', cleanupError.message);
}
}
console.log(error);
}
}
/**
* Convert a YouTube video to GIF by video ID
* @param {string} videoId - YouTube video ID
* @param {string} title - Video title for naming (optional)
* @param {Object} customOptions - Override default options for this conversion
* @returns {Promise<Object>} Result object with GIF path and video info
*/
async convertById(videoId, title = 'video', customOptions = {}) {
const options = { ...this.options, ...customOptions };
try {
// Ensure directories exist
await createDirectories([options.outputDir, options.tempDir]);
// Download the video
const videoPath = await downloadVideo(videoId, options.tempDir, options.quality);
// Extract clip and convert to GIF
const gifPath = await extractAndConvertToGif(
videoPath,
options.outputDir,
parseInt(options.duration),
title
);
// Cleanup temporary files if enabled
if (options.cleanup) {
await cleanupTempFiles(options.tempDir);
}
return {
success: true,
gifPath,
videoId,
title,
outputDir: options.outputDir,
tempDir: options.tempDir
};
} catch (error) {
console.log('โ Error:', error.message);
// Cleanup on error if enabled
if (options.cleanup) {
try {
await cleanupTempFiles(options.tempDir);
} catch (cleanupError) {
console.log('โ ๏ธ Failed to cleanup temporary files:', cleanupError.message);
}
}
console.log(error);
return null;
}
}
/**
* Search YouTube videos by song name without downloading
* @param {string} songName - The song name to search for
* @param {number} limit - Maximum number of results to return
* @returns {Promise<Array>} Array of video objects
*/
async search(songName, limit = 5) {
try {
const results = await searchYouTube(songName, limit);
return results;
} catch (error) {
console.log('โ Search error:', error.message);
return null;
}
}
/**
* Update converter options
* @param {Object} newOptions - New options to merge with existing ones
*/
updateOptions(newOptions) {
this.options = { ...this.options, ...newOptions };
}
/**
* Get current converter options
* @returns {Object} Current options
*/
getOptions() {
return { ...this.options };
}
}
/**
* Quick function to convert a song to GIF with default settings
* @param {string} songName - The song name to search for
* @param {Object} options - Conversion options
* @returns {Promise<Object>} Result object
*/
async function convertSongToGif(songName, options = {}) {
const converter = new YTGifConverter(options);
return await converter.convertByName(songName);
}
/**
* Quick function to convert a video ID to GIF with default settings
* @param {string} videoId - YouTube video ID
* @param {string} title - Video title for naming (optional)
* @param {Object} options - Conversion options
* @returns {Promise<Object>} Result object
*/
async function convertVideoToGif(videoId, title = 'video', options = {}) {
const converter = new YTGifConverter(options);
return await converter.convertById(videoId, title);
}
/**
* Search YouTube videos by song name
* @param {string} songName - The song name to search for
* @param {number} limit - Maximum number of results to return
* @returns {Promise<Array>} Array of video objects
*/
async function searchVideos(songName, limit = 5) {
return await searchYouTube(songName, limit);
}
export {
YTGifConverter,
convertSongToGif,
convertVideoToGif,
searchVideos
};
export default YTGifConverter;