UNPKG

opex-yt-info

Version:

Node.js library for searching YouTube (videos, channels, live), getting video/playlist metadata, and fetching homepage/trending videos.

516 lines (435 loc) 18.1 kB
[![npm version](https://badge.fury.io/js/opex-yt-info.svg)](https://badge.fury.io/js/opex-yt-info) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Visitors](https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fnpmjs.com%2Fopex-yt-info&countColor=%23263759&style=flat)](https://visitorbadge.io/status?path=https%3A%2F%2Fnpmjs.com%2Fopex-yt-info) # Opex YouTube Search / Поиск Opex YouTube [English](#english) | [Русский](#русский) --- ## English A Node.js library (ESM) providing separate, intuitive functions for searching YouTube content (videos, channels, live streams) and retrieving basic metadata for videos and playlists. ### Features * **Clear Separation:** Dedicated functions like `searchVideos`, `searchChannels`, `searchLive`, `getVideo`, `getPlaylist`. * **Promise-based:** All functions return Promises for easy async/await usage. * **Type Definitions:** Includes TypeScript definitions for better developer experience. * **Search Options:** Supports common search options like language (`hl`), region (`gl`), pagination (`pageStart`, `pageEnd`), and User-Agent. * **URL/ID Flexibility:** `getVideo` and `getPlaylist` accept both YouTube URLs and IDs. * **Combined Search:** `searchAll` function to get videos, channels, and live streams in one call. ### Installation ```bash npm install opex-yt-info # or yarn add opex-yt-info # or pnpm add opex-yt-info ``` ### Usage (ESM) ```javascript import { searchVideos, searchChannels, searchLive, searchAll, getVideo, getPlaylist } from 'opex-yt-info'; // --- Search Examples --- async function runSearches() { try { console.log('--- Searching Videos ---'); const videos = await searchVideos('lofi hip hop radio', { pageEnd: 1 }); if (videos.length > 0) { videos.slice(0, 3).forEach(v => console.log(`[Video] ${v.title} (${v.timestamp}) - ${v.views} views`)); } else { console.log('No videos found.'); } console.log('\n--- Searching Channels ---'); const channels = await searchChannels('freecodecamp', { pageEnd: 1 }); if (channels.length > 0) { channels.slice(0, 1).forEach(c => console.log(`[Channel] ${c.name} (${c.subCountLabel})`)); } else { console.log('No channels found.'); } console.log('\n--- Searching Live ---'); const liveStreams = await searchLive('live news', { pageEnd: 1 }); if (liveStreams.length > 0) { liveStreams.slice(0, 3).forEach(l => console.log(`[Live] ${l.title} (${l.watching} watching)`)); } else { console.log('No live streams found (or none matching "live news" currently).'); } console.log('\n--- Searching All (Videos, Channels, Live, maybe Playlists) ---'); const allResults = await searchAll('synthwave', { pageEnd: 1 }); if (allResults.length > 0) { allResults.slice(0, 5).forEach(item => { const title = item.title || item.name || 'Unknown Title'; // Use name for channel console.log(`[All:${item.type}] ${title}`); }); } else { console.log('No results found for "synthwave".'); } } catch (error) { console.error('Search failed:', error); } } // --- Get Metadata Examples --- async function runGetters() { try { const videoIdOrUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; // Rick Astley - Never Gonna Give You Up console.log(`\n--- Getting Video Info [${videoIdOrUrl}] ---`); const video = await getVideo(videoIdOrUrl); if (video) { console.log(`Title: ${video.title}`); console.log(`Views: ${video.views}`); console.log(`Upload Date: ${video.uploadDate}`); console.log(`Genre: ${video.genre}`); } else { console.log('Video not found or error fetching.'); } const playlistIdOrUrl = 'PLzDFYTz8KSyBUDaNaPOKVjomV2lCm5W4G'; // Example playlist ID console.log(`\n--- Getting Playlist Info [${playlistIdOrUrl}] ---`); const playlist = await getPlaylist(playlistIdOrUrl); if (playlist) { console.log(`Title: ${playlist.title}`); console.log(`Video Count: ${playlist.size}`); console.log(`Update Date: ${playlist.date}`); console.log(`First video: ${playlist.videos[0]?.title} (${playlist.videos[0]?.duration.timestamp})`); } else { console.log('Playlist not found or error fetching.'); } } catch (error) { console.error('Metadata fetch failed:', error); } } // Run the examples await runSearches(); await runGetters(); ``` ### API *(See `index.d.ts` for detailed TypeScript definitions)* #### Search Functions All search functions accept `query` (string) and optional `options` (object). Options include: `pageStart`, `pageEnd`, `hl`, `gl`, `category`, `sp`, `userAgent`. * **`searchVideos(query, [options])`**: Returns `Promise<Video[]>` * **`searchChannels(query, [options])`**: Returns `Promise<Channel[]>` * **`searchLive(query, [options])`**: Returns `Promise<LiveVideo[]>` * **`searchAll(query, [options])`**: Returns `Promise<Array<Video | Channel | LiveVideo | PlaylistSummary>>` #### Metadata Functions These functions accept an ID or URL (string) and optional `options` (object). Options include: `hl`, `gl`, `userAgent`. * **`getVideo(videoIdOrUrl, [options])`**: Accepts Video ID or URL. Returns `Promise<VideoDetail | null>` * **`getPlaylist(playlistIdOrUrl, [options])`**: Accepts Playlist ID or URL. Returns `Promise<PlaylistDetail | null>` #### Returned Object Structures ##### `Video` (from search) ```typescript { type: 'video'; videoId: string; url: string; title: string; description: string; // May be truncated image: string; // Thumbnail URL thumbnail: string; // Thumbnail URL seconds: number; // Duration in seconds timestamp: string; // Duration formatted (e.g., "3:10") duration: { seconds: number; timestamp: string; toString: () => string; }; ago: string; // Upload time relative (e.g., "1 year ago") views: number; author: { name: string; url: string; }; } ``` ##### `Channel` (from search) ```typescript { type: 'channel'; name: string; url: string; baseUrl?: string; // Relative URL path id?: string; // Channel ID (if available) title: string; about?: string; // Short description image: string; // Avatar URL thumbnail: string; // Avatar URL videoCount: number; videoCountLabel: string; // e.g., "1.2K videos" verified: boolean; subCount: number; // Approximate subscriber count subCountLabel: string; // e.g., "1.2M subscribers" } ``` ##### `LiveVideo` (from search) ```typescript { type: 'live'; videoId: string; url: string; title: string; description: string; image: string; thumbnail: string; watching: number; // Current viewers author: { name: string; url: string; }; status: 'LIVE' | 'UPCOMING'; startTime?: number; // Unix timestamp (ms) for upcoming startDate?: string; // Formatted date string for upcoming } ``` ##### `PlaylistSummary` (from `searchAll`) ```typescript { type: 'list'; listId: string; url: string; title: string; thumbnail: string; image: string; // Alias videoCount: number; author: { name: string; url: string; }; } ``` ##### `VideoDetail` (from `getVideo`) *Inherits from `Video` and adds fields potentially available from the underlying lookup:* ```typescript { // ... all properties from Video ... type: 'video'; genre?: string; uploadDate?: string; // e.g., "2023-10-27" } ``` ##### `PlaylistDetail` (from `getPlaylist`) ```typescript { title: string; listId: string; url: string; size?: number; // Video count views?: number; // Playlist views (if available) date?: string; // Last updated date (YYYY-MM-DD) if available image?: string; // Playlist thumbnail URL thumbnail?: string; // Playlist thumbnail URL videos: Array<{ // Array of video summaries within the playlist title: string; videoId: string; listId: string; thumbnail: string; duration: { seconds: number; timestamp: string; toString: () => string; }; author: { name: string; url: string; }; }>; author: { name: string; url: string; }; // Playlist creator } ``` ### License MIT --- ## Русский Node.js библиотека (ESM), предоставляющая отдельные, интуитивно понятные функции для поиска контента YouTube (видео, каналы, трансляции) и получения базовых метаданных для видео и плейлистов. ### Возможности * **Четкое разделение:** Выделенные функции, такие как `searchVideos`, `searchChannels`, `searchLive`, `getVideo`, `getPlaylist`. * **На основе Promise:** Все функции возвращают Promise для удобного использования с async/await. * **Определения типов:** Включает определения TypeScript для улучшения опыта разработки. * **Опции поиска:** Поддерживает общие опции поиска, такие как язык (`hl`), регион (`gl`), пагинация (`pageStart`, `pageEnd`) и User-Agent. * **Гибкость URL/ID:** `getVideo` и `getPlaylist` принимают как URL YouTube, так и ID. * **Общий поиск:** Функция `searchAll` для получения видео, каналов и трансляций одним вызовом. ### Установка ```bash npm install opex-yt-info # или yarn add opex-yt-info # или pnpm add opex-yt-info ``` ### Использование (ESM) ```javascript import { searchVideos, searchChannels, searchLive, searchAll, getVideo, getPlaylist } from 'opex-yt-info'; // --- Примеры поиска --- async function runSearches() { try { console.log('--- Поиск Видео ---'); const videos = await searchVideos('lofi hip hop radio', { pageEnd: 1 }); if (videos.length > 0) { videos.slice(0, 3).forEach(v => console.log(`[Видео] ${v.title} (${v.timestamp}) - ${v.views} просмотров`)); } else { console.log('Видео не найдены.'); } console.log('\n--- Поиск Каналов ---'); const channels = await searchChannels('freecodecamp', { pageEnd: 1 }); if (channels.length > 0) { channels.slice(0, 1).forEach(c => console.log(`[Канал] ${c.name} (${c.subCountLabel})`)); } else { console.log('Каналы не найдены.'); } console.log('\n--- Поиск Трансляций ---'); const liveStreams = await searchLive('live news', { pageEnd: 1 }); if (liveStreams.length > 0) { liveStreams.slice(0, 3).forEach(l => console.log(`[Live] ${l.title} (${l.watching} смотрят)`)); } else { console.log('Трансляции не найдены (или нет совпадений с "live news" в данный момент).'); } console.log('\n--- Поиск Всего (Видео, Каналы, Live, возможно Плейлисты) ---'); const allResults = await searchAll('synthwave', { pageEnd: 1 }); if (allResults.length > 0) { allResults.slice(0, 5).forEach(item => { const title = item.title || item.name || 'Неизвестное название'; // Используем name для канала console.log(`[Все:${item.type}] ${title}`); }); } else { console.log('Результаты для "synthwave" не найдены.'); } } catch (error) { console.error('Поиск не удался:', error); } } // --- Примеры получения метаданных --- async function runGetters() { try { const videoIdOrUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; // Rick Astley - Never Gonna Give You Up console.log(`\n--- Получение информации о видео [${videoIdOrUrl}] ---`); const video = await getVideo(videoIdOrUrl); if (video) { console.log(`Название: ${video.title}`); console.log(`Просмотры: ${video.views}`); console.log(`Дата загрузки: ${video.uploadDate}`); console.log(`Жанр: ${video.genre}`); } else { console.log('Видео не найдено или ошибка загрузки.'); } const playlistIdOrUrl = 'PLzDFYTz8KSyBUDaNaPOKVjomV2lCm5W4G'; // Пример ID плейлиста console.log(`\n--- Получение информации о плейлисте [${playlistIdOrUrl}] ---`); const playlist = await getPlaylist(playlistIdOrUrl); if (playlist) { console.log(`Название: ${playlist.title}`); console.log(`Кол-во видео: ${playlist.size}`); console.log(`Дата обновления: ${playlist.date}`); console.log(`Первое видео: ${playlist.videos[0]?.title} (${playlist.videos[0]?.duration.timestamp})`); } else { console.log('Плейлист не найден или ошибка загрузки.'); } } catch (error) { console.error('Получение метаданных не удалось:', error); } } // Запуск примеров await runSearches(); await runGetters(); ``` ### API *(См. `index.d.ts` для подробных определений TypeScript)* #### Функции Поиска Все функции поиска принимают `query` (string) и опциональный `options` (object). Опции включают: `pageStart`, `pageEnd`, `hl`, `gl`, `category`, `sp`, `userAgent`. * **`searchVideos(query, [options])`**: Возвращает `Promise<Video[]>` * **`searchChannels(query, [options])`**: Возвращает `Promise<Channel[]>` * **`searchLive(query, [options])`**: Возвращает `Promise<LiveVideo[]>` * **`searchAll(query, [options])`**: Возвращает `Promise<Array<Video | Channel | LiveVideo | PlaylistSummary>>` #### Функции Получения Метаданных Эти функции принимают ID или URL (string) и опциональный `options` (object). Опции включают: `hl`, `gl`, `userAgent`. * **`getVideo(videoIdOrUrl, [options])`**: Принимает ID или URL видео. Возвращает `Promise<VideoDetail | null>` * **`getPlaylist(playlistIdOrUrl, [options])`**: Принимает ID или URL плейлиста. Возвращает `Promise<PlaylistDetail | null>` #### Структуры Возвращаемых Объектов ##### `Video` (из поиска) ```typescript { type: 'video'; videoId: string; url: string; title: string; description: string; // Может быть усеченным image: string; // URL превью thumbnail: string; // URL превью seconds: number; // Длительность в секундах timestamp: string; // Длительность в формате "Ч:ММ:СС" duration: { seconds: number; timestamp: string; toString: () => string; }; ago: string; // Как давно загружено (напр., "1 год назад") views: number; author: { name: string; url: string; }; } ``` ##### `Channel` (из поиска) ```typescript { type: 'channel'; name: string; url: string; baseUrl?: string; // Относительный URL id?: string; // ID канала title: string; about?: string; // Краткое описание image: string; // URL аватара thumbnail: string; // URL аватара videoCount: number; videoCountLabel: string; // напр., "1.2K видео" verified: boolean; subCount: number; // Примерное кол-во подписчиков subCountLabel: string; // напр., "1.2M подписчиков" } ``` ##### `LiveVideo` (из поиска) ```typescript { type: 'live'; videoId: string; url: string; title: string; description: string; image: string; thumbnail: string; watching: number; // Зрителей сейчас author: { name: string; url: string; }; status: 'LIVE' | 'UPCOMING'; startTime?: number; // Unix timestamp (ms) для предстоящих startDate?: string; // Форматированная дата для предстоящих } ``` ##### `PlaylistSummary` (из `searchAll`) ```typescript { type: 'list'; listId: string; url: string; title: string; thumbnail: string; image: string; // Alias videoCount: number; author: { name: string; url: string; }; } ``` ##### `VideoDetail` (из `getVideo`) *Наследует от `Video` и добавляет поля, потенциально доступные при запросе по ID:* ```typescript { // ... все поля из Video ... type: 'video'; genre?: string; uploadDate?: string; // напр., "2023-10-27" } ``` ##### `PlaylistDetail` (из `getPlaylist`) ```typescript { title: string; listId: string; url: string; size?: number; // Кол-во видео views?: number; // Просмотры плейлиста (если есть) date?: string; // Дата последнего обновления (YYYY-MM-DD) если есть image?: string; // URL превью плейлиста thumbnail?: string; // URL превью плейлиста videos: Array<{ // Массив кратких данных о видео в плейлисте title: string; videoId: string; listId: string; thumbnail: string; duration: { seconds: number; timestamp: string; toString: () => string; }; author: { name: string; url: string; }; }>; author: { name: string; url: string; }; // Создатель плейлиста } ``` ### Лицензия MIT