add vitepress

This commit is contained in:
2025-12-03 22:46:15 +03:00
parent d85cb263ce
commit 0ccd16c1cf
15 changed files with 5802 additions and 4 deletions

367
docs/api/convert.md Normal file
View File

@@ -0,0 +1,367 @@
# convertToDash()
Главная функция для конвертации видео в адаптивные форматы DASH и HLS.
## Сигнатура
```typescript
async function convertToDash(
options: DashConvertOptions
): Promise<DashConvertResult>
```
## Параметры
### `DashConvertOptions`
| Параметр | Тип | Обязательный | По умолчанию | Описание |
|----------|-----|--------------|--------------|----------|
| `input` | `string` | ✅ | - | Путь к входному видео файлу |
| `outputDir` | `string` | ✅ | - | Директория для выходных файлов |
| `segmentDuration` | `number` | ❌ | `2` | Длительность сегмента в секундах |
| `profiles` | `VideoProfile[]` | ❌ | автовыбор | Массив профилей качества |
| `customProfiles` | `string[]` | ❌ | автовыбор | Профили как строки (например, `['720', '1080@60']`) |
| `codec` | `CodecType` | ❌ | `'dual'` | Кодек: `'h264'`, `'av1'` или `'dual'` |
| `format` | `StreamingFormat` | ❌ | `'both'` | Формат: `'dash'`, `'hls'` или `'both'` |
| `useNvenc` | `boolean` | ❌ | auto | Использовать NVENC (автоопределение) |
| `quality` | `QualitySettings` | ❌ | auto | Настройки качества (CQ/CRF) |
| `generateThumbnails` | `boolean` | ❌ | `true` | Генерировать превью-спрайт |
| `thumbnailConfig` | `ThumbnailConfig` | ❌ | см. ниже | Конфигурация превью |
| `generatePoster` | `boolean` | ❌ | `true` | Генерировать постер |
| `posterTimecode` | `string` | ❌ | `'00:00:01'` | Таймкод постера |
| `parallel` | `boolean` | ❌ | `true` | Параллельное кодирование |
| `onProgress` | `function` | ❌ | - | Колбэк для прогресса |
## Возвращаемое значение
### `DashConvertResult`
```typescript
interface DashConvertResult {
manifestPath: string; // Путь к DASH манифесту
hlsManifestPath?: string; // Путь к HLS манифесту (если format='hls' или 'both')
segments: string[]; // Пути к сегментам
thumbnailPath?: string; // Путь к спрайту превью
posterPath?: string; // Путь к постеру
}
```
## Примеры
### Базовое использование
```typescript
import { convertToDash } from '@grom13/adaptive-video-converter';
const result = await convertToDash({
input: './video.mp4',
outputDir: './output'
});
console.log('DASH манифест:', result.manifestPath);
console.log('HLS манифест:', result.hlsManifestPath);
```
### С кастомными профилями
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
customProfiles: ['360', '720', '1080']
});
```
### С высоким FPS
```typescript
const result = await convertToDash({
input: './gameplay.mp4',
outputDir: './output',
customProfiles: ['720@60', '1080@60', '1440@120']
});
```
### Выбор кодека
```typescript
// Только H.264
await convertToDash({
input: './video.mp4',
outputDir: './output',
codec: 'h264'
});
// Только AV1
await convertToDash({
input: './video.mp4',
outputDir: './output',
codec: 'av1'
});
// Оба кодека (по умолчанию)
await convertToDash({
input: './video.mp4',
outputDir: './output',
codec: 'dual'
});
```
### Выбор формата
```typescript
// Только DASH
await convertToDash({
input: './video.mp4',
outputDir: './output',
format: 'dash'
});
// Только HLS
await convertToDash({
input: './video.mp4',
outputDir: './output',
format: 'hls',
codec: 'h264' // HLS лучше работает с H.264
});
// Оба формата (по умолчанию)
await convertToDash({
input: './video.mp4',
outputDir: './output',
format: 'both'
});
```
### С отслеживанием прогресса
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
onProgress: (progress) => {
console.log(`Прогресс: ${progress.percent}%`);
console.log(`Этап: ${progress.stage}`);
console.log(`Профиль: ${progress.currentProfile}`);
console.log(`ETA: ${progress.eta}s`);
}
});
```
### С настройками качества
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
quality: {
h264: {
cq: 28, // CQ для GPU
crf: 23 // CRF для CPU (фоллбек)
},
av1: {
cq: 35,
crf: 35
}
}
});
```
### С кастомной конфигурацией превью
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
thumbnailConfig: {
width: 320, // Ширина превью
height: 180, // Высота превью
interval: 2, // Интервал в секундах
columns: 10, // Колонок в спрайте
rows: 10 // Строк в спрайте
}
});
```
### С кастомным постером
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
posterTimecode: '00:02:30' // Постер с 2:30
});
```
### Без превью и постера
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
generateThumbnails: false,
generatePoster: false
});
```
### С предварительной проверкой системы
```typescript
import {
convertToDash,
checkFFmpeg,
checkMP4Box,
checkNvenc
} from '@grom13/adaptive-video-converter';
// Проверки перед конвертацией
try {
await checkFFmpeg();
await checkMP4Box();
const hasNvenc = await checkNvenc();
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
useNvenc: hasNvenc // Явное указание
});
console.log('Успешно!', result.manifestPath);
} catch (error) {
console.error('Ошибка:', error.message);
}
```
### Последовательное кодирование (без параллелизма)
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
parallel: false // Медленнее, но меньше нагрузка
});
```
### С кастомными профилями (объектами)
```typescript
import type { VideoProfile } from '@grom13/adaptive-video-converter';
const customProfiles: VideoProfile[] = [
{
name: '720p',
width: 1280,
height: 720,
videoBitrate: '2500k',
audioBitrate: '128k',
fps: 30
},
{
name: '1080p',
width: 1920,
height: 1080,
videoBitrate: '5000k',
audioBitrate: '192k',
fps: 30
}
];
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
profiles: customProfiles
});
```
## Обработка ошибок
```typescript
try {
const result = await convertToDash({
input: './video.mp4',
outputDir: './output'
});
console.log('✅ Успешно');
} catch (error) {
if (error.message.includes('FFmpeg not found')) {
console.error('FFmpeg не установлен');
} else if (error.message.includes('MP4Box not found')) {
console.error('MP4Box не установлен');
} else if (error.message.includes('File not found')) {
console.error('Входной файл не найден');
} else {
console.error('Ошибка конвертации:', error.message);
}
}
```
## Поведение по умолчанию
Если не указаны параметры:
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output'
});
```
Эквивалентно:
```typescript
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
segmentDuration: 2,
codec: 'dual',
format: 'both',
useNvenc: true, // если доступен
generateThumbnails: true,
generatePoster: true,
posterTimecode: '00:00:01',
parallel: true,
customProfiles: автовыбор на основе исходного видео
});
```
## Автовыбор профилей
Если `profiles` и `customProfiles` не указаны:
| Исходное разрешение | Выбранные профили |
|---------------------|-------------------|
| ≤ 720p | 360p, 480p, 720p |
| 1080p | 360p, 720p, 1080p |
| 1440p | 720p, 1080p, 1440p |
| 2160p (4K) | 1080p, 1440p, 2160p |
FPS профилей соответствует исходному видео (максимум 120fps).
## Структура вывода
После вызова `convertToDash()` создается следующая структура:
```
output/
└── video/
├── manifest.mpd # DASH манифест
├── master.m3u8 # HLS мастер-плейлист (если format='hls' или 'both')
├── 720p-h264/ # Сегменты профиля
│ ├── 720p-h264_init.mp4
│ ├── 720p-h264_1.m4s
│ └── ...
├── 720p-av1/
├── 1080p-h264/
├── 1080p-av1/
├── thumbnails.jpg # Спрайт превью
├── thumbnails.vtt # WebVTT метки
├── poster.jpg # Постер
└── conversion.log # Лог конвертации
```
## См. также
- [Утилиты](/api/utilities) — Вспомогательные функции
- [Профили](/api/profiles) — Работа с профилями
- [Типы](/api/types) — Все TypeScript типы

236
docs/api/index.md Normal file
View File

@@ -0,0 +1,236 @@
# API Библиотеки
Adaptive Video Converter можно использовать программно в ваших Node.js/TypeScript проектах.
## Установка
```bash
npm install @grom13/adaptive-video-converter
```
## Быстрый старт
```typescript
import { convertToDash } from '@grom13/adaptive-video-converter';
const result = await convertToDash({
inputPath: './video.mp4',
outputDir: './output'
});
console.log('Готово!', result.manifestPath);
```
## Основные экспорты
### Функции
- [`convertToDash()`](/api/convert) — Главная функция конвертации
- [Утилиты](/api/utilities) — Вспомогательные функции (checkFFmpeg, getVideoMetadata и др.)
- [Профили](/api/profiles) — Работа с профилями качества
### TypeScript типы
- [Типы](/api/types) — Все доступные типы и интерфейсы
## Структура API
```typescript
// Основная функция
export { convertToDash } from './core/converter';
// Утилиты
export {
checkFFmpeg,
checkMP4Box,
checkNvenc,
checkAV1Support,
getVideoMetadata,
selectAudioBitrate
} from './utils';
// Профили
export {
DEFAULT_PROFILES,
selectProfiles
} from './config/profiles';
// Типы
export type {
DashConvertOptions,
DashConvertResult,
VideoProfile,
ThumbnailConfig,
ConversionProgress,
VideoMetadata,
VideoOptimizations,
CodecType
} from './types';
```
## Примеры использования
### Базовая конвертация
```typescript
import { convertToDash } from '@grom13/adaptive-video-converter';
await convertToDash({
inputPath: './video.mp4',
outputDir: './output'
});
```
### С кастомными профилями
```typescript
await convertToDash({
inputPath: './video.mp4',
outputDir: './output',
customProfiles: ['720', '1080', '1440']
});
```
### С обработкой прогресса
```typescript
await convertToDash({
inputPath: './video.mp4',
outputDir: './output',
onProgress: (progress) => {
console.log(`${progress.percent}% - ${progress.stage}`);
console.log(`ETA: ${progress.eta}s`);
}
});
```
### Выбор кодека и формата
```typescript
await convertToDash({
inputPath: './video.mp4',
outputDir: './output',
codecType: 'dual', // 'h264' | 'av1' | 'dual'
format: 'both' // 'dash' | 'hls' | 'both'
});
```
### С проверкой системы
```typescript
import {
convertToDash,
checkFFmpeg,
checkNvenc
} from '@grom13/adaptive-video-converter';
// Проверка перед конвертацией
try {
await checkFFmpeg();
const hasNvenc = await checkNvenc();
console.log('NVENC:', hasNvenc ? 'доступен' : 'недоступен');
await convertToDash({
inputPath: './video.mp4',
outputDir: './output'
});
} catch (error) {
console.error('Ошибка:', error.message);
}
```
### С анализом исходного видео
```typescript
import {
getVideoMetadata,
convertToDash
} from '@grom13/adaptive-video-converter';
// Получить метаданные
const metadata = await getVideoMetadata('./video.mp4');
console.log('Разрешение:', `${metadata.width}×${metadata.height}`);
console.log('FPS:', metadata.fps);
console.log('Длительность:', metadata.duration, 'сек');
// Конвертация с учетом метаданных
await convertToDash({
inputPath: './video.mp4',
outputDir: './output',
customProfiles: metadata.height >= 1080
? ['720', '1080', '1440']
: ['360', '720']
});
```
## Обработка ошибок
```typescript
import { convertToDash } from '@grom13/adaptive-video-converter';
try {
const result = await convertToDash({
inputPath: './video.mp4',
outputDir: './output'
});
console.log('✅ Успешно:', result.manifestPath);
} catch (error) {
if (error.message.includes('FFmpeg not found')) {
console.error('❌ FFmpeg не установлен');
} else if (error.message.includes('MP4Box not found')) {
console.error('❌ MP4Box не установлен');
} else {
console.error('❌ Ошибка:', error.message);
}
}
```
## Интеграция в Express
```typescript
import express from 'express';
import multer from 'multer';
import { convertToDash } from '@grom13/adaptive-video-converter';
import { promises as fs } from 'fs';
const app = express();
const upload = multer({ dest: 'uploads/' });
app.post('/convert', upload.single('video'), async (req, res) => {
try {
const result = await convertToDash({
inputPath: req.file.path,
outputDir: './public/videos',
onProgress: (progress) => {
// Можно отправлять через WebSocket
console.log(`${progress.percent}%`);
}
});
// Удалить временный файл
await fs.unlink(req.file.path);
res.json({
success: true,
manifestPath: result.manifestPath
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.listen(3000);
```
## Следующие шаги
- [convertToDash()](/api/convert) — Подробная документация основной функции
- [Утилиты](/api/utilities) — Вспомогательные функции
- [Профили](/api/profiles) — Работа с профилями качества
- [Типы](/api/types) — TypeScript типы и интерфейсы

316
docs/api/profiles.md Normal file
View File

@@ -0,0 +1,316 @@
# Профили качества
Работа с профилями качества видео (разрешения, битрейты, FPS).
## DEFAULT_PROFILES
Массив дефолтных профилей качества.
**Сигнатура:**
```typescript
const DEFAULT_PROFILES: VideoProfile[]
```
**Содержимое:**
| Профиль | Разрешение | Видео битрейт | Аудио битрейт | FPS |
|---------|------------|---------------|---------------|-----|
| 360p | 640×360 | 800k | 96k | 30 |
| 480p | 854×480 | 1400k | 128k | 30 |
| 720p | 1280×720 | 2500k | 128k | 30 |
| 1080p | 1920×1080 | 5000k | 192k | 30 |
| 1440p | 2560×1440 | 8000k | 192k | 30 |
| 2160p (4K) | 3840×2160 | 16000k | 192k | 30 |
**Пример:**
```typescript
import { DEFAULT_PROFILES } from '@grom13/adaptive-video-converter';
console.log('Доступные профили:', DEFAULT_PROFILES.length);
DEFAULT_PROFILES.forEach(profile => {
console.log(`${profile.name}: ${profile.width}×${profile.height} @ ${profile.videoBitrate}`);
});
```
---
## selectProfiles()
Автоматический выбор профилей на основе метаданных исходного видео.
**Сигнатура:**
```typescript
function selectProfiles(
metadata: VideoMetadata,
customProfiles?: string[]
): VideoProfile[]
```
**Параметры:**
- `metadata` — Метаданные исходного видео (из `getVideoMetadata()`)
- `customProfiles` — Опциональные кастомные профили как строки
**Возвращает:** Массив выбранных профилей
**Логика автовыбора:**
| Исходное разрешение | Выбранные профили |
|---------------------|-------------------|
| ≤ 720p | 360p, 480p, 720p |
| 1080p | 360p, 720p, 1080p |
| 1440p | 720p, 1080p, 1440p |
| 2160p (4K) | 1080p, 1440p, 2160p |
**Особенности:**
- FPS профилей соответствует исходному видео (до 120fps max)
- Битрейты рассчитываются автоматически по формуле BPP (Bits Per Pixel)
- Создаются варианты с высоким FPS если исходное видео поддерживает
**Примеры:**
### Автовыбор профилей
```typescript
import {
getVideoMetadata,
selectProfiles
} from '@grom13/adaptive-video-converter';
const metadata = await getVideoMetadata('./video.mp4');
const profiles = selectProfiles(metadata);
console.log('Выбранные профили:');
profiles.forEach(p => {
console.log(`- ${p.name}: ${p.width}×${p.height} @ ${p.fps}fps, ${p.videoBitrate}`);
});
```
### С кастомными профилями
```typescript
import {
getVideoMetadata,
selectProfiles
} from '@grom13/adaptive-video-converter';
const metadata = await getVideoMetadata('./video.mp4');
// Парсинг кастомных профилей
const profiles = selectProfiles(metadata, ['720', '1080', '1440']);
// Профили будут созданы на основе исходного FPS
```
### С высоким FPS
```typescript
import {
getVideoMetadata,
selectProfiles
} from '@grom13/adaptive-video-converter';
const metadata = await getVideoMetadata('./gameplay.mp4');
// Если исходное видео 60fps, создаст профили:
// 720p@60, 1080p@60, 1440p@60
const profiles = selectProfiles(metadata, ['720@60', '1080@60', '1440@60']);
```
---
## VideoProfile интерфейс
```typescript
interface VideoProfile {
name: string; // Название (например, "1080p", "720p@60")
width: number; // Ширина в пикселях
height: number; // Высота в пикселях
videoBitrate: string; // Видео битрейт (например, "5000k")
audioBitrate: string; // Аудио битрейт (например, "128k")
fps: number; // Кадров в секунду
}
```
---
## Создание кастомных профилей
### Вручную
```typescript
import type { VideoProfile } from '@grom13/adaptive-video-converter';
import { convertToDash } from '@grom13/adaptive-video-converter';
const myProfiles: VideoProfile[] = [
{
name: '720p-high',
width: 1280,
height: 720,
videoBitrate: '3500k', // Выше стандартного
audioBitrate: '192k',
fps: 30
},
{
name: '1080p-ultra',
width: 1920,
height: 1080,
videoBitrate: '8000k', // Выше стандартного
audioBitrate: '256k',
fps: 60
}
];
await convertToDash({
input: './video.mp4',
outputDir: './output',
profiles: myProfiles
});
```
### С расчетом битрейта
```typescript
import type { VideoProfile } from '@grom13/adaptive-video-converter';
// BPP (Bits Per Pixel) формула
function calculateBitrate(
width: number,
height: number,
fps: number,
bpp: number = 0.1 // По умолчанию 0.1
): string {
const bitrate = Math.round(width * height * fps * bpp / 1000);
return `${bitrate}k`;
}
const profile: VideoProfile = {
name: '1080p60',
width: 1920,
height: 1080,
videoBitrate: calculateBitrate(1920, 1080, 60, 0.1), // ~12000k
audioBitrate: '192k',
fps: 60
};
```
---
## Форматы строк для customProfiles
### Базовый формат
```
<resolution>[@<fps>]
```
**Примеры:**
- `'360'` → 360p @ 30fps
- `'720'` → 720p @ 30fps
- `'1080'` → 1080p @ 30fps
### С указанием FPS
```
<resolution>@<fps>
```
**Примеры:**
- `'720@60'` → 720p @ 60fps
- `'1080@60'` → 1080p @ 60fps
- `'1440@120'` → 1440p @ 120fps
### Комбинации
```typescript
const profiles = ['360', '720@30', '1080@60', '1440@120'];
```
---
## Рекомендации по битрейтам
### Стандартное качество (BPP ~0.1)
| Профиль | Битрейт |
|---------|---------|
| 360p @ 30fps | 800k |
| 480p @ 30fps | 1400k |
| 720p @ 30fps | 2500k |
| 1080p @ 30fps | 5000k |
| 1440p @ 30fps | 8000k |
| 2160p @ 30fps | 16000k |
### Высокое качество (BPP ~0.15)
| Профиль | Битрейт |
|---------|---------|
| 720p @ 30fps | 3800k |
| 1080p @ 30fps | 7500k |
| 1440p @ 30fps | 12000k |
| 2160p @ 30fps | 24000k |
### Высокий FPS
Для 60fps — умножить на 2
Для 120fps — умножить на 4
**Примеры:**
- 1080p @ 60fps: 5000k × 2 = 10000k
- 1440p @ 120fps: 8000k × 4 = 32000k
---
## Валидация профилей
При использовании `selectProfiles()` или `convertToDash()` автоматически происходит:
1. **Проверка разрешения** — не превышает исходное
2. **Проверка FPS** — не превышает исходный
3. **Ограничение FPS** — максимум 120fps
4. **Расчет битрейтов** — автоматически если не указаны
**Пример:**
```typescript
// Если исходное видео 1080p @ 30fps
const profiles = selectProfiles(metadata, ['720@60', '1080', '1440']);
// Результат:
// - 720p @ 30fps (FPS понижен до исходного)
// - 1080p @ 30fps
// - 1440p → ПРОПУЩЕН (разрешение выше исходного)
```
---
## Интеграция с convertToDash()
```typescript
import {
getVideoMetadata,
selectProfiles,
convertToDash
} from '@grom13/adaptive-video-converter';
// 1. Получить метаданные
const metadata = await getVideoMetadata('./video.mp4');
// 2. Выбрать профили
const profiles = selectProfiles(metadata, ['720', '1080', '1440']);
// 3. Конвертация
await convertToDash({
input: './video.mp4',
outputDir: './output',
profiles // Использовать выбранные профили
});
```
---
## См. также
- [convertToDash()](/api/convert) — Главная функция
- [Утилиты](/api/utilities) — getVideoMetadata()
- [Типы](/api/types) — VideoProfile тип

473
docs/api/types.md Normal file
View File

@@ -0,0 +1,473 @@
# TypeScript типы
Все доступные TypeScript типы и интерфейсы для работы с библиотекой.
## Основные типы
### `CodecType`
Тип видео кодека для кодирования.
```typescript
type CodecType = 'av1' | 'h264' | 'dual';
```
**Значения:**
- `'av1'` — Только AV1
- `'h264'` — Только H.264
- `'dual'`Оба кодека (H.264 + AV1)
---
### `StreamingFormat`
Тип формата стриминга.
```typescript
type StreamingFormat = 'dash' | 'hls' | 'both';
```
**Значения:**
- `'dash'` — Только DASH
- `'hls'` — Только HLS
- `'both'`Оба формата
---
## Интерфейсы опций
### `DashConvertOptions`
Конфигурация для `convertToDash()`.
```typescript
interface DashConvertOptions {
/** Входной видео файл */
input: string;
/** Выходная директория */
outputDir: string;
/** Длительность сегмента в секундах (по умолчанию: 2) */
segmentDuration?: number;
/** Профили качества */
profiles?: VideoProfile[];
/** Кастомные профили как строки (например, ['720', '1080@60']) */
customProfiles?: string[];
/** Кодек: 'av1', 'h264' или 'dual' (по умолчанию: 'dual') */
codec?: CodecType;
/** Формат: 'dash', 'hls' или 'both' (по умолчанию: 'both') */
format?: StreamingFormat;
/** Использовать NVENC (авто-определение если undefined) */
useNvenc?: boolean;
/** Настройки качества (CQ/CRF значения) */
quality?: QualitySettings;
/** Генерировать превью-спрайт (по умолчанию: true) */
generateThumbnails?: boolean;
/** Конфигурация превью */
thumbnailConfig?: ThumbnailConfig;
/** Генерировать постер (по умолчанию: true) */
generatePoster?: boolean;
/** Таймкод постера в формате HH:MM:SS или секунды (по умолчанию: '00:00:01') */
posterTimecode?: string;
/** Параллельное кодирование (по умолчанию: true) */
parallel?: boolean;
/** Колбэк для прогресса */
onProgress?: (progress: ConversionProgress) => void;
}
```
---
### `DashConvertResult`
Результат выполнения `convertToDash()`.
```typescript
interface DashConvertResult {
/** Путь к DASH манифесту (manifest.mpd) */
manifestPath: string;
/** Путь к HLS мастер-плейлисту (master.m3u8), если format='hls' или 'both' */
hlsManifestPath?: string;
/** Пути к сегментам */
segments: string[];
/** Путь к спрайту превью */
thumbnailPath?: string;
/** Путь к постеру */
posterPath?: string;
}
```
---
### `VideoProfile`
Профиль качества видео.
```typescript
interface VideoProfile {
/** Название профиля (например, "1080p", "720p@60") */
name: string;
/** Ширина в пикселях */
width: number;
/** Высота в пикселях */
height: number;
/** Видео битрейт (например, "5000k") */
videoBitrate: string;
/** Аудио битрейт (например, "128k") */
audioBitrate: string;
/** Кадров в секунду */
fps: number;
}
```
---
### `ThumbnailConfig`
Конфигурация генерации превью-спрайтов.
```typescript
interface ThumbnailConfig {
/** Ширина превью в пикселях (по умолчанию: 160) */
width?: number;
/** Высота превью в пикселях (по умолчанию: 90) */
height?: number;
/** Интервал между превью в секундах (по умолчанию: 1) */
interval?: number;
/** Количество колонок в спрайте (по умолчанию: 10) */
columns?: number;
/** Количество строк в спрайте (по умолчанию: 10) */
rows?: number;
}
```
**По умолчанию:**
```typescript
{
width: 160,
height: 90,
interval: 1,
columns: 10,
rows: 10
}
```
---
### `ConversionProgress`
Информация о прогрессе конвертации.
```typescript
interface ConversionProgress {
/** Процент выполнения (0-100) */
percent: number;
/** Текущий этап (например, "encoding", "packaging") */
stage: string;
/** Текущий профиль (например, "1080p-h264") */
currentProfile?: string;
/** Оценка времени до завершения в секундах */
eta?: number;
/** Скорость кодирования (например, "2.5x") */
speed?: string;
}
```
---
### `VideoMetadata`
Метаданные видео файла.
```typescript
interface VideoMetadata {
/** Ширина в пикселях */
width: number;
/** Высота в пикселях */
height: number;
/** Кадров в секунду */
fps: number;
/** Длительность в секундах */
duration: number;
/** Видео битрейт в кбит/с */
videoBitrate: number;
/** Аудио битрейт в кбит/с */
audioBitrate: number;
/** Видео кодек (например, "h264", "vp9") */
codec: string;
/** Аудио кодек (например, "aac", "opus") */
audioCodec: string;
}
```
---
### `QualitySettings`
Настройки качества кодирования.
```typescript
interface QualitySettings {
/** Настройки для H.264 */
h264?: CodecQualitySettings;
/** Настройки для AV1 */
av1?: CodecQualitySettings;
}
```
---
### `CodecQualitySettings`
Настройки качества для одного кодека.
```typescript
interface CodecQualitySettings {
/** CQ (Constant Quality) для GPU кодеров (0-51, меньше = лучше) */
cq?: number;
/** CRF (Constant Rate Factor) для CPU кодеров
* - 0-51 для H.264
* - 0-63 для AV1
* Меньше = лучше качество
*/
crf?: number;
}
```
---
### `AV1Support`
Информация о доступных AV1 кодерах.
```typescript
interface AV1Support {
/** NVIDIA NVENC AV1 */
nvenc: boolean;
/** Intel Quick Sync Video AV1 */
qsv: boolean;
/** AMD AMF AV1 */
amf: boolean;
/** libsvtav1 (CPU) */
software: boolean;
}
```
---
## Примеры использования типов
### С полной типизацией
```typescript
import {
convertToDash,
type DashConvertOptions,
type DashConvertResult,
type VideoProfile,
type ConversionProgress
} from '@grom13/adaptive-video-converter';
// Кастомные профили
const profiles: VideoProfile[] = [
{
name: '720p',
width: 1280,
height: 720,
videoBitrate: '2500k',
audioBitrate: '128k',
fps: 30
},
{
name: '1080p',
width: 1920,
height: 1080,
videoBitrate: '5000k',
audioBitrate: '192k',
fps: 30
}
];
// Опции с типизацией
const options: DashConvertOptions = {
input: './video.mp4',
outputDir: './output',
profiles,
codec: 'dual',
format: 'both',
onProgress: (progress: ConversionProgress) => {
console.log(`${progress.percent}% - ${progress.stage}`);
}
};
// Результат с типизацией
const result: DashConvertResult = await convertToDash(options);
console.log('DASH:', result.manifestPath);
console.log('HLS:', result.hlsManifestPath);
```
### С partial типами
```typescript
import type { DashConvertOptions } from '@grom13/adaptive-video-converter';
// Функция-помощник с дефолтными значениями
function createOptions(
input: string,
overrides?: Partial<DashConvertOptions>
): DashConvertOptions {
return {
input,
outputDir: './output',
codec: 'dual',
format: 'both',
...overrides
};
}
// Использование
const options = createOptions('./video.mp4', {
customProfiles: ['720', '1080'],
generatePoster: false
});
```
### С дискриминирующими типами
```typescript
import type {
CodecType,
StreamingFormat
} from '@grom13/adaptive-video-converter';
// Функция с проверкой типов
function getEncoderName(codec: CodecType): string {
switch (codec) {
case 'h264':
return 'h264_nvenc';
case 'av1':
return 'av1_nvenc';
case 'dual':
return 'both';
default:
// TypeScript гарантирует что это невозможно
const _exhaustive: never = codec;
throw new Error(`Unknown codec: ${_exhaustive}`);
}
}
// Функция с проверкой формата
function getManifestExtension(format: StreamingFormat): string {
switch (format) {
case 'dash':
return '.mpd';
case 'hls':
return '.m3u8';
case 'both':
return '.mpd and .m3u8';
}
}
```
### С generic типами
```typescript
import type {
DashConvertOptions,
DashConvertResult
} from '@grom13/adaptive-video-converter';
// Generic функция для обработки результата
async function processConversion<T>(
options: DashConvertOptions,
transformer: (result: DashConvertResult) => T
): Promise<T> {
const result = await convertToDash(options);
return transformer(result);
}
// Использование
const urls = await processConversion(
{ input: './video.mp4', outputDir: './output' },
(result) => ({
dashUrl: `/videos/${result.manifestPath}`,
hlsUrl: `/videos/${result.hlsManifestPath}`
})
);
```
### Type guards
```typescript
import type { DashConvertResult } from '@grom13/adaptive-video-converter';
// Type guard для проверки HLS
function hasHLS(result: DashConvertResult): result is DashConvertResult & {
hlsManifestPath: string;
} {
return result.hlsManifestPath !== undefined;
}
// Использование
const result = await convertToDash({
input: './video.mp4',
outputDir: './output',
format: 'both'
});
if (hasHLS(result)) {
// TypeScript знает что hlsManifestPath существует
console.log('HLS:', result.hlsManifestPath);
}
```
---
## См. также
- [convertToDash()](/api/convert) — Использование типов в основной функции
- [Утилиты](/api/utilities) — Типы для утилит
- [Профили](/api/profiles) — VideoProfile тип

341
docs/api/utilities.md Normal file
View File

@@ -0,0 +1,341 @@
# Утилиты
Вспомогательные функции для работы с системой и метаданными видео.
## Проверка системы
### `checkFFmpeg()`
Проверяет наличие FFmpeg в системе.
**Сигнатура:**
```typescript
async function checkFFmpeg(): Promise<void>
```
**Возвращает:** `Promise<void>` — Успешно если FFmpeg найден
**Выбрасывает:** `Error` если FFmpeg не найден
**Пример:**
```typescript
import { checkFFmpeg } from '@grom13/adaptive-video-converter';
try {
await checkFFmpeg();
console.log('✅ FFmpeg установлен');
} catch (error) {
console.error('❌ FFmpeg не найден');
}
```
---
### `checkMP4Box()`
Проверяет наличие MP4Box (gpac) в системе.
**Сигнатура:**
```typescript
async function checkMP4Box(): Promise<void>
```
**Возвращает:** `Promise<void>`
**Выбрасывает:** `Error` если MP4Box не найден
**Пример:**
```typescript
import { checkMP4Box } from '@grom13/adaptive-video-converter';
try {
await checkMP4Box();
console.log('✅ MP4Box установлен');
} catch (error) {
console.error('❌ MP4Box не найден');
}
```
---
### `checkNvenc()`
Проверяет доступность NVIDIA NVENC для H.264.
**Сигнатура:**
```typescript
async function checkNvenc(): Promise<boolean>
```
**Возвращает:** `Promise<boolean>``true` если NVENC доступен
**Пример:**
```typescript
import { checkNvenc } from '@grom13/adaptive-video-converter';
const hasNvenc = await checkNvenc();
if (hasNvenc) {
console.log('✅ NVENC доступен - будет использовано GPU-ускорение');
} else {
console.log('⚠️ NVENC недоступен - будет использован CPU');
}
```
---
### `checkAV1Support()`
Проверяет доступность AV1 кодеров (GPU и CPU).
**Сигнатура:**
```typescript
interface AV1Support {
nvenc: boolean; // NVIDIA NVENC AV1
qsv: boolean; // Intel Quick Sync Video
amf: boolean; // AMD AMF
software: boolean; // libsvtav1 (CPU)
}
async function checkAV1Support(): Promise<AV1Support>
```
**Возвращает:** Объект с информацией о доступных AV1 кодерах
**Пример:**
```typescript
import { checkAV1Support } from '@grom13/adaptive-video-converter';
const av1Support = await checkAV1Support();
console.log('AV1 NVENC:', av1Support.nvenc);
console.log('AV1 QSV:', av1Support.qsv);
console.log('AV1 AMF:', av1Support.amf);
console.log('AV1 Software:', av1Support.software);
if (av1Support.nvenc) {
console.log('✅ Будет использован AV1 NVENC (GPU)');
} else if (av1Support.software) {
console.log('⚠️ Будет использован libsvtav1 (CPU)');
}
```
---
## Работа с метаданными
### `getVideoMetadata()`
Извлекает метаданные видео файла через ffprobe.
**Сигнатура:**
```typescript
interface VideoMetadata {
width: number; // Ширина в пикселях
height: number; // Высота в пикселях
fps: number; // Кадров в секунду
duration: number; // Длительность в секундах
videoBitrate: number; // Видео битрейт в кбит/с
audioBitrate: number; // Аудио битрейт в кбит/с
codec: string; // Кодек (например, "h264")
audioCodec: string; // Аудио кодек
}
async function getVideoMetadata(
filePath: string
): Promise<VideoMetadata>
```
**Параметры:**
- `filePath` — Путь к видео файлу
**Возвращает:** Объект с метаданными видео
**Пример:**
```typescript
import { getVideoMetadata } from '@grom13/adaptive-video-converter';
const metadata = await getVideoMetadata('./video.mp4');
console.log(`Разрешение: ${metadata.width}×${metadata.height}`);
console.log(`FPS: ${metadata.fps}`);
console.log(`Длительность: ${metadata.duration}с`);
console.log(`Видео битрейт: ${metadata.videoBitrate}кбит/с`);
console.log(`Аудио битрейт: ${metadata.audioBitrate}кбит/с`);
console.log(`Кодек: ${metadata.codec}`);
```
**Использование с convertToDash:**
```typescript
import {
getVideoMetadata,
convertToDash
} from '@grom13/adaptive-video-converter';
// Анализ перед конвертацией
const metadata = await getVideoMetadata('./video.mp4');
// Выбор профилей на основе исходного разрешения
const profiles = metadata.height >= 1080
? ['720', '1080', '1440']
: ['360', '720'];
await convertToDash({
input: './video.mp4',
outputDir: './output',
customProfiles: profiles
});
```
---
### `selectAudioBitrate()`
Выбирает оптимальный аудио битрейт на основе исходного.
**Сигнатура:**
```typescript
function selectAudioBitrate(
sourceAudioBitrate: number
): number
```
**Параметры:**
- `sourceAudioBitrate` — Исходный аудио битрейт в кбит/с
**Возвращает:** Оптимальный аудио битрейт в кбит/с
**Логика:**
- Если исходный ≥ 192 → 192
- Если исходный ≥ 128 → 128
- Иначе → 96
**Пример:**
```typescript
import {
getVideoMetadata,
selectAudioBitrate
} from '@grom13/adaptive-video-converter';
const metadata = await getVideoMetadata('./video.mp4');
const audioBitrate = selectAudioBitrate(metadata.audioBitrate);
console.log(`Исходный: ${metadata.audioBitrate}кбит/с`);
console.log(`Выбранный: ${audioBitrate}кбит/с`);
```
---
## Комплексная проверка системы
```typescript
import {
checkFFmpeg,
checkMP4Box,
checkNvenc,
checkAV1Support
} from '@grom13/adaptive-video-converter';
async function checkSystem() {
console.log('🔍 Проверка системы...\n');
// FFmpeg
try {
await checkFFmpeg();
console.log('✅ FFmpeg найден');
} catch (error) {
console.error('❌ FFmpeg не найден');
process.exit(1);
}
// MP4Box
try {
await checkMP4Box();
console.log('✅ MP4Box найден');
} catch (error) {
console.error('❌ MP4Box не найден');
process.exit(1);
}
// NVENC
const hasNvenc = await checkNvenc();
if (hasNvenc) {
console.log('✅ NVENC H.264 доступен');
} else {
console.log('⚠️ NVENC недоступен, будет использован CPU');
}
// AV1
const av1 = await checkAV1Support();
if (av1.nvenc) {
console.log('✅ NVENC AV1 доступен');
} else if (av1.qsv) {
console.log('✅ Quick Sync AV1 доступен');
} else if (av1.amf) {
console.log('✅ AMF AV1 доступен');
} else if (av1.software) {
console.log('⚠️ Только CPU AV1 (libsvtav1)');
} else {
console.log('⚠️ AV1 недоступен');
}
console.log('\n✅ Система готова к работе');
}
await checkSystem();
```
---
## Интеграция с Express
```typescript
import express from 'express';
import {
checkFFmpeg,
checkMP4Box,
checkNvenc,
getVideoMetadata,
convertToDash
} from '@grom13/adaptive-video-converter';
const app = express();
// Проверка при старте сервера
async function startup() {
try {
await checkFFmpeg();
await checkMP4Box();
const hasNvenc = await checkNvenc();
console.log('Server ready. NVENC:', hasNvenc);
app.listen(3000, () => {
console.log('Listening on port 3000');
});
} catch (error) {
console.error('Startup error:', error.message);
process.exit(1);
}
}
// Эндпоинт для получения метаданных
app.get('/video/metadata', async (req, res) => {
try {
const metadata = await getVideoMetadata(req.query.path);
res.json(metadata);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
startup();
```
---
## См. также
- [convertToDash()](/api/convert) — Главная функция конвертации
- [Профили](/api/profiles) — Работа с профилями
- [Типы](/api/types) — TypeScript типы