### Install and Start Project (npm) Source: https://github.com/moshfeu/y2mp3/blob/master/README.md Use these commands to install project dependencies and start the application using npm. ```bash npm install npm start ``` -------------------------------- ### Install and Start Project (yarn) Source: https://github.com/moshfeu/y2mp3/blob/master/README.md Use these commands to install project dependencies and start the application using yarn. ```bash yarn yarn start ``` -------------------------------- ### Install FFmpeg Source: https://context7.com/moshfeu/y2mp3/llms.txt Utility functions to check for FFmpeg installation and automatically download FFmpeg binaries if not present on the system. Use `isFFMpegInstalled` to check availability and `installFfmpeg` for automatic download with progress updates. `isFfmpegInPath` specifically checks the system's PATH. ```typescript import { installFfmpeg, isFFMpegInstalled } from './services/ffmpeg-installer'; import { isFfmpegInPath, setFfmpegPath } from './services/api'; // Check if FFmpeg is available (in PATH or app data folder) if (isFFMpegInstalled()) { console.log('FFmpeg is ready'); setFfmpegPath(); // Configure fluent-ffmpeg with the path } else { console.log('FFmpeg not found, installing...'); // Download FFmpeg with progress updates await installFfmpeg((progress) => { console.log(`Download progress: ${(progress.progress * 100).toFixed(1)}%`); }); console.log('FFmpeg installed successfully'); } // Check specifically if ffmpeg is in system PATH if (isFfmpegInPath()) { console.log('Using system FFmpeg'); } ``` -------------------------------- ### Create and Manage Download Queue Source: https://context7.com/moshfeu/y2mp3/llms.txt Implement a generic task queue for sequential processing of downloads. Supports task cancellation and abortion. The queue starts automatically upon creation. ```typescript import { Queue, ITask } from './services/youtube-mp3-downloader/queue'; // Create a queue (auto-starts by default) const queue = new Queue(true); // Define a task const task: ITask = { id: 'unique-task-id', data: { videoId: 'dQw4w9WgXcQ', onStateChanged: callback }, main: async (task) => { // Task execution logic if (task.aborted) { console.log('Task was cancelled'); return task; } // Perform download... return task; } }; // Add tasks to queue (processed sequentially) queue.add(task1, task2, task3); // Remove/cancel a task queue.remove('unique-task-id'); // Task states during execution: // - If task is current: marked as aborted, queue processes next // - If task is queued: removed from queue and marked aborted ``` -------------------------------- ### Electron Main Process IPC Handlers Source: https://context7.com/moshfeu/y2mp3/llms.txt Set up IPC handlers in the main Electron process to manage application version retrieval and open directory selection dialogs. Also includes an example for updating the tray tooltip. ```typescript // Main process (main.ts) import { ipcMain, dialog, BrowserWindow, app } from 'electron'; // Get app version ipcMain.handle('version', () => app.getVersion()); // Open directory picker dialog ipcMain.handle('open-directory-explorer', async () => { const { filePaths } = await dialog.showOpenDialog( BrowserWindow.getFocusedWindow(), { properties: ['openDirectory', 'createDirectory'], title: 'Choose a directory' } ); return { filePaths }; }); // Tray tooltip updates ipcMain.on('tray', (_, message: string) => { tray.setToolTip(message); }); ``` -------------------------------- ### Initialize and Use YoutubeMp3Downloader Source: https://context7.com/moshfeu/y2mp3/llms.txt Initializes the downloader with configuration options such as FFmpeg path, output directory, video quality, and format. Demonstrates how to download a video with state change callbacks, cancel a download, and update settings dynamically. ```typescript import { YoutubeMp3Downloader, StateChangeAction, DownloadFormat, DownloadQuality } from './youtube-mp3-downloader'; // Initialize the downloader with configuration const downloader = new YoutubeMp3Downloader({ ffmpegPath: '/usr/local/bin/ffmpeg', outputPath: '/Users/downloads', youtubeVideoQuality: 'highest', filter: 'audioandvideo', format: 'mp3' as DownloadFormat, progressTimeout: 1000, outputOptions: ['-id3v2_version', '4'], }); // Download a video with state change callback downloader.download('dQw4w9WgXcQ', (action: StateChangeAction) => { switch (action.state) { case 'added': console.log(`Video ${action.payload} added to queue`); break; case 'getting info': console.log(`Fetching info for ${action.payload}`); break; case 'downloading': const { videoId, progress } = action.payload; console.log(`Downloading ${videoId}: ${progress.percentage.toFixed(2)}%`); console.log(`Speed: ${progress.speed} bytes/s, ETA: ${progress.eta}s`); break; case 'done': const { videoTitle, thumbnail, file } = action.payload; console.log(`Completed: ${videoTitle}`); break; case 'error': console.error(`Error for ${action.payload.videoId}: ${action.error.message}`); break; } }); // Cancel an active download downloader.cancelDownload('dQw4w9WgXcQ'); // Update settings dynamically downloader.setOutputPath('/new/download/path'); downloader.setQuality('highest'); downloader.setFormat('wav'); ``` -------------------------------- ### Tagging a New Release Source: https://github.com/moshfeu/y2mp3/blob/master/README.md This command sequence is used to create and push a Git tag for a new release. Ensure the tag format is `vX.Y.Z`. ```bash git tag -a v1.2.3 -m "1.2.3" git push origin refs/tags/v1.2.3 ``` -------------------------------- ### Manage User Settings Source: https://context7.com/moshfeu/y2mp3/llms.txt Manages user preferences with localStorage persistence. Settings include download folder, audio quality, format, and various UI preferences. Ensure correct types for DownloadQuality and DownloadFormat are used. ```typescript import { settingsManager, IConfig } from './services/settings'; import { DownloadQuality, DownloadFormat } from './services/youtube-mp3-downloader'; // Get/Set downloads folder console.log(settingsManager.downloadsFolder); // Default: ~/Music/y2mp3 settingsManager.downloadsFolder = '/Users/me/Downloads'; // Audio quality: 'lowest', 'highest', or specific itag number settingsManager.audioQuality = 'highest'; // Download format options // Audio: 'mp3', 'ogg', 'wav', 'flac', 'm4a', 'wma', 'aac' // Video: 'mp4', 'mpg', 'wmv' settingsManager.downloadFormat = 'mp3'; // Save playlist videos in dedicated subfolders settingsManager.playlistFolder = true; // Auto-paste YouTube URLs from clipboard on window focus settingsManager.autoPaste = true; // Check for app updates on startup settingsManager.checkForUpdate = true; // Embed video thumbnail as album art (MP3 only) settingsManager.albumArt = true; // Show desktop notification when download completes settingsManager.notificationWhenDone = true; // All settings interface interface IConfig { downloadsFolder: string; audioQuality: DownloadQuality; playlistFolder: boolean; autoPaste: boolean; checkForUpdate: boolean; albumArt: boolean; notificationWhenDone: boolean; downloadFormat: DownloadFormat; } ``` -------------------------------- ### Electron Renderer Process IPC Usage Source: https://context7.com/moshfeu/y2mp3/llms.txt Demonstrates how to use IPC handlers in the renderer process to invoke main process functions, such as retrieving the app version and opening a folder picker. ```typescript // Renderer process usage import { ipcRenderer } from 'electron'; // Get current app version const version = await ipcRenderer.invoke('version'); console.log(`App version: ${version}`); // Open folder picker const { filePaths } = await ipcRenderer.invoke('open-directory-explorer'); if (filePaths.length > 0) { settingsManager.downloadsFolder = filePaths[0]; } ``` -------------------------------- ### YoutubeMp3Downloader Class Source: https://context7.com/moshfeu/y2mp3/llms.txt The core download engine for fetching video information, streaming content, and converting it to the desired format using FFmpeg. It manages a download queue and provides progress callbacks. ```APIDOC ## YoutubeMp3Downloader Class ### Description The core download engine that handles fetching video information from YouTube, streaming content, and converting to the desired format using FFmpeg. It manages a download queue and provides progress callbacks throughout the download lifecycle. ### Methods - `download(videoId: string, callback: StateChangeAction) -> void` - `cancelDownload(videoId: string) -> void` - `setOutputPath(path: string) -> void` - `setQuality(quality: DownloadQuality) -> void` - `setFormat(format: DownloadFormat) -> void` ### Configuration Options - `ffmpegPath` (string): Path to FFmpeg binary. - `outputPath` (string): Output directory for downloads. - `youtubeVideoQuality` (string): Quality of the YouTube video ('lowest', 'highest', or a specific number). - `filter` (string): FFmpeg filter option. - `format` (DownloadFormat): Output format for the downloaded file. - `progressTimeout` (number): Progress update interval in milliseconds. - `outputOptions` (string[]): Additional FFmpeg options. ### StateChangeAction Payload - `added`: `{ videoId: string }` - `getting info`: `{ videoId: string }` - `downloading`: `{ videoId: string, progress: { percentage: number, speed: number, eta: number } }` - `done`: `{ videoId: string, videoTitle: string, thumbnail: string, file: string }` - `error`: `{ videoId: string, error: { message: string } }` ### Request Example ```typescript import { YoutubeMp3Downloader, StateChangeAction, DownloadFormat, DownloadQuality } from './youtube-mp3-downloader'; const downloader = new YoutubeMp3Downloader({ ffmpegPath: '/usr/local/bin/ffmpeg', outputPath: '/Users/downloads', youtubeVideoQuality: 'highest', filter: 'audioandvideo', format: 'mp3' as DownloadFormat, progressTimeout: 1000, outputOptions: ['-id3v2_version', '4'], }); downloader.download('dQw4w9WgXcQ', (action: StateChangeAction) => { switch (action.state) { case 'downloading': const { progress } = action.payload; console.log(`Downloading: ${progress.percentage.toFixed(2)}%`); break; case 'done': const { videoTitle, file } = action.payload; console.log(`Completed: ${videoTitle}, File: ${file}`); break; case 'error': console.error(`Error: ${action.error.message}`); break; } }); ``` ### Response Example (Callbacks provide state updates, no direct response body for download initiation) ``` -------------------------------- ### Define Supported Audio Formats Source: https://context7.com/moshfeu/y2mp3/llms.txt Configuration object for supported audio formats in FFmpeg conversion. Includes direct conversion options and specific codec configurations for formats like MP3 and OGG. ```typescript import { audioFormats, videoFormats } from './services/youtube-mp3-downloader/options'; // Available audio formats const audioFormats = { wav: null, // Direct conversion flac: null, // Direct conversion m4a: null, // Direct conversion wma: null, // Direct conversion mp3: { codec: 'libmp3lame' }, // MP3 with LAME encoder ogg: { codec: 'libvorbis' }, // OGG Vorbis aac: { format: 'adts' }, // AAC with ADTS container }; // Available video formats const videoFormats = { mp4: null, // Direct conversion mpg: null, // Direct conversion wmv: null, // Direct conversion }; // Type definition type DownloadFormat = 'mp3' | 'ogg' | 'wav' | 'flac' | 'm4a' | 'wma' | 'aac' | 'mp4' | 'mpg' | 'wmv'; ``` -------------------------------- ### Fetch YouTube Videos and Metadata Source: https://context7.com/moshfeu/y2mp3/llms.txt Provides functions to validate YouTube URLs, fetch metadata for single videos or entire playlists, and defines the structure of a video entity. Useful for preparing download tasks. ```typescript import { fetchVideos, isYoutubeURL } from './services/api'; import { IVideoEntity } from './types'; // Validate a YouTube URL const url = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; if (isYoutubeURL(url)) { console.log('Valid YouTube URL'); } // Fetch a single video const singleVideoUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; const videos: IVideoEntity[] = await fetchVideos(singleVideoUrl); // Result: [{ id: 'dQw4w9WgXcQ', name: 'Video Title', progress: 0, status: 'Not Started', playlistName: '' }] // Fetch all videos from a playlist (up to 100 videos) const playlistUrl = 'https://www.youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf'; const playlistVideos: IVideoEntity[] = await fetchVideos(playlistUrl); playlistVideos.forEach(video => { console.log(`ID: ${video.id}, Title: ${video.name}, Playlist: ${video.playlistName}`); }); // Video entity structure interface IVideoEntity { id: string; // YouTube video ID name: string; // Video title progress: number; // Download progress (0-100) status: EVideoStatus; // Current status playlistName: string; // Parent playlist name (if applicable) } enum EVideoStatus { NOT_STARTED = 'Not Started', GETTING_INFO = 'Getting Data', PENDING = 'Pending', DOWNLOADING = 'Downloading', DONE = 'Done', ERROR = 'Error', } ``` -------------------------------- ### Video Fetching API Source: https://context7.com/moshfeu/y2mp3/llms.txt Functions for parsing YouTube URLs and fetching video metadata from single videos or entire playlists. Returns structured video entity objects ready for download. ```APIDOC ## Video Fetching API ### Description Functions for parsing YouTube URLs and fetching video metadata from single videos or entire playlists. Returns structured video entity objects ready for download. ### Functions - `isYoutubeURL(url: string) -> boolean` - `fetchVideos(url: string) -> Promise` ### Parameters #### `fetchVideos` function: - **url** (string) - Required - The YouTube URL of a single video or a playlist. ### Return Value - `Promise`: A promise that resolves to an array of `IVideoEntity` objects. ### IVideoEntity Structure - **id** (string) - YouTube video ID. - **name** (string) - Video title. - **progress** (number) - Download progress (0-100). - **status** (EVideoStatus) - Current status of the video. - **playlistName** (string) - Parent playlist name (if applicable). ### EVideoStatus Enum - `NOT_STARTED` - `GETTING_INFO` - `PENDING` - `DOWNLOADING` - `DONE` - `ERROR` ### Request Example ```typescript import { fetchVideos, isYoutubeURL } from './services/api'; const url = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; if (isYoutubeURL(url)) { console.log('Valid YouTube URL'); const videos = await fetchVideos(url); console.log(videos); } const playlistUrl = 'https://www.youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf'; const playlistVideos = await fetchVideos(playlistUrl); playlistVideos.forEach(video => { console.log(`ID: ${video.id}, Title: ${video.name}`); }); ``` ### Response Example ```json [ { "id": "dQw4w9WgXcQ", "name": "Rick Astley - Never Gonna Give You Up (Official Music Video)", "progress": 0, "status": "Not Started", "playlistName": "" } ] ``` ``` -------------------------------- ### Interact with MobX Store Source: https://context7.com/moshfeu/y2mp3/llms.txt The central state management store using MobX observables. Handles video list state, search operations, download progress tracking, and UI state. Use specific methods to manage video status and UI elements. ```typescript import store from './mobx/store'; import { IVideoEntity, EVideoStatus } from './types'; // Search for videos (single video or playlist) await store.search('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); // Access video list console.log(`Videos loaded: ${store.videos.length}`); store.videos.forEach(video => { console.log(`${video.name}: ${video.status} (${video.progress}%)`); }); // Check if videos are in queue if (store.hasVideosInQueue) { console.log('Ready to download'); } // Get specific video by ID const video = store.getVideo('dQw4w9WgXcQ'); // Update video status during download store.addToQueue('dQw4w9WgXcQ'); // Mark as pending store.gettingInfo('dQw4w9WgXcQ'); // Mark as fetching info store.progress({ videoId: 'dQw4w9WgXcQ', progress: { percentage: 50, speed: 1024000, eta: 30, /* ... */ } }); store.finished(null, { videoId: 'dQw4w9WgXcQ' }); // Mark as done store.finished(new Error('Failed'), { videoId: 'abc123' }); // Mark as error // Remove video from list store.removeVideo('dQw4w9WgXcQ'); // Clear all results store.clearResult(); // UI state store.isAboutOpen = true; store.isPreferencesOpen = true; store.hasUpdate = true; store.isFFMpegInstalled; // Read-only, checked on init ``` -------------------------------- ### Scrape YouTube Playlist Source: https://context7.com/moshfeu/y2mp3/llms.txt Scrapes YouTube playlist pages to extract video IDs and titles without requiring API keys. Handles private playlist detection and returns structured playlist data. ```typescript import { scrap } from './services/playlist-scraper'; // Scrape a YouTube playlist const playlistUrl = 'https://www.youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf'; try { const result = await scrap(playlistUrl); console.log(`Playlist Name: ${result.name}`); console.log(`Has more than 100 videos: ${result.hasMore}`); result.playlist.forEach(video => { console.log(`Video ID: ${video.id}, Title: ${video.name}`); }); // Result structure: // { // name: 'My Playlist', // hasMore: false, // playlist: [ // { id: 'dQw4w9WgXcQ', name: 'Video Title 1' }, // { id: 'abc123xyz', name: 'Video Title 2' }, // ] // } } catch (error) { // Handle errors: private playlist, invalid URL, not found console.error(error.message); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.