add vitepress
This commit is contained in:
367
docs/api/convert.md
Normal file
367
docs/api/convert.md
Normal 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
236
docs/api/index.md
Normal 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
316
docs/api/profiles.md
Normal 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
473
docs/api/types.md
Normal 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
341
docs/api/utilities.md
Normal 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 типы
|
||||
Reference in New Issue
Block a user