ffmpeg-stream-manager
Version:
🎥 A powerful TypeScript library for managing multiple simultaneous RTMP streams using FFmpeg. Perfect for streaming to platforms like YouTube Live, Twitch, and others.
1,073 lines (889 loc) • 28.3 kB
Markdown
# 🎥 FFmpegStreamManager
[](https://badge.fury.io/js/ffmpeg-stream-manager)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
> Uma biblioteca poderosa em TypeScript para gerenciar múltiplas transmissões RTMP simultâneas usando FFmpeg. Ideal para streaming para plataformas como YouTube Live, Twitch e outras que suportam RTMP.
## 📖 Índice
- [Características](#-características)
- [Instalação](#-instalação)
- [Uso Rápido](#-uso-rápido)
- [API Completa](#-api-completa)
- [Exemplos Detalhados](#-exemplos-detalhados)
- [Configurações](#-configurações)
- [Eventos](#-eventos)
- [Tratamento de Erros](#-tratamento-de-erros)
- [Logs e Monitoramento](#-logs-e-monitoramento)
- [Tipos TypeScript](#-tipos-typescript)
- [Configurações Pré-definidas](#-configurações-pré-definidas)
- [Requisitos do Sistema](#-requisitos-do-sistema)
- [FAQ](#-faq)
- [Contribuição](#-contribuição)
- [Licença](#-licença)
## 🚀 Características
### ✨ Funcionalidades Principais
- **🔄 Múltiplas transmissões simultâneas**: Gerencie até N streams em paralelo
- **🎯 Suporte completo ao YouTube Live**: Configurações otimizadas para RTMP
- **📹 Tipos de entrada flexíveis**:
- Arquivos de vídeo (.mp4, .avi, .mov, .mkv, etc.) - **ÚNICO ou MÚLTIPLOS**
- Arquivos de áudio (.mp3, .wav, .aac, .flac) com imagem estática - **PLAYLIST**
- Geradores FFmpeg (testsrc, anullsrc, color, etc.)
- **🎵 Playlists automáticas**: Múltiplos arquivos em sequência com loop infinito
- **♾️ Loop infinito**: Reinicialização automática quando o arquivo termina
- **🔄 Reinício automático**: Recuperação automática de falhas
- **⚙️ Gerenciamento completo**: Iniciar, parar, pausar, retomar e atualizar configurações
- **📊 Logs detalhados**: Captura completa de stdout/stderr do FFmpeg
- **🛡️ TypeScript 100%**: Tipagem forte e segura
- **🔍 Monitoramento em tempo real**: Status, uptime, logs por stream
- **🚫 Sem dependências web**: Biblioteca pura para uso interno
### 🎛️ Controles Avançados
- Configuração dinâmica de bitrate, resolução e codec
- Eventos em tempo real para todos os estados do stream
- Filtros de log por stream ID e nível
- Configurações otimizadas para diferentes plataformas
- Gerenciamento automático de recursos
## 📦 Instalação
```bash
npm install ffmpeg-stream-manager
```
**Pré-requisitos:**
- **Node.js**: 16.0 ou superior
- **FFmpeg**: 4.0 ou superior instalado no sistema
- **TypeScript**: 4.5+ (para desenvolvimento)
### Instalação do FFmpeg
**Ubuntu/Debian:**
```bash
sudo apt update && sudo apt install ffmpeg
```
**CentOS/RHEL/Fedora:**
```bash
sudo dnf install ffmpeg
```
**macOS:**
```bash
brew install ffmpeg
```
**Windows:**
- Baixe de [https://ffmpeg.org/download.html](https://ffmpeg.org/download.html)
- Adicione ao PATH do sistema
## 🔧 Uso Rápido
```typescript
import { FFmpegStreamManager } from 'ffmpeg-stream-manager';
async function exemploRapido() {
// Criar gerenciador
const manager = new FFmpegStreamManager({
maxConcurrentStreams: 5,
autoRestart: true,
logLevel: 'info'
});
// Configurar eventos
manager.on('stream-started', (streamId) => {
console.log(`✅ Stream iniciado: ${streamId}`);
});
manager.on('stream-error', (streamId, error) => {
console.error(`❌ Erro: ${error.message}`);
});
try {
// Iniciar stream para YouTube
const streamId = await manager.startYouTubeStream(
{
inputType: 'video',
inputPath: '/caminho/para/video.mp4',
staticImagePath: undefined,
loop: true,
...FFmpegStreamManager.getDefaultConfigs().youTube1080p
},
{
streamKey: 'sua-chave-youtube',
server: undefined // usa servidor padrão
}
);
console.log(`🎥 Stream ativo: ${streamId}`);
// Monitorar status
const status = manager.getStreamStatus(streamId);
console.log(`Status: ${status.status}, Uptime: ${status.uptime}s`);
} catch (error) {
console.error('Erro:', error);
} finally {
// Limpar recursos
await manager.destroy();
}
}
```
## 📚 API Completa
### FFmpegStreamManager
#### Constructor
```typescript
new FFmpegStreamManager(options?: StreamManagerOptions)
```
**Parâmetros:**
```typescript
interface StreamManagerOptions {
maxConcurrentStreams?: number; // Limite de streams (padrão: 10)
autoRestart?: boolean; // Auto-restart em falhas (padrão: true)
restartDelay?: number; // Delay entre restarts em ms (padrão: 5000)
logLevel?: 'debug' | 'info' | 'warning' | 'error'; // Nível de log (padrão: 'info')
}
```
#### Métodos Principais
##### `startStream(config: StreamConfig): Promise<string>`
Inicia um novo stream com configuração personalizada.
```typescript
const streamId = await manager.startStream({
rtmpUrl: 'rtmp://servidor.com/live/chave',
inputType: 'video',
inputPath: '/caminho/video.mp4',
staticImagePath: undefined,
loop: true,
videoConfig: {
width: 1920,
height: 1080,
bitrate: '4500k',
framerate: 30,
codec: 'libx264',
profile: 'high',
level: '4.1'
},
audioConfig: {
codec: 'aac',
bitrate: '128k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: 'zerolatency',
bufsize: '9000k',
maxrate: '4500k'
}
});
```
##### `startYouTubeStream(config, youtubeConfig): Promise<string>`
Inicia um stream otimizado para YouTube Live.
```typescript
const streamId = await manager.startYouTubeStream(
{
inputType: 'audio',
inputPath: '/caminho/audio.mp3',
staticImagePath: '/caminho/imagem.jpg',
loop: true,
...FFmpegStreamManager.getDefaultConfigs().youTube720p
},
{
streamKey: 'sua-chave-youtube',
server: 'rtmp://a.rtmp.youtube.com/live2/' // opcional
}
);
```
##### `stopStream(streamId: string): Promise<void>`
Para um stream específico.
##### `restartStream(streamId: string): Promise<void>`
Reinicia um stream.
##### `updateStreamConfig(streamId: string, updates: StreamUpdate): void`
Atualiza configurações (stream deve estar parado).
##### `getStreamStatus(streamId: string): StreamStatus`
Obtém status detalhado de um stream.
##### `getAllStreamStatuses(): StreamStatus[]`
Obtém status de todos os streams.
##### `getActiveStreamIds(): string[]`
Lista IDs dos streams ativos.
##### `stopAllStreams(): Promise<void>`
Para todos os streams.
##### `destroy(): Promise<void>`
Limpa todos os recursos.
#### Configurações Pré-definidas
```typescript
const configs = FFmpegStreamManager.getDefaultConfigs();
// Disponíveis:
// - youTube1080p: 1920x1080 @ 4500k
// - youTube720p: 1280x720 @ 2500k
// - youTube480p: 854x480 @ 1000k
```
## 🎬 Exemplos Detalhados
### Stream de Vídeo para YouTube
```typescript
import { FFmpegStreamManager } from 'ffmpeg-stream-manager';
async function streamVideoYoutube() {
const manager = new FFmpegStreamManager();
const streamId = await manager.startYouTubeStream(
{
inputType: 'video',
inputPath: '/videos/meu-video.mp4',
staticImagePath: undefined,
loop: true,
...FFmpegStreamManager.getDefaultConfigs().youTube1080p
},
{
streamKey: 'abcd-efgh-ijkl-mnop'
}
);
console.log(`Stream iniciado: ${streamId}`);
}
```
### Stream de Áudio com Imagem Estática
```typescript
async function streamAudioComImagem() {
const manager = new FFmpegStreamManager();
const streamId = await manager.startStream({
rtmpUrl: 'rtmp://live.twitch.tv/live/sua-chave',
inputType: 'audio',
inputPath: '/audio/musica.mp3',
staticImagePath: '/imagens/capa.jpg',
loop: true,
videoConfig: {
width: 1280,
height: 720,
bitrate: '2500k',
framerate: 30,
codec: 'libx264',
profile: 'main',
level: '3.1'
},
audioConfig: {
codec: 'aac',
bitrate: '128k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: 'zerolatency',
bufsize: '5000k',
maxrate: '2500k'
}
});
return streamId;
}
```
### Múltiplos Streams Simultâneos
```typescript
async function multiplosStreams() {
const manager = new FFmpegStreamManager({
maxConcurrentStreams: 3
});
const streams = await Promise.allSettled([
manager.startYouTubeStream(configYoutube1, { streamKey: 'key1' }),
manager.startYouTubeStream(configYoutube2, { streamKey: 'key2' }),
manager.startStream(configTwitch)
]);
streams.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Stream ${index + 1} iniciado: ${result.value}`);
} else {
console.error(`Stream ${index + 1} falhou: ${result.reason}`);
}
});
}
```
### Stream com Múltiplos Arquivos
```typescript
async function streamMultiplosArquivos() {
const manager = new FFmpegStreamManager();
// Múltiplos vídeos em sequência (playlist)
const videoStreamId = await manager.startYouTubeStream({
inputType: 'video',
inputPath: [
'/videos/intro.mp4',
'/videos/episodio1.mp4',
'/videos/episodio2.mp4',
'/videos/outro.mp4'
], // Array de arquivos
staticImagePath: undefined,
loop: true, // Repete a playlist infinitamente
...FFmpegStreamManager.getDefaultConfigs().youTube1080p
}, {
streamKey: 'sua-chave-youtube'
});
// Múltiplos áudios com imagem estática
const audioStreamId = await manager.startStream({
rtmpUrl: 'rtmp://live.twitch.tv/live/chave',
inputType: 'audio',
inputPath: [
'/musicas/track1.mp3',
'/musicas/track2.mp3',
'/musicas/track3.mp3'
], // Playlist de músicas
staticImagePath: '/imagens/capa-album.jpg',
loop: true, // Radio 24/7
videoConfig: {
width: 1280,
height: 720,
bitrate: '2500k',
framerate: 30,
codec: 'libx264',
profile: 'main',
level: '3.1'
},
audioConfig: {
codec: 'aac',
bitrate: '128k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: 'zerolatency',
bufsize: '5000k',
maxrate: '2500k'
}
});
return { videoStreamId, audioStreamId };
}
```
### Stream com Gerador FFmpeg
```typescript
async function streamGenerado() {
const manager = new FFmpegStreamManager();
// Stream de cor sólida com áudio silencioso
const streamId = await manager.startStream({
rtmpUrl: 'rtmp://servidor.com/live/test',
inputType: 'video',
inputPath: 'color=blue:size=1920x1080:rate=30',
staticImagePath: undefined,
loop: true,
...FFmpegStreamManager.getDefaultConfigs().youTube720p
});
return streamId;
}
```
## ⚙️ Configurações
### StreamConfig Interface
```typescript
interface StreamConfig {
id: string; // Auto-gerado (UUID v4)
rtmpUrl: string; // URL RTMP de destino
inputType: 'video' | 'audio'; // Tipo de entrada
inputPath: string | string[]; // Arquivo único ou múltiplos (playlist)
staticImagePath: string | undefined; // Imagem para streams de áudio
loop: boolean; // Loop infinito
videoConfig: VideoConfig; // Configurações de vídeo
audioConfig: AudioConfig; // Configurações de áudio
presetConfig: PresetConfig; // Configurações de preset
}
```
### VideoConfig Interface
```typescript
interface VideoConfig {
width: number; // Largura em pixels
height: number; // Altura em pixels
bitrate: string; // Taxa de bits (ex: "4500k")
framerate: number; // FPS (ex: 30)
codec: string; // Codec (ex: "libx264")
profile: string | undefined; // Perfil H.264 (ex: "high")
level: string | undefined; // Nível H.264 (ex: "4.1")
}
```
### AudioConfig Interface
```typescript
interface AudioConfig {
codec: string; // Codec (ex: "aac")
bitrate: string; // Taxa de bits (ex: "128k")
sampleRate: number; // Taxa de amostragem (ex: 44100)
channels: number; // Canais (ex: 2 para estéreo)
}
```
### PresetConfig Interface
```typescript
interface PresetConfig {
preset: string; // Preset FFmpeg (ex: "fast")
tune: string | undefined; // Tunning (ex: "zerolatency")
bufsize: string | undefined; // Buffer size (ex: "5000k")
maxrate: string | undefined; // Taxa máxima (ex: "2500k")
}
```
## 📡 Eventos
### Configurando Event Listeners
```typescript
const manager = new FFmpegStreamManager();
// Stream iniciado
manager.on('stream-started', (streamId: string) => {
console.log(`✅ Stream iniciado: ${streamId}`);
});
// Stream parado
manager.on('stream-stopped', (streamId: string) => {
console.log(`⏹️ Stream parado: ${streamId}`);
});
// Erro no stream
manager.on('stream-error', (streamId: string, error: Error) => {
console.error(`❌ Erro no stream ${streamId}: ${error.message}`);
});
// Stream reiniciado
manager.on('stream-restarted', (streamId: string) => {
console.log(`🔄 Stream reiniciado: ${streamId}`);
});
// Logs do FFmpeg
manager.on('log', (log: FFmpegLog) => {
console.log(`[${log.level}] [${log.streamId}] ${log.message}`);
});
```
### Filtrando Logs por Stream
```typescript
// Logs de um stream específico
manager.on('log', (log) => {
if (log.streamId === 'meu-stream-id') {
console.log(`Log específico: ${log.message}`);
}
});
// Apenas logs de erro
manager.on('log', (log) => {
if (log.level === 'error') {
console.error(`❌ Erro: ${log.message}`);
}
});
// Excluir logs do manager
manager.on('log', (log) => {
if (log.streamId !== 'manager') {
console.log(`Stream log: ${log.message}`);
}
});
```
## 🚨 Tratamento de Erros
### Try-Catch Básico
```typescript
try {
const streamId = await manager.startStream(config);
console.log('Stream iniciado com sucesso');
} catch (error) {
if (error instanceof StreamError) {
console.error(`Erro no stream ${error.streamId}: ${error.message}`);
} else {
console.error('Erro desconhecido:', error);
}
}
```
### Event Listeners para Erros
```typescript
manager.on('stream-error', (streamId, error) => {
console.error(`Stream ${streamId} falhou: ${error.message}`);
// Tentar reiniciar após 5 segundos
setTimeout(async () => {
try {
await manager.restartStream(streamId);
console.log(`Stream ${streamId} reiniciado com sucesso`);
} catch (restartError) {
console.error(`Falha ao reiniciar stream ${streamId}:`, restartError);
}
}, 5000);
});
```
### Validação de Configuração
```typescript
import { FFmpegCommandBuilder } from 'ffmpeg-stream-manager';
try {
FFmpegCommandBuilder.validateConfig(config);
console.log('Configuração válida');
} catch (error) {
console.error('Configuração inválida:', error.message);
}
```
## 📊 Logs e Monitoramento
### Monitoramento em Tempo Real
```typescript
// Monitorar todos os streams a cada 30 segundos
setInterval(() => {
const statuses = manager.getAllStreamStatuses();
console.log(`\n📊 Status dos Streams (${statuses.length} total):`);
statuses.forEach(status => {
const emoji = status.status === 'running' ? '🟢' :
status.status === 'error' ? '🔴' : '🟡';
console.log(`${emoji} ${status.id}:`);
console.log(` Status: ${status.status}`);
console.log(` Uptime: ${status.uptime}s`);
console.log(` Restarts: ${status.restartCount}`);
if (status.lastError) {
console.log(` Last Error: ${status.lastError}`);
}
});
}, 30000);
```
### Sistema de Logs Personalizado
```typescript
class StreamLogger {
private logFile: string;
constructor(logFile: string) {
this.logFile = logFile;
}
setupLogging(manager: FFmpegStreamManager) {
manager.on('log', (log) => {
const timestamp = log.timestamp.toISOString();
const logLine = `${timestamp} [${log.level}] [${log.streamId}] ${log.message}\n`;
// Escrever no arquivo (usando fs)
fs.appendFileSync(this.logFile, logLine);
// Console apenas para erros
if (log.level === 'error') {
console.error(logLine.trim());
}
});
manager.on('stream-started', (streamId) => {
this.logEvent('STARTED', streamId);
});
manager.on('stream-stopped', (streamId) => {
this.logEvent('STOPPED', streamId);
});
}
private logEvent(event: string, streamId: string) {
const timestamp = new Date().toISOString();
const logLine = `${timestamp} [EVENT] [${streamId}] ${event}\n`;
fs.appendFileSync(this.logFile, logLine);
}
}
// Uso
const logger = new StreamLogger('./streams.log');
logger.setupLogging(manager);
```
## 🔧 Tipos TypeScript
### StreamStatus Interface
```typescript
interface StreamStatus {
id: string; // ID único do stream
status: StreamState; // Estado atual
startTime: Date | undefined; // Hora de início
uptime: number | undefined; // Tempo ativo em segundos
restartCount: number; // Número de reinicializações
lastError: string | undefined; // Último erro
ffmpegPid: number | undefined; // PID do processo FFmpeg
config: StreamConfig; // Configuração do stream
}
```
### StreamState Enum
```typescript
enum StreamState {
STOPPED = 'stopped',
STARTING = 'starting',
RUNNING = 'running',
PAUSED = 'paused',
ERROR = 'error',
RESTARTING = 'restarting'
}
```
### FFmpegLog Interface
```typescript
interface FFmpegLog {
streamId: string; // ID do stream
timestamp: Date; // Timestamp do log
level: 'info' | 'error' | 'warning'; // Nível do log
message: string; // Mensagem
source: 'stdout' | 'stderr'; // Origem do log
}
```
### StreamUpdate Interface
```typescript
interface StreamUpdate {
rtmpUrl?: string; // Nova URL RTMP
inputPath?: string | string[]; // Novos arquivos (playlist)
videoConfig?: Partial<VideoConfig>; // Atualizações de vídeo
audioConfig?: Partial<AudioConfig>; // Atualizações de áudio
presetConfig?: Partial<PresetConfig>; // Atualizações de preset
loop?: boolean; // Alterar loop
}
```
## 🎛️ Configurações Pré-definidas
### YouTube Presets
```typescript
const configs = FFmpegStreamManager.getDefaultConfigs();
// 1080p - Alta qualidade
configs.youTube1080p = {
videoConfig: {
width: 1920,
height: 1080,
bitrate: '4500k',
framerate: 30,
codec: 'libx264',
profile: 'high',
level: '4.1'
},
audioConfig: {
codec: 'aac',
bitrate: '128k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: 'zerolatency',
bufsize: '9000k',
maxrate: '4500k'
}
};
// 720p - Qualidade média
configs.youTube720p = {
videoConfig: {
width: 1280,
height: 720,
bitrate: '2500k',
framerate: 30,
codec: 'libx264',
profile: 'high',
level: '3.1'
},
audioConfig: {
codec: 'aac',
bitrate: '128k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: 'zerolatency',
bufsize: '5000k',
maxrate: '2500k'
}
};
// 480p - Baixa qualidade
configs.youTube480p = {
videoConfig: {
width: 854,
height: 480,
bitrate: '1000k',
framerate: 30,
codec: 'libx264',
profile: 'main',
level: '3.0'
},
audioConfig: {
codec: 'aac',
bitrate: '96k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: 'zerolatency',
bufsize: '2000k',
maxrate: '1000k'
}
};
```
### Configurações Personalizadas
```typescript
// Para Twitch
const twitchConfig = {
videoConfig: {
width: 1920,
height: 1080,
bitrate: '6000k', // Twitch permite até 6Mbps
framerate: 60, // 60 FPS para jogos
codec: 'libx264',
profile: 'main',
level: '4.1'
},
audioConfig: {
codec: 'aac',
bitrate: '160k', // Áudio de alta qualidade
sampleRate: 48000, // 48kHz recomendado
channels: 2
},
presetConfig: {
preset: 'veryfast', // Preset mais rápido para menos latência
tune: 'zerolatency',
bufsize: '12000k',
maxrate: '6000k'
}
};
// Para Facebook Live
const facebookConfig = {
videoConfig: {
width: 1280,
height: 720,
bitrate: '4000k',
framerate: 30,
codec: 'libx264',
profile: 'baseline', // Facebook prefere baseline
level: '3.1'
},
audioConfig: {
codec: 'aac',
bitrate: '128k',
sampleRate: 44100,
channels: 2
},
presetConfig: {
preset: 'fast',
tune: undefined, // Sem tune específico
bufsize: '8000k',
maxrate: '4000k'
}
};
```
## 📋 Requisitos do Sistema
### Requisitos Mínimos
- **Node.js**: 16.0.0 ou superior
- **FFmpeg**: 4.0 ou superior
- **RAM**: 512MB disponível
- **CPU**: Depende da resolução e número de streams
- **Largura de banda**: Conforme bitrate configurado
### Requisitos Recomendados
- **Node.js**: 18.0.0 ou superior
- **FFmpeg**: 5.0 ou superior (melhor performance)
- **RAM**: 2GB+ para múltiplos streams
- **CPU**: Processador multi-core
- **SSD**: Para melhor I/O de arquivos
### Performance Guidelines
| Resolução | Streams Simultâneos | CPU Recomendado | RAM Recomendada |
|-----------|---------------------|-----------------|-----------------|
| 480p | 1-3 | 2 cores | 1GB |
| 720p | 1-2 | 4 cores | 2GB |
| 1080p | 1 | 6+ cores | 4GB |
### Estimativa de Uso de CPU
```typescript
// Exemplo de monitoramento de recursos
async function monitorarRecursos() {
const manager = new FFmpegStreamManager();
manager.on('stream-started', (streamId) => {
const status = manager.getStreamStatus(streamId);
console.log(`Stream ${streamId} - PID: ${status.ffmpegPid}`);
// Monitorar CPU do processo (usando bibliotecas como 'pidusage')
// pidusage(status.ffmpegPid, (err, stats) => {
// console.log(`CPU: ${stats.cpu}%, Memory: ${stats.memory} bytes`);
// });
});
}
```
## ❓ FAQ
### **Q: Como funciona o ID dos streams?**
**A:** O streamID é gerado automaticamente usando UUID v4, garantindo unicidade global. Formato: `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.
### **Q: Como usar múltiplos arquivos em loop?**
**A:** Use um array de strings no `inputPath`:
```typescript
{
inputPath: [
'/videos/parte1.mp4',
'/videos/parte2.mp4',
'/videos/parte3.mp4'
],
loop: true // Repete a sequência infinitamente
}
```
### **Q: Os arquivos são reproduzidos em ordem?**
**A:** Sim, os arquivos são reproduzidos na ordem exata do array. Para ordem aleatória, embaralhe o array antes:
```typescript
const files = ['/video1.mp4', '/video2.mp4', '/video3.mp4'];
const shuffled = files.sort(() => Math.random() - 0.5);
```
### **Q: Posso misturar diferentes formatos?**
**A:** Sim, mas todos devem ser do mesmo tipo (vídeo ou áudio). FFmpeg normalizará automaticamente:
```typescript
inputPath: [
'/videos/arquivo.mp4',
'/videos/outro.avi',
'/videos/terceiro.mov'
]
```
### **Q: Posso usar arquivos em rede (URLs HTTP)?**
**A:** Sim, o FFmpeg suporta URLs HTTP/HTTPS como entrada:
```typescript
{
inputPath: 'https://exemplo.com/video.mp4',
// ...
}
```
### **Q: Como otimizar para low latency?**
**A:** Use estas configurações:
```typescript
{
presetConfig: {
preset: 'ultrafast',
tune: 'zerolatency',
bufsize: '1000k' // Buffer menor
}
}
```
### **Q: Posso fazer stream sem arquivo (webcam/tela)?**
**A:** Esta biblioteca é focada em arquivos. Para webcam/tela, use geradores FFmpeg:
```typescript
{
inputPath: ':0.0+10,10', // Tela no Windows
// ou
inputPath: '/dev/video0' // Webcam no Linux
}
```
### **Q: Como tratar streams que param inesperadamente?**
**A:** Use auto-restart e monitore eventos:
```typescript
const manager = new FFmpegStreamManager({
autoRestart: true,
restartDelay: 3000
});
manager.on('stream-error', async (streamId, error) => {
console.error(`Stream ${streamId} erro: ${error.message}`);
// Lógica personalizada de restart
if (error.message.includes('Connection refused')) {
// Aguardar mais tempo para reconnect
await new Promise(resolve => setTimeout(resolve, 10000));
await manager.restartStream(streamId);
}
});
```
### **Q: Qual codec usar para melhor qualidade?**
**A:** Depende do caso:
- **H.264 (libx264)**: Mais compatível, boa qualidade
- **H.265 (libx265)**: Melhor compressão, requer mais CPU
- **Para YouTube**: H.264 é recomendado
- **Para baixa latência**: H.264 com tune zerolatency
### **Q: Como verificar se FFmpeg está instalado?**
**A:**
```bash
ffmpeg -version
```
Se não retornar versão, instale conforme seu OS.
### **Q: Posso usar com Docker?**
**A:** Sim, use uma imagem com Node.js + FFmpeg:
```dockerfile
FROM node:18
RUN apt-get update && apt-get install -y ffmpeg
COPY . .
RUN npm install
CMD ["npm", "start"]
```
### **Q: Como fazer debug de problemas?**
**A:**
1. Ative logs debug: `logLevel: 'debug'`
2. Monitore eventos de erro
3. Teste comando FFmpeg manualmente
4. Verifique permissões de arquivo
## 🤝 Contribuição
Contribuições são muito bem-vindas!
### Como Contribuir
1. **Fork** o repositório
2. Crie uma **branch** para sua feature (`git checkout -b feature/AmazingFeature`)
3. **Commit** suas mudanças (`git commit -m 'Add some AmazingFeature'`)
4. **Push** para a branch (`git push origin feature/AmazingFeature`)
5. Abra um **Pull Request**
### Diretrizes
- ✅ Mantenha 100% cobertura de tipos TypeScript
- ✅ Adicione testes para novas funcionalidades
- ✅ Siga o padrão de código existente
- ✅ Documente mudanças no README
- ✅ Teste com múltiplas versões do Node.js
### Desenvolvimento Local
```bash
# Clone o repositório
git clone https://github.com/seu-usuario/ffmpeg-stream-manager.git
cd ffmpeg-stream-manager
# Instale dependências
npm install
# Desenvolvimento com watch
npm run dev
# Executar testes
npm test
# Build
npm run build
# Lint
npm run lint
```
## 📄 Licença
Este projeto está licenciado sob a **MIT License** - veja o arquivo [LICENSE](LICENSE) para detalhes.
## 🔗 Links Úteis
- **NPM**: [https://www.npmjs.com/package/ffmpeg-stream-manager](https://www.npmjs.com/package/ffmpeg-stream-manager)
- **GitHub**: [https://github.com/seu-usuario/ffmpeg-stream-manager](https://github.com/seu-usuario/ffmpeg-stream-manager)
- **Issues**: [https://github.com/seu-usuario/ffmpeg-stream-manager/issues](https://github.com/seu-usuario/ffmpeg-stream-manager/issues)
- **FFmpeg Docs**: [https://ffmpeg.org/documentation.html](https://ffmpeg.org/documentation.html)
- **YouTube Live**: [https://support.google.com/youtube/answer/2907883](https://support.google.com/youtube/answer/2907883)
## 📊 Estatísticas




---
**Desenvolvido com ❤️ por [Seu Nome]**
*Se esta biblioteca foi útil para você, considere dar uma ⭐ no GitHub!*