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 типы
|