342 lines
8.5 KiB
Markdown
342 lines
8.5 KiB
Markdown
# Утилиты
|
||
|
||
Вспомогательные функции для работы с системой и метаданными видео.
|
||
|
||
## Проверка системы
|
||
|
||
### `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 типы
|