vlibras-player-nextjs
Version:
VLibras Player para Next.js - Biblioteca moderna para tradução de texto em Libras com callbacks de estado
1,015 lines (808 loc) • 30.1 kB
Markdown
# vlibras-player-nextjs
> Biblioteca moderna do VLibras Player para Next.js e React com TypeScript






## 🎯 Sobre
O **vlibras-player-nextjs** é uma biblioteca moderna e otimizada do VLibras Player, especialmente desenvolvida para aplicações Next.js e React. Esta biblioteca permite integrar facilmente a tradução automática de texto para Libras (Língua Brasileira de Sinais) em suas aplicações web.
### ✨ Principais Características
- 🚀 **Compatível com Next.js 13+** (App Router e Pages Router)
- 🔷 **TypeScript nativo** com tipagem completa
- ⚛️ **Hooks React modernos** com conexão automática ao DOM
- 🎨 **Componentes estilizados** prontos para uso
- 📱 **Design responsivo** e acessível
- 🌙 **Suporte a tema escuro**
- 🔧 **API moderna** e fácil de usar
- 📦 **Tree-shaking** otimizado
- 🧪 **Totalmente testado**
- 🔄 **Conexão automática** ao container DOM (v2.1.0+)
- 🔧 **Sem duplicação** de containers Unity (v2.1.1+)
- 🎯 **Callbacks de estado** para monitoramento preciso (v2.2.0+)
- 🔄 **Gerenciamento Unity corrigido** com aguardo real de prontidão (v2.3.0+)
## 🆕 Novidades v2.5.0 - Hook com Melhores Práticas React! ⚛️
A versão **v2.5.0** traz o **hook redesenhado seguindo as melhores práticas do React**:
### 🏗️ Arquitetura Moderna com useReducer
- ✅ **Estado Centralizado**: Gerenciamento com `useReducer` para maior previsibilidade
- ✅ **Memoização Inteligente**: Callbacks e objetos memoizados para performance otimizada
- ✅ **Estados Derivados**: `canTranslate`, `canPause`, `canResume`, `canStop`, `canRestart`
- ✅ **Tratamento de Erros Robusto**: Distinção entre erros fatais e avisos
- ✅ **Debouncing**: Prevenção de traduções muito rápidas consecutivas
### 🎯 Interface Organizadas em Grupos
```tsx
const player = useVLibrasPlayer({ containerRef, autoInit: true });
// Controles agrupados
player.controls.play();
player.controls.pause();
// Configurações agrupadas
player.settings.setSpeed(1.5);
player.settings.setRegion('BR');
// Utilitários agrupados
player.utils.clearWarnings();
player.utils.retry();
```
### 🚀 Funcionalidades Avançadas
- � **Retry Automático**: Tentativas de reconexão configuráveis
- ⏱️ **Debouncing**: Controle de frequência de traduções
- 🛑 **AbortController**: Cancelamento de operações assíncronas
- 🧹 **Cleanup Automático**: Gerenciamento de memória e timers
- � **Estados Derivados**: Estados computados para UX melhor
### 🔗 Compatibilidade Mantida
- ✅ **API Legacy**: Métodos antigos mantidos para compatibilidade
- ✅ **Migração Gradual**: Adote novas práticas progressivamente
- ✅ **TypeScript Melhorado**: Tipagem mais precisa e documentação inline
### ⚠️ Principais Melhorias v2.4.1:
1. **Hook incompleto sem novas funcionalidades** → ✅ **Hook oficial 100% atualizado**
2. **Faltavam controles inteligentes** → ✅ **Controles automáticos baseados no estado**
3. **Sem logging de eventos** → ✅ **Sistema completo de event logging**
4. **Callbacks não integrados no hook** → ✅ **Integração total com callbacks**
5. **Erros de tipagem TypeScript** → ✅ **Tipos corrigidos e interface atualizada**
## 🆕 v2.3.0 - Correções Críticas de Estado
A versão **v2.3.0** corrige **problemas críticos** de gerenciamento de estado Unity:
- ✅ **UnityStateManager**: Nova classe para controle preciso do estado Unity WebGL
- ✅ **Aguardo de Prontidão**: Métodos aguardam automaticamente Unity estar pronto
- ✅ **Callbacks Funcionais**: Sistema de callbacks totalmente corrigido
- ✅ **Detecção de Animação**: Aguarda conclusão real das animações
- ✅ **Estados Confiáveis**: `isReady` reflete o estado real do Unity
- ✅ **Debugging**: Informações detalhadas para desenvolvimento
### ⚠️ Problemas Corrigidos na v2.3.0:
1. **`isReady: true` antes do Unity estar pronto** → ✅ Corrigido
2. **Callbacks `onLoad` não funcionando** → ✅ Corrigido
3. **Tradução não aguardando animação** → ✅ Corrigido
4. **Estados inconsistentes** → ✅ Corrigido
## 🆕 v2.2.0 - Callbacks de Estado (Base)
A versão **v2.2.0** introduz **callbacks de estado** que permitem monitorar eventos reais do VLibras Player:
```typescript
const { translate, isTranslating, isPlaying } = useVLibrasPlayer({
// ✅ Callbacks de tradução
onTranslationStart: () => console.log('🎬 Tradução iniciada'),
onTranslationEnd: () => console.log('✅ Tradução finalizada'),
onTranslationError: (error) => console.log('❌ Erro:', error),
// ✅ Callbacks de reprodução
onPlay: () => console.log('▶️ Reprodução iniciada'),
onPause: () => console.log('⏸️ Pausado'),
onStop: () => console.log('⏹️ Parado'),
// ✅ Callbacks do player
onPlayerReady: () => console.log('🚀 Player pronto'),
onPlayerError: (error) => console.log('💥 Erro no player:', error),
});
// ✅ Estados precisos baseados em eventos reais
console.log('Traduzindo:', isTranslating); // true/false preciso
console.log('Reproduzindo:', isPlaying); // true/false preciso
```
**Benefícios dos Callbacks:**
- 🎯 **Estado preciso** - Conhecimento real do que está acontecendo
- 🖥️ **UI responsiva** - Interfaces que refletem o estado real
- 📊 **Analytics** - Logging preciso de eventos
- 🔄 **Sem timers** - Eventos nativos do Unity WebGL
- ✅ **Retrocompatível** - API anterior continua funcionando
> 📚 **Documentação completa:** [docs/CALLBACKS_DOCUMENTATION.md](docs/CALLBACKS_DOCUMENTATION.md)
## 📦 Instalação
```bash
npm install vlibras-player-nextjs
# ou
yarn add vlibras-player-nextjs
# ou
pnpm add vlibras-player-nextjs
```
## � Debugging e Estado Unity (v2.3.0)
Para verificar o estado real do Unity e debugar problemas:
```tsx
'use client';
import { useVLibrasPlayer, UnityStateManager } from 'vlibras-player-nextjs';
export default function DebugComponent() {
const { player, isReady, connect } = useVLibrasPlayer({
onLoad: () => console.log('✅ Unity realmente pronto!'),
});
const showDebugInfo = () => {
const debugInfo = UnityStateManager.getDebugInfo();
console.log('🔍 Debug Unity:', debugInfo);
// Verificação manual do estado
console.log('🔍 Unity Ready:', UnityStateManager.isUnityReady());
console.log('🔍 Animation Playing:', UnityStateManager.isAnimationPlaying());
};
return (
<div>
<button onClick={showDebugInfo}>Ver Debug Info</button>
<div id="vlibras-player-container"></div>
<div>Estado: {isReady ? '✅ Pronto' : '⏳ Carregando'}</div>
</div>
);
}
```
## �🚀 Uso Básico
### Hook React Moderno (v2.5.0+) ⚛️
```typescript
'use client';
import { useRef } from 'react';
import { useVLibrasPlayer } from 'vlibras-player-nextjs';
export default function ModernVLibrasComponent() {
const containerRef = useRef<HTMLDivElement>(null);
// 🚀 Hook com melhores práticas React
const player = useVLibrasPlayer({
containerRef,
autoInit: true,
retryOnError: true,
maxRetries: 3,
debounceMs: 300,
// Callbacks organizados
onPlayerReady: () => console.log('🚀 Player pronto!'),
onStateChange: (state) => console.log('📊 Estado:', state.status),
onTranslationStart: () => console.log('🎬 Tradução iniciada'),
onTranslationEnd: () => console.log('✅ Tradução finalizada'),
onPlayerError: (error, isFatal) => {
console.log(isFatal ? '💥 Erro fatal:' : '⚠️ Aviso:', error);
}
});
const handleTranslate = async () => {
if (!player.canTranslate) return;
try {
await player.translate("Olá mundo moderno!");
} catch (error) {
console.error('Erro na tradução:', error);
}
};
return (
<div>
<div ref={containerRef} className="vlibras-container" />
{/* Controles inteligentes baseados em estado derivado */}
<button
onClick={handleTranslate}
disabled={!player.canTranslate}
>
{player.isBusy ? 'Processando...' : 'Traduzir'}
</button>
<button
onClick={player.controls.pause}
disabled={!player.canPause}
>
Pausar
</button>
<button
onClick={player.controls.resume}
disabled={!player.canResume}
>
Retomar
</button>
<button
onClick={player.controls.stop}
disabled={!player.canStop}
>
Parar
</button>
{/* Configurações */}
<button onClick={() => player.settings.setSpeed(1.5)}>
Velocidade 1.5x
</button>
{/* Utilitários */}
{player.hasWarnings && (
<button onClick={player.utils.clearWarnings}>
Limpar Avisos ({player.errors.warnings.length})
</button>
)}
{/* Estado visual */}
<div>
<p>Status: {player.status}</p>
<p>Pronto: {player.isReady ? '✅' : '⏳'}</p>
<p>Traduzindo: {player.isTranslating ? '🎬' : '⏸️'}</p>
<p>Reproduzindo: {player.isPlaying ? '▶️' : '⏹️'}</p>
{player.errors.fatal && (
<p style={{ color: 'red' }}>Erro: {player.errors.fatal}</p>
)}
</div>
</div>
);
}
```
### API de Compatibilidade (v2.4.x e anteriores)
```typescript
'use client';
import { useRef } from 'react';
import { useVLibrasPlayer } from 'vlibras-player-nextjs';
export default function LegacyComponent() {
const containerRef = useRef<HTMLDivElement>(null);
const { translate, isReady, isLoading, error } = useVLibrasPlayer({
autoInit: true,
containerRef, // 🔥 CONEXÃO AUTOMÁTICA!
targetPath: '/vlibras/target',
region: 'BR',
onLoad: () => console.log('Player carregado!'),
onError: (error) => console.error('Erro:', error)
});
const handleTranslate = async () => {
if (!isReady) return;
try {
await translate("Olá mundo!");
} catch (error) {
console.error('Erro na tradução:', error);
}
};
return (
<div>
<div ref={containerRef} className="vlibras-container" />
<button
onClick={handleTranslate}
disabled={!isReady || isLoading}
>
{isLoading ? 'Traduzindo...' : 'Traduzir'}
</button>
{error && <p style={{ color: 'red' }}>Erro: {error}</p>}
</div>
);
}
}
```
### Classe VLibras Player (Uso Direto)
```typescript
'use client';
import { VLibrasPlayer } from 'vlibras-player-nextjs';
import { useRef, useEffect, useState } from 'react';
export default function DirectUsage() {
const containerRef = useRef<HTMLDivElement>(null);
const [player, setPlayer] = useState<VLibrasPlayer | null>(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (containerRef.current) {
const playerInstance = new VLibrasPlayer({
targetPath: '/vlibras/target',
region: 'BR'
});
playerInstance.load(containerRef.current);
setPlayer(playerInstance);
}
}, []);
const handleTranslate = async () => {
if (!player) return;
setIsLoading(true);
try {
await player.translate("Olá mundo!");
} catch (error) {
console.error('Erro na tradução:', error);
} finally {
setIsLoading(false);
}
};
return (
<div>
<div ref={containerRef} className="vlibras-container" />
<button onClick={handleTranslate} disabled={!player || isLoading}>
{isLoading ? 'Traduzindo...' : 'Traduzir'}
</button>
</div>
);
}
```
player.load(containerRef.current);
}
}, [player]);
## 🆕 Novidades da v2.1.1
### 🔧 Bug Crítico de Duplicação Resolvido
A v2.1.1 resolve um **bug crítico** que causava duplicação de containers Unity WebGL:
#### ❌ Problema (v2.1.0 e anteriores)
- 🔴 **Múltiplos containers**: Criava containers duplicados a cada re-render
- 🔴 **Vazamentos de memória**: Containers órfãos não eram limpos
- 🔴 **Performance degradada**: Múltiplas instâncias Unity simultâneas
- 🔴 **IDs aleatórios**: Timestamps únicos impediam reutilização
#### ✅ Solução (v2.1.1)
- 🟢 **Container único**: Reutiliza container existente quando possível
- 🟢 **Cleanup automático**: Remove containers órfãos antes de criar novos
- 🟢 **IDs estáveis**: Baseados na região em vez de timestamps
- 🟢 **Verificação de estado**: Só carrega Unity se necessário
### 🚀 Melhorias Implementadas
1. **Verificação de Container Existente**: Player reutiliza containers quando possível
2. **Cleanup Automático**: Remove containers órfãos para evitar duplicação
3. **IDs Estáveis**: Containers têm IDs previsíveis para melhor reutilização
4. **Dispose Melhorado**: Limpeza completa de estado e recursos
5. **Hook Otimizado**: Dependências otimizadas para evitar re-execuções
## 🔄 Novidades da v2.1.0
### ✅ Hook useVLibrasPlayer Corrigido
O principal problema da v2.0.0 foi resolvido! Agora o hook **conecta automaticamente** ao container DOM:
#### ❌ Antes (v2.0.0 - Quebrado)
```typescript
const { player, translate } = useVLibrasPlayer({ autoInit: true });
// ❌ Necessário fazer conexão manual
useEffect(() => {
if (containerRef.current && player) {
player.load(containerRef.current); // ❌ Não funcionava
}
}, [player]);
```
#### ✅ Agora (v2.1.0+ - Funciona!)
```typescript
const { translate, isReady } = useVLibrasPlayer({
autoInit: true,
containerRef // ✅ Conexão automática!
});
// ✅ Pronto para usar, sem configuração adicional!
```
### 🚀 Funcionalidades v2.1.0
1. **Conexão Automática**: Use `containerRef` para conexão automática
2. **Callbacks de Eventos**: `onLoad`, `onTranslateStart`, `onTranslateEnd`, `onError`
3. **Estado `isReady`**: Saiba quando o player está pronto para uso
4. **Método `connect()`**: Conexão manual quando necessário
5. **Tratamento de Erros Melhorado**: Erros mais informativos
if (playerRef.current) {
await playerRef.current.translate('Olá mundo!');
}
};
return (
<div>
<div ref={containerRef} className="vlibras-container" />
<button onClick={handleTranslate}>Traduzir</button>
</div>
);
}
</button>
<button onClick={() => play()}>Play</button>
<button onClick={() => pause()}>Pause</button>
</div>
<div className="status">
Status: {player.status} | Carregado: {player.loaded ? 'Sim' : 'Não'}
</div>
</div>
);
}
```
## 🔧 API Completa
### Hook useVLibrasPlayer (v2.1.0+)
```typescript
interface UseVLibrasPlayerOptions {
// Configurações do Player
autoInit?: boolean; // Inicializa automaticamente
containerRef?: RefObject<HTMLElement>; // Ref para conexão automática
targetPath?: string; // Caminho dos arquivos Unity
translatorUrl?: string; // URL do serviço de tradução
region?: 'BR' | 'PT'; // Região do dicionário
enableStats?: boolean; // Habilitar estatísticas
// Callbacks
onLoad?: () => void; // Player carregado
onTranslateStart?: (text: string) => void; // Tradução iniciada
onTranslateEnd?: (gloss: string) => void; // Tradução finalizada
onError?: (error: string) => void; // Erro ocorrido
}
// Uso do Hook
const {
// Estado
player, // Estado atual do player
isLoading, // Se está carregando/traduzindo
error, // Erro atual (se houver)
isReady, // Se está pronto para uso (v2.1.0+)
// Métodos de Controle
translate, // Traduzir texto
play, // Reproduzir animação
pause, // Pausar animação
stop, // Parar animação
repeat, // Repetir última animação
setSpeed, // Definir velocidade
toggleSubtitle, // Alternar legendas
changeAvatar, // Trocar avatar
setRegion, // Definir região
// Conexão Manual (v2.1.0+)
connect, // Conectar a container específico
} = useVLibrasPlayer(options);
```
### Classe VLibrasPlayer
```typescript
interface VLibrasPlayerOptions {
translatorUrl?: string;
targetPath?: string;
region?: 'BR' | 'PT';
enableStats?: boolean;
onLoad?: () => void;
}
// Uso da Classe
const player = new VLibrasPlayer(options);
player.load(containerElement);
await player.translate(text);
```
// Métodos de controle
translate, // Traduzir texto
play, // Reproduzir
pause, // Pausar
stop, // Parar
repeat, // Repetir
// Configurações
## 🎨 Exemplos Avançados
### Exemplo com Callbacks e Estados
```typescript
'use client';
import { useRef, useState } from 'react';
import { useVLibrasPlayer } from 'vlibras-player-nextjs';
export default function AdvancedExample() {
const containerRef = useRef<HTMLDivElement>(null);
const [status, setStatus] = useState('Aguardando...');
const [translatedText, setTranslatedText] = useState('');
const {
translate,
play,
pause,
stop,
setSpeed,
isReady,
isLoading,
error,
player
} = useVLibrasPlayer({
autoInit: true,
containerRef,
region: 'BR',
targetPath: '/vlibras/target',
onLoad: () => setStatus('Player carregado!'),
onTranslateStart: (text) => {
setStatus(`Traduzindo: ${text}`);
setTranslatedText(text);
},
onTranslateEnd: (gloss) => setStatus(`Glosa: ${gloss}`),
onError: (error) => setStatus(`Erro: ${error}`)
});
const handleTranslate = async () => {
const text = prompt('Digite o texto para traduzir:');
if (text && text.trim()) {
try {
await translate(text);
} catch (err) {
console.error('Erro na tradução:', err);
}
}
};
return (
<div className="vlibras-demo">
<div ref={containerRef} className="vlibras-container" />
<div className="controls">
<button onClick={handleTranslate} disabled={!isReady}>
📝 Traduzir Texto
</button>
<button onClick={() => play()} disabled={!isReady}>
▶️ Play
</button>
<button onClick={pause} disabled={!isReady}>
⏸️ Pause
</button>
<button onClick={stop} disabled={!isReady}>
⏹️ Stop
</button>
<button onClick={() => setSpeed(1.5)} disabled={!isReady}>
⚡ Velocidade 1.5x
</button>
</div>
<div className="status">
<p><strong>Status:</strong> {status}</p>
<p><strong>Player Status:</strong> {player.status}</p>
<p><strong>Carregado:</strong> {player.loaded ? 'Sim' : 'Não'}</p>
<p><strong>Pronto:</strong> {isReady ? 'Sim' : 'Não'}</p>
<p><strong>Carregando:</strong> {isLoading ? 'Sim' : 'Não'}</p>
{translatedText && <p><strong>Último texto:</strong> {translatedText}</p>}
{error && <p style={{ color: 'red' }}><strong>Erro:</strong> {error}</p>}
</div>
</div>
);
}
```
### Conexão Manual Avançada
```typescript
'use client';
import { useRef, useEffect, useState } from 'react';
import { useVLibrasPlayer } from 'vlibras-player-nextjs';
export default function ManualConnectionExample() {
const [selectedContainer, setSelectedContainer] = useState<string>('container1');
const container1Ref = useRef<HTMLDivElement>(null);
const container2Ref = useRef<HTMLDivElement>(null);
const { connect, translate, isReady } = useVLibrasPlayer({
autoInit: true,
// Sem containerRef para conexão manual
});
const handleContainerChange = (containerId: string) => {
setSelectedContainer(containerId);
const container = containerId === 'container1'
? container1Ref.current
: container2Ref.current;
if (container) {
connect(container);
}
};
return (
<div>
<div className="container-selection">
<button onClick={() => handleContainerChange('container1')}>
Conectar ao Container 1
</button>
<button onClick={() => handleContainerChange('container2')}>
Conectar ao Container 2
</button>
</div>
<div className="containers">
<div
ref={container1Ref}
className={`vlibras-container ${selectedContainer === 'container1' ? 'active' : ''}`}
style={{ border: selectedContainer === 'container1' ? '2px solid blue' : '1px solid gray' }}
/>
<div
ref={container2Ref}
className={`vlibras-container ${selectedContainer === 'container2' ? 'active' : ''}`}
style={{ border: selectedContainer === 'container2' ? '2px solid blue' : '1px solid gray' }}
/>
</div>
<button onClick={() => translate("Olá!")} disabled={!isReady}>
Traduzir no Container Ativo
</button>
</div>
);
}
```
## ⚙️ Configuração
### Next.js (next.config.js)
```javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
// Configurações para WebGL/Unity
webpack: (config) => {
config.resolve.fallback = {
...config.resolve.fallback,
fs: false,
};
return config;
},
// Headers para WebGL
async headers() {
return [
{
source: '/vlibras/target/:path*',
headers: [
{
key: 'Cross-Origin-Embedder-Policy',
value: 'require-corp',
},
{
key: 'Cross-Origin-Opener-Policy',
value: 'same-origin',
},
],
},
];
},
};
module.exports = nextConfig;
```
### Estrutura de Arquivos
```
public/
vlibras/
target/
playerweb.data.unityweb
playerweb.json
playerweb.wasm.code.unityweb
playerweb.wasm.framework.unityweb
UnityLoader.js
```
Os arquivos Unity são incluídos automaticamente na biblioteca, mas você pode substituí-los colocando os arquivos na pasta `public/vlibras/target/`.
## 🔄 Migração
### De v2.1.0 para v2.1.1
A v2.1.1 é **100% retrocompatível** e resolve automaticamente o problema de duplicação:
#### ✅ Sem Mudanças Necessárias
```typescript
// Seu código existente continua funcionando perfeitamente
const { translate, isReady } = useVLibrasPlayer({
autoInit: true,
containerRef
});
// ✅ Agora SEM duplicação de containers automático!
```
#### 🚀 Benefícios Automáticos da v2.1.1:
- **Performance melhorada**: Sem containers duplicados
- **Menos uso de memória**: Cleanup automático de recursos
- **Estabilidade**: Comportamento consistente em re-renders
- **React StrictMode**: Funciona perfeitamente com modo estrito
### De v2.0.0 para v2.1.1
Migração recomendada em duas etapas:
#### ✅ Código Recomendado (v2.1.1)
```typescript
const { translate, isReady } = useVLibrasPlayer({
autoInit: true,
containerRef // Conexão automática + sem duplicação
});
// ✅ API moderna sem problemas de performance
```
#### ❌ Código Antigo (ainda funciona, mas não recomendado)
```typescript
const { player, translate } = useVLibrasPlayer({ autoInit: true });
useEffect(() => {
if (containerRef.current && player) {
// Conexão manual ainda funciona, mas é desnecessária
player.load?.(containerRef.current);
}
}, [player]);
```
### Do VLibras Original
Se você está migrando do VLibras original, a integração é simples:
#### Antes (VLibras Original)
```html
<div vw class="enabled">
<div vw-access-button class="active"></div>
<div vw-plugin-wrapper>
<div class="vw-plugin-top-wrapper"></div>
</div>
</div>
<script src="https://vlibras.gov.br/app/vlibras-plugin.js"></script>
<script>
new window.VLibras.Widget('https://vlibras.gov.br/app');
</script>
```
#### Depois (vlibras-player-nextjs)
```typescript
import { useVLibrasPlayer } from 'vlibras-player-nextjs';
const { translate } = useVLibrasPlayer({
autoInit: true,
containerRef
});
```
### Arquivos Unity (public/vlibras/target/)
Coloque os arquivos Unity WebGL no diretório público:
```
public/
└── vlibras/
└── target/
├── UnityLoader.js
├── playerweb.json
├── playerweb.data.unityweb
├── playerweb.wasm.code.unityweb
└── playerweb.wasm.framework.unityweb
```
## ❓ FAQ
### **Hook vs Classe: Qual usar?**
**Hook (Recomendado)**: Use para integração simples em componentes React
```typescript
const { translate, isReady } = useVLibrasPlayer({ autoInit: true, containerRef });
```
**Classe**: Use para controle avançado ou integração com frameworks não-React
```typescript
const player = new VLibrasPlayer(options);
player.load(container);
```
### **Como corrigir "Player não inicializado"?**
**v2.1.0+**: Use `containerRef` para conexão automática
```typescript
const containerRef = useRef<HTMLDivElement>(null);
const { translate } = useVLibrasPlayer({ autoInit: true, containerRef });
```
### **Arquivos Unity não carregam?**
1. Verifique se os arquivos estão em `public/vlibras/target/`
2. Configure os headers CORS no `next.config.js`
3. Use `targetPath: '/vlibras/target'` nas opções
### **Como personalizar o avatar?**
```typescript
const { changeAvatar } = useVLibrasPlayer({ autoInit: true, containerRef });
// Trocar para avatar feminino
changeAvatar('anya');
// Trocar para avatar masculino
changeAvatar('icaro');
```
### **Funciona com SSR/SSG?**
Sim! Use `'use client'` no componente que usa o VLibras:
```typescript
'use client';
import { useVLibrasPlayer } from 'vlibras-player-nextjs';
```
## 🎯 Compatibilidade
- ✅ **Next.js 13+** (App Router e Pages Router)
- ✅ **React 18+**
- ✅ **TypeScript 5+**
- ✅ **Node.js 16+**
- ✅ **Navegadores modernos** (Chrome 80+, Firefox 74+, Safari 13+)
- ✅ **SSR/SSG** com Next.js
- ✅ **Webpack 5+**
- ✅ **Vite 4+**
## 📊 Performance
- 📦 **Tamanho do bundle**: ~14MB (inclui arquivos Unity WebGL)
- ⚡ **Carregamento inicial**: ~2-3s (dependendo da conexão)
- 🔄 **Tradução**: ~500ms-1s por frase
- 💾 **Uso de memória**: ~50-100MB durante reprodução
## 🛠️ Desenvolvimento
```bash
# Clonar repositório
git clone https://github.com/Luca-Sousa/vlibras-player-web-nextjs.git
# Instalar dependências
npm install
# Desenvolvimento
npm run dev
# Build
npm run build
# Testes
npm run test
# Verificação de tipos
npm run type-check
```
## 📄 Licença
Este projeto está licenciado sob a [LGPL v3.0](LICENSE) - veja o arquivo LICENSE para detalhes.
O VLibras é uma tecnologia desenvolvida pelo [Governo Federal do Brasil](https://www.vlibras.gov.br/).
## 🤝 Contribuição
Contribuições são bem-vindas! Por favor, leia nosso [guia de contribuição](CONTRIBUTING.md) antes de submeter um PR.
### Como contribuir:
1. 🍴 Fork o projeto
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
## 📞 Suporte
- 📋 **Issues**: [GitHub Issues](https://github.com/Luca-Sousa/vlibras-player-web-nextjs/issues)
- 📧 **Email**: [contato](mailto:lucas.sousa.ldev@gmail.com)
- 📱 **NPM**: [vlibras-player-nextjs](https://www.npmjs.com/package/vlibras-player-nextjs)
## 🙏 Agradecimentos
- [VLibras](https://www.vlibras.gov.br/) - Tecnologia original
- [Unity Technologies](https://unity.com/) - WebGL Runtime
- [Next.js Team](https://nextjs.org/) - Framework
- [React Team](https://reactjs.org/) - Biblioteca
---
<div align="center">
**vlibras-player-nextjs v2.1.1** - *Acessibilidade em Libras para React e Next.js* 🤟
[](https://www.npmjs.com/package/vlibras-player-nextjs)
[](https://www.npmjs.com/package/vlibras-player-nextjs)
[](LICENSE)
</div>
/>
</div>
<div className="flex gap-2">
<button
onClick={handleTranslate}
disabled={isTranslating || !text.trim()}
className="bg-blue-500 text-white px-4 py-2 rounded disabled:opacity-50"
>
{isTranslating ? 'Traduzindo...' : 'Traduzir'}
</button>
<button
onClick={() => playerRef.current?.play()}
className="bg-green-500 text-white px-4 py-2 rounded"
>
Play
</button>
<button
onClick={() => playerRef.current?.pause()}
className="bg-yellow-500 text-white px-4 py-2 rounded"
>
Pause
</button>
<button
onClick={() => playerRef.current?.stop()}
className="bg-red-500 text-white px-4 py-2 rounded"
>
Stop
</button>
</div>
</div>
</div>
);
}
```
## 🤝 Contribuindo
Contribuições são bem-vindas! Por favor, leia nosso [guia de contribuição](CONTRIBUTING.md) para mais detalhes.
## 📄 Licença
Este projeto está licenciado sob a [LGPL-3.0](LICENSE) - veja o arquivo LICENSE para detalhes.
## 👥 Créditos
- **Equipe VLibras Original:** Criadores da tecnologia base
- **Comunidade Next.js:** Inspiração e melhores práticas
- **Contribuidores:** Todos que ajudaram a modernizar esta biblioteca
---
<div align="center">
<p>Feito com ❤️ para democratizar o acesso à Libras na web</p>
</div>