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
Markdown
[](https://badge.fury.io/js/opex-yt-info)
[](https://opensource.org/licenses/MIT)
[](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