322 lines
10 KiB
Markdown
322 lines
10 KiB
Markdown
|
|
# DASH Video Converter 🎬
|
|||
|
|
|
|||
|
|
Быстрая библиотека для конвертации видео в формат DASH с поддержкой аппаратного ускорения NVIDIA NVENC и генерацией превью спрайтов.
|
|||
|
|
|
|||
|
|
## Возможности
|
|||
|
|
|
|||
|
|
- ⚡ **Аппаратное ускорение NVENC** - максимальная скорость конвертации на GPU
|
|||
|
|
- 🎯 **Адаптивный стриминг** - автоматическое создание нескольких битрейтов
|
|||
|
|
- 🖼️ **Превью спрайты** - генерация thumbnail спрайтов с VTT файлами
|
|||
|
|
- 🔄 **Параллельная обработка** - одновременное кодирование нескольких профилей
|
|||
|
|
- 📊 **Прогресс в реальном времени** - отслеживание процесса конвертации
|
|||
|
|
- 🎬 **Фрагменты 2 секунды** - оптимальная сегментация для потокового вещания
|
|||
|
|
|
|||
|
|
## Требования
|
|||
|
|
|
|||
|
|
- **Bun** >= 1.0.0
|
|||
|
|
- **FFmpeg** с поддержкой DASH (libavformat)
|
|||
|
|
- **NVIDIA GPU** (опционально, для NVENC)
|
|||
|
|
|
|||
|
|
### Установка FFmpeg
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Ubuntu/Debian
|
|||
|
|
sudo apt install ffmpeg
|
|||
|
|
|
|||
|
|
# Arch Linux
|
|||
|
|
sudo pacman -S ffmpeg
|
|||
|
|
|
|||
|
|
# macOS
|
|||
|
|
brew install ffmpeg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Установка
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
bun install
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Быстрый старт
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { convertToDash } from '@dash-converter/core';
|
|||
|
|
|
|||
|
|
const result = await convertToDash({
|
|||
|
|
input: './video.mp4',
|
|||
|
|
outputDir: './output',
|
|||
|
|
segmentDuration: 2,
|
|||
|
|
useNvenc: true, // Использовать NVENC если доступен
|
|||
|
|
generateThumbnails: true,
|
|||
|
|
onProgress: (progress) => {
|
|||
|
|
console.log(`${progress.stage}: ${progress.percent}%`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log('Готово!', result.manifestPath);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## API
|
|||
|
|
|
|||
|
|
### `convertToDash(options: DashConvertOptions): Promise<DashConvertResult>`
|
|||
|
|
|
|||
|
|
Основная функция конвертации видео в DASH формат.
|
|||
|
|
|
|||
|
|
#### Опции
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface DashConvertOptions {
|
|||
|
|
// Путь к входному видео файлу (обязательно)
|
|||
|
|
input: string;
|
|||
|
|
|
|||
|
|
// Директория для выходных файлов (обязательно)
|
|||
|
|
outputDir: string;
|
|||
|
|
|
|||
|
|
// Длительность сегмента в секундах (по умолчанию: 2)
|
|||
|
|
segmentDuration?: number;
|
|||
|
|
|
|||
|
|
// Профили качества видео (авто-определение если не указано)
|
|||
|
|
profiles?: VideoProfile[];
|
|||
|
|
|
|||
|
|
// Использовать NVENC ускорение (авто-определение если не указано)
|
|||
|
|
useNvenc?: boolean;
|
|||
|
|
|
|||
|
|
// Генерировать превью спрайты (по умолчанию: true)
|
|||
|
|
generateThumbnails?: boolean;
|
|||
|
|
|
|||
|
|
// Настройки превью спрайтов
|
|||
|
|
thumbnailConfig?: ThumbnailConfig;
|
|||
|
|
|
|||
|
|
// Параллельное кодирование профилей (по умолчанию: true)
|
|||
|
|
parallel?: boolean;
|
|||
|
|
|
|||
|
|
// Коллбэк для отслеживания прогресса
|
|||
|
|
onProgress?: (progress: ConversionProgress) => void;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Профили видео
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface VideoProfile {
|
|||
|
|
name: string; // Название профиля (например, "1080p")
|
|||
|
|
width: number; // Ширина в пикселях
|
|||
|
|
height: number; // Высота в пикселях
|
|||
|
|
videoBitrate: string; // Битрейт видео (например, "5000k")
|
|||
|
|
audioBitrate: string; // Битрейт аудио (например, "256k")
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Профили по умолчанию:**
|
|||
|
|
- 1080p: 1920x1080, 5000k видео, 256k аудио
|
|||
|
|
- 720p: 1280x720, 3000k видео, 256k аудио
|
|||
|
|
- 480p: 854x480, 1500k видео, 256k аудио
|
|||
|
|
- 360p: 640x360, 800k видео, 256k аудио
|
|||
|
|
|
|||
|
|
#### Настройки превью
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface ThumbnailConfig {
|
|||
|
|
width?: number; // Ширина миниатюры (по умолчанию: 160)
|
|||
|
|
height?: number; // Высота миниатюры (по умолчанию: 90)
|
|||
|
|
interval?: number; // Интервал между превью в секундах (по умолчанию: 10)
|
|||
|
|
columns?: number; // Количество столбцов в спрайте (по умолчанию: 10)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Результат
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface DashConvertResult {
|
|||
|
|
manifestPath: string; // Путь к MPD манифесту
|
|||
|
|
videoPaths: string[]; // Пути к видео сегментам
|
|||
|
|
thumbnailSpritePath?: string; // Путь к спрайту превью
|
|||
|
|
thumbnailVttPath?: string; // Путь к VTT файлу превью
|
|||
|
|
duration: number; // Длительность видео в секундах
|
|||
|
|
profiles: VideoProfile[]; // Использованные профили
|
|||
|
|
usedNvenc: boolean; // Использовался ли NVENC
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Примеры использования
|
|||
|
|
|
|||
|
|
### Базовое использование
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { convertToDash } from '@dash-converter/core';
|
|||
|
|
|
|||
|
|
const result = await convertToDash({
|
|||
|
|
input: './my-video.mp4',
|
|||
|
|
outputDir: './dash-output'
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### С кастомными профилями
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const result = await convertToDash({
|
|||
|
|
input: './my-video.mp4',
|
|||
|
|
outputDir: './dash-output',
|
|||
|
|
profiles: [
|
|||
|
|
{
|
|||
|
|
name: '4k',
|
|||
|
|
width: 3840,
|
|||
|
|
height: 2160,
|
|||
|
|
videoBitrate: '15000k',
|
|||
|
|
audioBitrate: '256k'
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: '1080p',
|
|||
|
|
width: 1920,
|
|||
|
|
height: 1080,
|
|||
|
|
videoBitrate: '5000k',
|
|||
|
|
audioBitrate: '256k'
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### С отслеживанием прогресса
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const result = await convertToDash({
|
|||
|
|
input: './my-video.mp4',
|
|||
|
|
outputDir: './dash-output',
|
|||
|
|
onProgress: (progress) => {
|
|||
|
|
console.log(`
|
|||
|
|
Стадия: ${progress.stage}
|
|||
|
|
Прогресс: ${progress.percent.toFixed(2)}%
|
|||
|
|
Профиль: ${progress.currentProfile || 'N/A'}
|
|||
|
|
`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Без GPU ускорения (только CPU)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const result = await convertToDash({
|
|||
|
|
input: './my-video.mp4',
|
|||
|
|
outputDir: './dash-output',
|
|||
|
|
useNvenc: false // Принудительно использовать CPU
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Кастомные настройки превью
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const result = await convertToDash({
|
|||
|
|
input: './my-video.mp4',
|
|||
|
|
outputDir: './dash-output',
|
|||
|
|
thumbnailConfig: {
|
|||
|
|
width: 320,
|
|||
|
|
height: 180,
|
|||
|
|
interval: 5, // Каждые 5 секунд
|
|||
|
|
columns: 5 // 5 превью в ряд
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Запуск примера
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Конвертировать видео
|
|||
|
|
bun run example examples/basic.ts ./input.mp4 ./output
|
|||
|
|
|
|||
|
|
# Или через npm script
|
|||
|
|
bun run example
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Утилиты
|
|||
|
|
|
|||
|
|
### Проверка системы
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { checkFFmpeg, checkNvenc } from '@dash-converter/core';
|
|||
|
|
|
|||
|
|
const hasFFmpeg = await checkFFmpeg();
|
|||
|
|
const hasNvenc = await checkNvenc();
|
|||
|
|
|
|||
|
|
console.log('FFmpeg:', hasFFmpeg ? '✓' : '✗');
|
|||
|
|
console.log('NVENC:', hasNvenc ? '✓' : '✗');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Получение метаданных видео
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { getVideoMetadata } from '@dash-converter/core';
|
|||
|
|
|
|||
|
|
const metadata = await getVideoMetadata('./video.mp4');
|
|||
|
|
console.log(`
|
|||
|
|
Разрешение: ${metadata.width}x${metadata.height}
|
|||
|
|
Длительность: ${metadata.duration}s
|
|||
|
|
FPS: ${metadata.fps}
|
|||
|
|
Кодек: ${metadata.codec}
|
|||
|
|
`);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Выбор профилей
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { selectProfiles } from '@dash-converter/core';
|
|||
|
|
|
|||
|
|
// Автоматический выбор профилей на основе разрешения
|
|||
|
|
const profiles = selectProfiles(1920, 1080);
|
|||
|
|
console.log('Доступные профили:', profiles.map(p => p.name));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Производительность
|
|||
|
|
|
|||
|
|
### Сравнение NVENC vs CPU
|
|||
|
|
|
|||
|
|
Тестовое видео: 1080p, 60fps, 2 минуты
|
|||
|
|
|
|||
|
|
| Метод | Время конвертации | Ускорение |
|
|||
|
|
|-------|-------------------|-----------|
|
|||
|
|
| CPU (libx264, preset medium) | ~8 минут | 1x |
|
|||
|
|
| NVENC (preset p4) | ~45 секунд | **10.6x** |
|
|||
|
|
|
|||
|
|
### Советы по оптимизации
|
|||
|
|
|
|||
|
|
1. **Используйте NVENC** - самое большое ускорение
|
|||
|
|
2. **Параллельное кодирование** - включено по умолчанию
|
|||
|
|
3. **Оптимальная длина сегментов** - 2-4 секунды для баланса качества/размера
|
|||
|
|
4. **Профили по необходимости** - не генерируйте лишние разрешения
|
|||
|
|
|
|||
|
|
## Структура выходных файлов
|
|||
|
|
|
|||
|
|
Библиотека автоматически создает структурированную папку с именем входного видеофайла:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
output/
|
|||
|
|
└── video-name/ # Имя входного файла
|
|||
|
|
├── manifest.mpd # Главный DASH манифест
|
|||
|
|
├── thumbnails.jpg # Спрайт превью
|
|||
|
|
├── thumbnails.vtt # WebVTT для превью
|
|||
|
|
├── audio/ # Общий аудио трек
|
|||
|
|
│ ├── audio_init.m4s # Инициализационный сегмент
|
|||
|
|
│ ├── audio_1.m4s # Аудио сегмент #1
|
|||
|
|
│ ├── audio_2.m4s # Аудио сегмент #2
|
|||
|
|
│ └── ...
|
|||
|
|
├── 1080p/ # Папка для профиля 1080p
|
|||
|
|
│ ├── 1080p_init.m4s # Инициализационный сегмент
|
|||
|
|
│ ├── 1080p_1.m4s # Видео сегмент #1
|
|||
|
|
│ ├── 1080p_2.m4s # Видео сегмент #2
|
|||
|
|
│ └── ...
|
|||
|
|
├── 720p/ # Папка для профиля 720p
|
|||
|
|
│ ├── 720p_init.m4s
|
|||
|
|
│ ├── 720p_1.m4s
|
|||
|
|
│ └── ...
|
|||
|
|
├── 480p/ # Папка для профиля 480p
|
|||
|
|
│ └── ...
|
|||
|
|
└── 360p/ # Папка для профиля 360p
|
|||
|
|
└── ...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Лицензия
|
|||
|
|
|
|||
|
|
MIT
|
|||
|
|
|
|||
|
|
## Автор
|
|||
|
|
|
|||
|
|
Создано с ❤️ на Bun + TypeScript
|