Files

368 lines
9.8 KiB
Markdown
Raw Permalink Normal View History

2025-12-03 22:46:15 +03:00
# 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 типы