doc-scan-sdk
v1.0.2
Published
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
Maintainers
Readme
📄 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).
🚀 Versão 1.0.2 - Modal 80% maior, captura mais fácil e confiável! Ver melhorias
📚 Índice
- Novidades v1.0.2
- O que é?
- Características
- Instalação
- Início Rápido
- Como Funciona
- Guia Completo
- Callbacks e Eventos
- API Referência
- Exemplos Práticos
- Testes
- Solução de Problemas
- 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: truepara 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 completo de callbacks e eventos
- MELHORIAS_V1.0.2.md - Detalhes técnicos das melhorias
- 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)
npm install doc-scan-sdkOpção 2: CDN (Mais rápido para testar)
<!-- 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
- Baixe o arquivo
doc-scan-sdk.min.jsda pastadist/ - Copie para seu projeto
- Inclua no HTML:
<script src="caminho/doc-scan-sdk.min.js"></script>
🚀 Início Rápido
Exemplo Mínimo (3 linhas!)
<!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
Acesso à Câmera 📹
- SDK pede permissão para acessar a câmera
- Inicia transmissão de vídeo ao vivo
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)
Captura Automática 📸
- Quando qualidade ≥ 80% por 3 frames consecutivos
- Captura foto automaticamente
- Ou você pode forçar captura manual
OCR (Reconhecimento de Texto) 🤖
- Usa Tesseract.js para extrair texto da imagem
- Processamento local (nada enviado para servidor)
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
// 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
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
// 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
// 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
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():
// 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)
{
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)
{
code: "SCANNER_ERROR", // SCANNER_ERROR, CAMERA_ERROR, OCR_ERROR, TIMEOUT_ERROR
message: "Descrição...", // Mensagem legível
details: {...} // Detalhes opcionais
}QualityMetrics (onQualityChange)
{
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
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
onQualityChangepara 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 para exemplos avançados.
💻 Exemplos Práticos
Exemplo 1: Formulário de Cadastro
<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
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
<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.
# Executar todos os testes
npm test
# Executar testes em modo watch
npm run test:watch
# Gerar relatório de cobertura
npm run test:coverageEstrutura 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
# 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:
- Certifique-se que está usando a versão 1.0.2+
- Verifique se fez o build:
npm run build - 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:
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:
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:
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:
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:
- 💡 Use luz natural ou luz branca
- 📏 Aproxime o documento (preencha a moldura)
- 🎯 Centralize o documento
- 🤚 Segure firme (evite movimento)
- 🚫 Evite sombras e reflexos
- 📱 Use câmera traseira (melhor qualidade)
Problema: Documento não é detectado
Soluções:
- Aproxime mais o documento da câmera
- Use fundo contrastante (documento claro em mesa escura)
- Certifique-se que o documento está dentro da moldura
- Reduza
minQualitypara 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.
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:
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:
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:
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?
- Veja o console (F12) com
debug: true - Teste o exemplo:
examples/vanilla-html/index.html - Teste callbacks:
examples/callbacks-demo.html - Leia os guias:
- 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 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:
- Fork o projeto
- Crie uma branch:
git checkout -b minha-feature - Commit suas mudanças:
git commit -m 'feat: minha feature' - Push para branch:
git push origin minha-feature - 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
- 💬 Discussões: GitHub Discussions
- 📧 Email: [email protected]
🎉 Créditos
Desenvolvido com ❤️ usando:
- Tesseract.js - OCR Engine
- TypeScript - Linguagem
- Rollup - 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
new DocScanner(container: string | HTMLElement, options: ScannerOptions)Parâmetros:
container: Seletor CSS (string) ou elemento HTML onde o scanner será renderizadooptions: 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
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!
