npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

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).

License TypeScript npm

🚀 Versão 1.0.2 - Modal 80% maior, captura mais fácil e confiável! Ver melhorias


📚 Índice


🚀 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


🎯 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-sdk

Opçã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

  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!)

<!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

// 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 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 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: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

# 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:

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:

  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.

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?

  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:
  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 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


🎉 Créditos

Desenvolvido com ❤️ usando:


🗺️ 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á 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

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!