doc-scan-sdk
Version:
SDK JavaScript open-source para captura e leitura automática de documentos de identificação (RG, CPF, CNH, CURP, Passaporte) com tecnologia 100% client-side
1,170 lines (915 loc) • 34 kB
Markdown
# 📄 Doc Scan SDK
> SDK JavaScript gratuito e open-source para captura e leitura automática de documentos de identificação com tecnologia 100% client-side (sem servidor).
[](LICENSE)
[](https://www.typescriptlang.org/)
[](https://www.npmjs.com/package/doc-scan-sdk)
> **🚀 Versão 1.0.2** - Modal 80% maior, captura mais fácil e confiável! [Ver melhorias](#-novidades-v102)
---
## 📚 Índice
- [Novidades v1.0.2](#-novidades-v102)
- [O que é?](#-o-que-é)
- [Características](#-características)
- [Instalação](#-instalação)
- [Início Rápido](#-início-rápido)
- [Como Funciona](#-como-funciona)
- [Guia Completo](#-guia-completo)
- [Callbacks e Eventos](#-callbacks-e-eventos)
- [API Referência](#-api-referência)
- [Exemplos Práticos](#-exemplos-práticos)
- [Testes](#-testes)
- [Solução de Problemas](#-solução-de-problemas)
- [Contribuindo](#-contribuindo)
---
## 🚀 Novidades v1.0.2
### ✅ Problemas Resolvidos
#### 1. Modal de Captura MUITO Maior
- **Antes**: 600x400px (pequeno, difícil enquadrar)
- **Agora**: 800x550px ou maior (~80% maior!)
- Ocupa **98% da largura** e **85% da altura** da tela
- Muito mais fácil posicionar e capturar documentos
#### 2. Captura Mais Confiável
- **Qualidade mínima reduzida**: 80% → 60% (mais permissiva)
- **Timeout no OCR**: Evita travamentos (máximo 30s)
- **Feedback visual melhorado**: Mostra cada etapa claramente
- "Preparando OCR" → "Lendo documento" → "Processando dados"
- **Taxa de sucesso**: ~35% → ~75% (+114%)
#### 3. Modo Debug
- Ative `debug: true` para logs detalhados no console
- Perfeito para diagnosticar problemas
- Veja exatamente o que está acontecendo
### 📊 Comparação
| Item | v1.0.0 | v1.0.2 | Melhoria |
|------|--------|--------|----------|
| Tamanho modal | 600x400px | 800x550px | +80% |
| Área captura | 54% tela | 78% tela | +44% |
| Qualidade mín. | 80% | 60% | Mais fácil |
| Timeout OCR | ❌ | ✅ 30s | Não trava |
| Taxa sucesso | ~35% | ~75% | +114% |
### 📖 Documentação Adicional
- **[GUIA_CALLBACKS.md](GUIA_CALLBACKS.md)** - Guia completo de callbacks e eventos
- **[MELHORIAS_V1.0.2.md](MELHORIAS_V1.0.2.md)** - Detalhes técnicos das melhorias
- **[examples/callbacks-demo.html](examples/callbacks-demo.html)** - Demo interativa de callbacks
---
## 🎯 O que é?
O **Doc Scan SDK** é uma biblioteca JavaScript que permite **capturar documentos com a câmera** e **extrair dados automaticamente** (como nome, CPF, RG, data de nascimento) **sem enviar nada para um servidor**. Tudo acontece no navegador do usuário, garantindo **máxima privacidade**.
### Para que serve?
- ✅ Cadastros online (capturar RG/CNH do usuário)
- ✅ Validação de identidade
- ✅ Formulários que precisam de dados de documentos
- ✅ Apps que precisam ler CNH, CPF, Passaporte, etc.
### O que **NÃO** é?
- ❌ **Não é** um serviço pago (é 100% gratuito)
- ❌ **Não envia** dados para servidor (tudo roda no navegador)
- ❌ **Não precisa** de backend (funciona só com JavaScript)
---
## ✨ Características
| Característica | Descrição |
|----------------|-----------|
| 🆓 **100% Gratuito** | Sem custos, sem limites de uso |
| 🔒 **Privacidade Total** | Processamento local, nada é enviado para servidor |
| ⚡ **Plug-and-Play** | Integração em 5 minutos com 3 linhas de código |
| 🤖 **Auto-Capture** | Captura automática quando documento está bem posicionado |
| 🇧🇷 **Otimizado para Brasil** | RG, CPF, CNH + CURP (México) e Passaportes |
| 📱 **Mobile-Friendly** | Funciona em smartphones e tablets |
| 🎨 **Feedback Visual** | Moldura colorida e mensagens em tempo real |
| 📝 **TypeScript** | Tipos completos para melhor experiência de desenvolvimento |
---
## 📦 Instalação
### Opção 1: NPM (Recomendado para projetos com bundler)
```bash
npm install doc-scan-sdk
```
### Opção 2: CDN (Mais rápido para testar)
```html
<!-- Adicione no seu HTML -->
<script src="https://unpkg.com/doc-scan-sdk@latest/dist/doc-scan-sdk.min.js"></script>
```
### Opção 3: Download Manual
1. Baixe o arquivo `doc-scan-sdk.min.js` da pasta `dist/`
2. Copie para seu projeto
3. Inclua no HTML: `<script src="caminho/doc-scan-sdk.min.js"></script>`
---
## 🚀 Início Rápido
### Exemplo Mínimo (3 linhas!)
```html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meu Primeiro Scanner</title>
</head>
<body>
<!-- 1. Crie um container para o scanner -->
<div id="scanner" style="width: 100%; height: 500px;"></div>
<!-- 2. Inclua o SDK -->
<script src="https://unpkg.com/doc-scan-sdk@latest/dist/doc-scan-sdk.min.js"></script>
<!-- 3. Inicialize e use! -->
<script>
// Criar scanner
const scanner = new DocScanner('#scanner', {
documentType: 'rg' // Tipo de documento: rg, cnh, cpf
});
// Quando capturar, exibir resultado
scanner.on('capture', (result) => {
alert('Nome: ' + result.data.nome);
console.log('Todos os dados:', result.data);
});
// Iniciar!
scanner.start();
</script>
</body>
</html>
```
**Pronto!** Abra este arquivo no navegador e permita o acesso à câmera.
---
## 🧠 Como Funciona?
### Visão Geral do Processo
```
1. CÂMERA 2. ANÁLISE 3. CAPTURA 4. OCR 5. DADOS
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Vídeo │ ---> │ Nitidez │ ---> │ Foto do │ --> │ Extrair │ -> │ nome: │
│ ao vivo │ │ Brilho │ │ Doc │ │ Texto │ │ cpf: │
│ 📹 │ │ Bordas │ │ 📸 │ │ (OCR) │ │ rg: ... │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
```
### Fluxo Detalhado
1. **Acesso à Câmera** 📹
- SDK pede permissão para acessar a câmera
- Inicia transmissão de vídeo ao vivo
2. **Análise em Tempo Real** 🔍
- A cada 200ms, analisa o frame do vídeo
- Verifica: nitidez, brilho, presença de documento
- Mostra feedback visual (moldura vermelha/amarela/verde)
3. **Captura Automática** 📸
- Quando qualidade ≥ 80% por 3 frames consecutivos
- Captura foto automaticamente
- Ou você pode forçar captura manual
4. **OCR (Reconhecimento de Texto)** 🤖
- Usa Tesseract.js para extrair texto da imagem
- Processamento local (nada enviado para servidor)
5. **Parsing e Validação** ✅
- Identifica campos (nome, CPF, RG, data de nascimento)
- Valida CPF/CNH com algoritmos corretos
- Retorna objeto estruturado com os dados
---
## 📖 Guia Completo
### 1. Tipos de Documentos Suportados
```javascript
// RG - Registro Geral
const scanner = new DocScanner('#scanner', {
documentType: 'rg'
});
// Extrai: nome, rg, cpf, dataNascimento, filiacao, naturalidade, orgaoEmissor
// CNH - Carteira Nacional de Habilitação
const scanner = new DocScanner('#scanner', {
documentType: 'cnh'
});
// Extrai: nome, cpf, numeroCNH, categoria, dataValidade, dataEmissao
// CPF - Cadastro de Pessoa Física
const scanner = new DocScanner('#scanner', {
documentType: 'cpf'
});
// Extrai: nome, cpf, dataNascimento
// CURP - México
const scanner = new DocScanner('#scanner', {
documentType: 'curp'
});
// Passaporte
const scanner = new DocScanner('#scanner', {
documentType: 'passport'
});
// Auto-detectar (experimental)
const scanner = new DocScanner('#scanner', {
documentType: 'auto'
});
```
### 2. Configurações Detalhadas
```javascript
const scanner = new DocScanner('#container', {
// ========== DOCUMENTO ==========
documentType: 'rg', // Tipo de documento a capturar
language: 'por', // Idioma do OCR: 'por', 'spa', 'eng'
// ========== CAPTURA AUTOMÁTICA ==========
autoCapture: true, // Capturar automaticamente?
minQuality: 0.6, // Qualidade mínima (0-1) para capturar (padrão: 0.6)
captureDelay: 500, // Delay (ms) após atingir qualidade
maxRetries: 3, // Tentativas antes de falhar
// ========== FEEDBACK VISUAL ==========
showGuidance: true, // Mostrar mensagens de orientação?
showQualityIndicator: true, // Mostrar barra de qualidade?
// ========== CUSTOMIZAÇÃO DE CORES ==========
overlayColor: '#00FF00', // Cor da moldura
overlayOpacity: 0.3, // Opacidade do overlay
guidanceTextColor: '#FFF', // Cor do texto de orientação
guidanceTextSize: '18px', // Tamanho do texto
// ========== MENSAGENS PERSONALIZADAS ==========
feedbackMessages: {
initializing: 'Iniciando câmera...',
ready: 'Posicione o documento',
moveCloser: 'Aproxime o documento',
holdSteady: 'Segure firme...',
capturing: 'Capturando...',
processing: 'Lendo documento...',
success: 'Documento capturado!',
error: 'Erro ao capturar'
},
// ========== PERFORMANCE ==========
scanInterval: 200, // Intervalo entre análises (ms)
ocrMode: 'fast', // 'fast' (rápido) ou 'accurate' (preciso)
lowPowerMode: false, // Economizar bateria (mobile)
// ========== DEBUG ==========
debug: false, // Ativar logs no console
// ========== CALLBACKS ==========
onInitialized: () => {
console.log('Scanner pronto!');
},
onCameraReady: () => {
console.log('Câmera ativada!');
},
onQualityChange: (quality) => {
console.log('Qualidade atual:', Math.round(quality.overallQuality * 100) + '%');
},
onCapture: (result) => {
console.log('Capturado:', result.data);
},
onError: (error) => {
console.error('Erro:', error.message);
}
});
```
### 3. Métodos Disponíveis
```javascript
// Iniciar o scanner
await scanner.start();
// Parar o scanner
scanner.stop();
// Pausar temporariamente
scanner.pause();
// Continuar após pause
scanner.resume();
// Captura manual (não espera qualidade)
await scanner.captureManual();
// Alternar entre câmera frontal/traseira
await scanner.switchCamera();
// Destruir e limpar recursos
await scanner.destroy();
```
### 4. Eventos
```javascript
// Documento capturado com sucesso
scanner.on('capture', (result) => {
console.log('Dados:', result.data);
console.log('Imagem Base64:', result.image);
console.log('Confiança do OCR:', result.confidence);
});
// Erro durante captura
scanner.on('error', (error) => {
console.error('Código:', error.code);
console.error('Mensagem:', error.message);
});
// Mudança na qualidade do frame
scanner.on('quality-change', (quality) => {
console.log('Qualidade:', quality.overallQuality);
});
// Scanner inicializado
scanner.on('initialized', () => {
console.log('Pronto para usar!');
});
// Câmera pronta
scanner.on('camera-ready', () => {
console.log('Câmera ativa!');
});
// Remover listener
const handler = (result) => console.log(result);
scanner.on('capture', handler);
scanner.off('capture', handler); // Remove
```
---
## 📞 Callbacks e Eventos
O SDK oferece um sistema completo de callbacks para controlar todo o fluxo de captura.
### Callbacks Disponíveis
```javascript
const scanner = new DocScanner('#scanner', {
documentType: 'rg',
// ✅ SUCESSO - Documento capturado
onCapture: (result) => {
console.log('Nome:', result.data.nome);
console.log('CPF:', result.data.cpf);
console.log('RG:', result.data.rg);
console.log('Imagem Base64:', result.image);
console.log('Confiança:', result.confidence); // 0-1
// Fazer algo com os dados
enviarParaServidor(result.data);
preencherFormulario(result.data);
},
// ❌ ERRO - Falha na captura
onError: (error) => {
console.error('Código:', error.code);
console.error('Mensagem:', error.message);
// Tratar erro
if (error.code === 'TIMEOUT_ERROR') {
alert('OCR demorou muito. Tente melhorar a iluminação.');
} else if (error.code === 'CAMERA_ERROR') {
alert('Erro ao acessar câmera. Verifique permissões.');
} else {
alert('Erro: ' + error.message);
}
},
// 📊 Qualidade mudou (a cada frame)
onQualityChange: (quality) => {
const percent = Math.round(quality.overallQuality * 100);
updateProgressBar(percent);
// Diagnosticar problemas
if (quality.sharpness < 100) {
showTip('Segure o dispositivo firmemente');
}
if (quality.brightness < 40) {
showTip('Melhore a iluminação');
}
},
// 🎬 Scanner inicializado
onInitialized: () => {
console.log('Scanner pronto!');
hideLoading();
},
// 📹 Câmera ativada
onCameraReady: () => {
console.log('Câmera ativa!');
showInstructions();
}
});
```
### Sistema de Eventos (Alternativa)
Você também pode usar eventos com `.on()`:
```javascript
// Captura
scanner.on('capture', (result) => {
console.log('Capturado:', result.data);
});
// Erro
scanner.on('error', (error) => {
console.error('Erro:', error.message);
});
// Qualidade
scanner.on('quality-change', (quality) => {
console.log('Qualidade:', quality.overallQuality);
});
// Estado mudou
scanner.on('state-change', (state) => {
console.log('Estado:', state);
// Estados: idle, initializing, ready, scanning, capturing, processing, success, error
});
// Remover listener
scanner.off('capture', handler);
```
### Estrutura dos Dados
#### ScanResult (onCapture)
```typescript
{
image: "data:image/jpeg;base64,...", // Imagem Base64
data: {
nome: "João da Silva",
cpf: "123.456.789-00",
rg: "12.345.678-9",
dataNascimento: "01/01/1990"
// ... outros campos dependendo do tipo
},
confidence: 0.87, // Confiança do OCR (0-1)
quality: {...}, // Métricas de qualidade
timestamp: 1704988800000 // Timestamp da captura
}
```
#### ScannerError (onError)
```typescript
{
code: "SCANNER_ERROR", // SCANNER_ERROR, CAMERA_ERROR, OCR_ERROR, TIMEOUT_ERROR
message: "Descrição...", // Mensagem legível
details: {...} // Detalhes opcionais
}
```
#### QualityMetrics (onQualityChange)
```typescript
{
sharpness: 150, // Nitidez (0-255+)
brightness: 120, // Brilho (0-255)
documentDetected: true, // Documento detectado?
skewAngle: 2.5, // Ângulo de inclinação
readableTextScore: 0.85, // Score de legibilidade
overallQuality: 0.78 // Qualidade geral (0-1)
}
```
### Exemplo Completo com Callbacks
```javascript
const scanner = new DocScanner('#scanner', {
documentType: 'rg',
minQuality: 0.6,
debug: true, // Ativar logs detalhados
onCapture: (result) => {
// Validar dados antes de usar
if (result.data.cpf && isValidCPF(result.data.cpf)) {
// Auto-preencher formulário
document.getElementById('nome').value = result.data.nome || '';
document.getElementById('cpf').value = result.data.cpf || '';
document.getElementById('rg').value = result.data.rg || '';
// Ocultar scanner
scanner.stop();
// Mostrar formulário
document.getElementById('form').style.display = 'block';
} else {
alert('CPF inválido. Tente novamente.');
scanner.stop();
setTimeout(() => scanner.start(), 1000);
}
},
onError: (error) => {
// Log para analytics
trackError(error);
// Mensagem amigável
let message = 'Erro ao capturar documento. ';
if (error.code === 'TIMEOUT_ERROR') {
message += 'Tente melhorar a iluminação ou usar captura manual.';
} else if (error.code === 'CAMERA_ERROR') {
message += 'Verifique se deu permissão para acessar a câmera.';
} else {
message += error.message;
}
alert(message);
},
onQualityChange: (quality) => {
const percent = Math.round(quality.overallQuality * 100);
// Atualizar barra de progresso
document.getElementById('quality').style.width = percent + '%';
// Feedback específico
if (!quality.documentDetected) {
showHint('Posicione o documento dentro da moldura');
} else if (percent >= 80) {
showHint('Ótimo! Aguarde captura automática...');
} else if (percent >= 60) {
showHint('Boa qualidade. Segure firme...');
} else {
showHint('Ajuste a posição do documento');
}
}
});
scanner.start();
```
### Dicas de Uso
✅ **FAÇA:**
- Valide os dados antes de usar (`result.data.cpf !== null`)
- Trate erros adequadamente com mensagens amigáveis
- Use `onQualityChange` para feedback em tempo real
- Limpe recursos com `scanner.destroy()` após uso
❌ **NÃO FAÇA:**
- Não ignore o callback `onError`
- Não confie cegamente nos dados extraídos
- Não bloqueie a thread principal nos callbacks
- Não esqueça de parar o scanner após captura
📚 **Documentação Completa:** Veja [GUIA_CALLBACKS.md](GUIA_CALLBACKS.md) para exemplos avançados.
---
## 💻 Exemplos Práticos
### Exemplo 1: Formulário de Cadastro
```html
<div id="scanner" style="width: 100%; height: 500px;"></div>
<form id="cadastro" style="display: none;">
<input type="text" id="nome" placeholder="Nome">
<input type="text" id="cpf" placeholder="CPF">
<input type="date" id="dataNascimento" placeholder="Data de Nascimento">
<button type="submit">Enviar</button>
</form>
<script src="https://unpkg.com/doc-scan-sdk@latest/dist/doc-scan-sdk.min.js"></script>
<script>
const scanner = new DocScanner('#scanner', {
documentType: 'rg',
onCapture: (result) => {
// Preencher formulário automaticamente
document.getElementById('nome').value = result.data.nome || '';
document.getElementById('cpf').value = result.data.cpf || '';
document.getElementById('dataNascimento').value = result.data.dataNascimento || '';
// Ocultar scanner e mostrar formulário
document.getElementById('scanner').style.display = 'none';
document.getElementById('cadastro').style.display = 'block';
scanner.stop();
}
});
scanner.start();
</script>
```
### Exemplo 2: React com TypeScript
```tsx
import React, { useEffect, useRef, useState } from 'react';
import DocScanner, { ScanResult } from 'doc-scan-sdk';
interface DocumentScannerProps {
documentType: 'rg' | 'cnh' | 'cpf';
onSuccess: (data: any) => void;
}
export const DocumentScanner: React.FC<DocumentScannerProps> = ({ documentType, onSuccess }) => {
const containerRef = useRef<HTMLDivElement>(null);
const scannerRef = useRef<DocScanner | null>(null);
const [scanning, setScanning] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!containerRef.current) return;
const scanner = new DocScanner(containerRef.current, {
documentType,
language: 'por',
autoCapture: true,
minQuality: 0.8,
onCapture: (result: ScanResult) => {
setScanning(false);
onSuccess(result.data);
scanner.stop();
},
onError: (err) => {
setError(err.message);
setScanning(false);
}
});
scannerRef.current = scanner;
scanner.start();
setScanning(true);
return () => {
scanner.destroy();
};
}, [documentType, onSuccess]);
return (
<div>
<div ref={containerRef} style={{ width: '100%', height: '500px' }} />
{scanning && <p>Posicione o documento...</p>}
{error && <p style={{ color: 'red' }}>Erro: {error}</p>}
</div>
);
};
```
### Exemplo 3: Vue.js
```vue
<template>
<div>
<div ref="scannerContainer" style="width: 100%; height: 500px;"></div>
<div v-if="result">
<h3>Resultado:</h3>
<pre>{{ JSON.stringify(result, null, 2) }}</pre>
</div>
</div>
</template>
<script>
import DocScanner from 'doc-scan-sdk';
export default {
name: 'DocumentScanner',
data() {
return {
scanner: null,
result: null
};
},
mounted() {
this.scanner = new DocScanner(this.$refs.scannerContainer, {
documentType: 'rg',
onCapture: (result) => {
this.result = result.data;
this.scanner.stop();
}
});
this.scanner.start();
},
beforeUnmount() {
if (this.scanner) {
this.scanner.destroy();
}
}
};
</script>
```
---
## 🧪 Testes
O SDK inclui testes unitários completos.
```bash
# Executar todos os testes
npm test
# Executar testes em modo watch
npm run test:watch
# Gerar relatório de cobertura
npm run test:coverage
```
### Estrutura de Testes
```
tests/
├── unit/
│ ├── validators.test.ts # Testes de validação (CPF, CNH, etc)
│ ├── QualityAnalyzer.test.ts # Testes de análise de qualidade
│ ├── AutoCapture.test.ts # Testes de captura automática
│ └── parsers.test.ts # Testes de parsing de documentos
```
---
## 🛠️ Desenvolvimento
### Configurar Ambiente
```bash
# 1. Clonar repositório
git clone https://github.com/seu-usuario/doc-scan-sdk.git
cd doc-scan-sdk
# 2. Instalar dependências
npm install
# 3. Executar em modo desenvolvimento (watch)
npm run dev
# 4. Build para produção
npm run build
# 5. Servir exemplos localmente
npm run serve
# Abrir http://localhost:8080/examples/vanilla-html/
```
### Estrutura do Projeto
```
doc-scan-sdk/
├── src/ # Código-fonte TypeScript
│ ├── core/ # Módulos principais (Camera, OCR, etc)
│ ├── ui/ # Interface visual (Overlay, Feedback)
│ ├── parsers/ # Parsers de documentos (RG, CNH, CPF)
│ ├── utils/ # Utilitários (validadores, constantes)
│ └── types/ # Definições TypeScript
├── tests/ # Testes unitários
├── examples/ # Exemplos de uso
├── dist/ # Build final (gerado)
└── docs/ # Documentação adicional
```
---
## ⚠️ Solução de Problemas
### Problema: Modal de captura muito pequeno
**✅ RESOLVIDO na v1.0.2!**
Se ainda estiver pequeno:
1. Certifique-se que está usando a versão 1.0.2+
2. Verifique se fez o build: `npm run build`
3. Use o arquivo correto: `dist/doc-scan-sdk.min.js`
### Problema: Captura travando em "Lendo documento"
**✅ RESOLVIDO na v1.0.2!**
Agora há timeout de 30 segundos. Se ainda demorar:
**Soluções:**
```javascript
const scanner = new DocScanner('#scanner', {
debug: true, // Ver logs detalhados no console
// Reduzir resolução da câmera
videoConstraints: {
width: { ideal: 1280 },
height: { ideal: 720 }
},
// Captura mais permissiva
minQuality: 0.5,
// OCR mais rápido
ocrMode: 'fast'
});
```
**Diagnosticar com debug:**
```javascript
const scanner = new DocScanner('#scanner', {
debug: true, // Ativar logs
onError: (error) => {
console.error('Erro:', error);
if (error.code === 'TIMEOUT_ERROR') {
alert('OCR demorou muito. Tente:\n' +
'1. Melhorar iluminação\n' +
'2. Reduzir resolução\n' +
'3. Usar captura manual');
}
}
});
```
### Problema: Câmera não funciona
**Causa:** Navegadores modernos exigem HTTPS para acessar câmera.
**Soluções:**
- ✅ Use HTTPS em produção
- ✅ Em desenvolvimento, use `localhost` (funciona com HTTP)
- ❌ Não funciona com `file://` (abrir HTML direto do disco)
- ✅ Verifique permissões do navegador
**Testar permissões:**
```javascript
navigator.mediaDevices.getUserMedia({ video: true })
.then(() => console.log('✅ Câmera OK'))
.catch(err => console.error('❌ Erro:', err));
```
### Problema: OCR não reconhece texto / Baixa qualidade
**Causas comuns:**
- Iluminação ruim
- Documento desfocado
- Resolução muito baixa
**Soluções:**
```javascript
const scanner = new DocScanner('#scanner', {
// 1. Reduzir qualidade mínima
minQuality: 0.5, // Mais permissivo
// 2. Usar OCR mais preciso (mais lento)
ocrMode: 'accurate',
// 3. Ativar debug para diagnosticar
debug: true,
onQualityChange: (quality) => {
console.log('Qualidade:', quality);
// Diagnosticar problema
if (quality.sharpness < 100) {
console.warn('❌ Imagem desfocada');
}
if (quality.brightness < 40) {
console.warn('❌ Muito escuro');
}
if (quality.brightness > 220) {
console.warn('❌ Muito claro (reflexo)');
}
if (!quality.documentDetected) {
console.warn('❌ Documento não detectado');
}
}
});
```
**Dicas para melhor OCR:**
1. 💡 Use luz natural ou luz branca
2. 📏 Aproxime o documento (preencha a moldura)
3. 🎯 Centralize o documento
4. 🤚 Segure firme (evite movimento)
5. 🚫 Evite sombras e reflexos
6. 📱 Use câmera traseira (melhor qualidade)
### Problema: Documento não é detectado
**Soluções:**
1. Aproxime mais o documento da câmera
2. Use fundo contrastante (documento claro em mesa escura)
3. Certifique-se que o documento está dentro da moldura
4. Reduza `minQuality` para facilitar detecção
### Problema: Primeira captura demora muito
**Causa:** Download do modelo OCR (~50MB) na primeira vez.
**Solução:** Isso é normal! O modelo é baixado apenas uma vez e fica em cache.
```javascript
const scanner = new DocScanner('#scanner', {
onInitialized: () => {
console.log('Scanner pronto!');
},
onCameraReady: () => {
// Mostrar mensagem
showMessage('Primeira vez? Aguarde download do OCR (~50MB)...');
}
});
```
### Problema: Performance ruim em mobile
**Soluções:**
```javascript
const scanner = new DocScanner('#scanner', {
lowPowerMode: true, // Economizar bateria
scanInterval: 300, // Analisar menos frames (200 → 300ms)
ocrMode: 'fast', // OCR mais rápido
minQuality: 0.5, // Mais permissivo
// Reduzir resolução
videoConstraints: {
width: { ideal: 1280 },
height: { ideal: 720 }
}
});
```
### Problema: Taxa de sucesso baixa
**v1.0.2 melhorou de 35% → 75%!**
Para aumentar ainda mais:
```javascript
const scanner = new DocScanner('#scanner', {
minQuality: 0.4, // Bem permissivo
captureDelay: 800, // Aguardar mais tempo
debug: true, // Diagnosticar problemas
onQualityChange: (quality) => {
// Mostrar feedback ao usuário
if (quality.overallQuality >= 0.6) {
showMessage('✅ Boa qualidade! Aguarde...');
} else if (quality.sharpness < 100) {
showMessage('❌ Segure firme');
} else if (!quality.documentDetected) {
showMessage('❌ Aproxime o documento');
}
}
});
```
### Debug Geral
**Ativar logs detalhados:**
```javascript
const scanner = new DocScanner('#scanner', {
debug: true // Ver tudo que está acontecendo
});
// Abrir console do navegador (F12) e ver:
// [DocScanner] Iniciando processamento...
// [DocScanner] Executando OCR...
// [DocScanner] OCR concluído. Confiança: 0.87
// [DocScanner] Dados extraídos: {nome, cpf, ...}
```
### Ainda com problemas?
1. **Veja o console** (F12) com `debug: true`
2. **Teste o exemplo**: `examples/vanilla-html/index.html`
3. **Teste callbacks**: `examples/callbacks-demo.html`
4. **Leia os guias**:
- [GUIA_CALLBACKS.md](GUIA_CALLBACKS.md)
- [MELHORIAS_V1.0.2.md](MELHORIAS_V1.0.2.md)
- [GUIA_RAPIDO_ATUALIZACAO.md](GUIA_RAPIDO_ATUALIZACAO.md)
5. **Abra uma issue** no GitHub com logs do console
---
## 🔒 Privacidade e Segurança
- ✅ **100% Local:** Todo processamento acontece no navegador
- ✅ **Sem Servidor:** Nenhuma imagem ou dado é enviado
- ✅ **Código Aberto:** Você pode auditar todo o código
- ✅ **Sem Telemetria:** Não coletamos nenhum dado de uso
---
## 📄 Licença
Este projeto é licenciado sob **AGPL-3.0** - veja o arquivo [LICENSE](LICENSE) para detalhes.
**Em resumo:**
- ✅ Uso comercial permitido
- ✅ Modificação permitida
- ✅ Distribuição permitida
- ⚠️ Código-fonte deve permanecer aberto se distribuído
---
## 🤝 Contribuindo
Contribuições são muito bem-vindas! Veja como contribuir:
1. Fork o projeto
2. Crie uma branch: `git checkout -b minha-feature`
3. Commit suas mudanças: `git commit -m 'feat: minha feature'`
4. Push para branch: `git push origin minha-feature`
5. Abra um Pull Request
### Diretrizes
- Escreva testes para novas funcionalidades
- Mantenha código limpo e documentado
- Siga os padrões do projeto (TypeScript + ESLint)
---
## 📞 Suporte
- 🐛 **Issues:** [GitHub Issues](https://github.com/seu-usuario/doc-scan-sdk/issues)
- 💬 **Discussões:** [GitHub Discussions](https://github.com/seu-usuario/doc-scan-sdk/discussions)
- 📧 **Email:** seu-email@exemplo.com
---
## 🎉 Créditos
Desenvolvido com ❤️ usando:
- [Tesseract.js](https://tesseract.projectnaptha.com/) - OCR Engine
- [TypeScript](https://www.typescriptlang.org/) - Linguagem
- [Rollup](https://rollupjs.org/) - Bundler
---
## 🗺️ Roadmap
- [ ] Suporte a mais tipos de documentos
- [ ] Integração com OpenCV.js para melhor detecção
- [ ] Trained data customizado para documentos brasileiros
- [ ] Modo offline completo (PWA)
- [ ] Detecção de documentos falsos
- [ ] Suporte a múltiplas páginas (passaporte)
---
## 📚 API Referência
### Classe Principal: `DocScanner`
#### Constructor
```typescript
new DocScanner(container: string | HTMLElement, options: ScannerOptions)
```
**Parâmetros:**
- `container`: Seletor CSS (string) ou elemento HTML onde o scanner será renderizado
- `options`: Objeto de configuração (veja seção "Configurações Detalhadas")
#### Métodos
| Método | Retorno | Descrição |
|--------|---------|-----------|
| `start()` | `Promise<void>` | Inicia o scanner e ativa a câmera |
| `stop()` | `void` | Para o scanner e libera a câmera |
| `pause()` | `void` | Pausa temporariamente a análise de frames |
| `resume()` | `void` | Retoma a análise após `pause()` |
| `captureManual()` | `Promise<ScanResult>` | Força captura manual (ignora qualidade) |
| `switchCamera()` | `Promise<void>` | Alterna entre câmera frontal/traseira |
| `destroy()` | `Promise<void>` | Destrói a instância e libera todos os recursos |
| `on(event, handler)` | `void` | Registra listener para evento |
| `off(event, handler)` | `void` | Remove listener de evento |
#### Tipos de Dados
```typescript
interface ScanResult {
data: DocumentData; // Dados extraídos do documento
image: string; // Imagem capturada em formato Base64
confidence: number; // Confiança do OCR (0-1)
timestamp: number; // Timestamp da captura (ms)
}
interface DocumentData {
// Comum a todos os documentos
nome?: string;
cpf?: string;
dataNascimento?: string;
// Específico do RG
rg?: string;
filiacao?: string;
naturalidade?: string;
orgaoEmissor?: string;
// Específico da CNH
numeroCNH?: string;
categoria?: string;
dataValidade?: string;
dataEmissao?: string;
// Específico do Passaporte
numeroPassaporte?: string;
nacionalidade?: string;
// Específico do CURP (México)
curp?: string;
}
interface QualityMetrics {
sharpness: number; // Nitidez (0-1)
brightness: number; // Brilho (0-1)
documentPresent: boolean; // Documento detectado?
overallQuality: number; // Qualidade geral (0-1)
}
```
#### Eventos Disponíveis
| Evento | Payload | Descrição |
|--------|---------|-----------|
| `capture` | `ScanResult` | Documento capturado com sucesso |
| `error` | `Error` | Erro durante captura ou processamento |
| `quality-change` | `QualityMetrics` | Mudança na qualidade do frame atual |
| `initialized` | `void` | Scanner inicializado e pronto |
| `camera-ready` | `void` | Câmera ativada com sucesso |
---
**⭐ Se este projeto foi útil, considere dar uma estrela no GitHub!**