UNPKG

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
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;