368 lines
9.8 KiB
Markdown
368 lines
9.8 KiB
Markdown
# 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 типы
|