Acesso exclusivo. Digite o código que você recebeu.
build 12ago-1
Requisitos mínimos
O que é preciso para testar agora e para levar a ferramenta à loja.
Para a equipe testar (este ambiente)
Celular ou computador com navegador atual — Chrome, Safari, Edge ou Firefox
Conexão estável — Wi-Fi ou 4G com bom sinal; a foto sobe ~150 KB por prova
Câmera é opcional — dá para enviar uma foto da galeria
Nada para instalar — roda 100% no navegador, sempre em HTTPS
Para integrar na loja
Qualquer plataforma que faça uma chamada HTTPS — VTEX, site próprio, app; exemplos prontos em “Ver integração”
A foto de produto que a PDP já exibe — por URL ou base64; não precisa refotografar o catálogo
Latência típica de 5 a 12 segundos por prova — até ~1 min em pico (fila)
Para hospedar o modelo completo no servidor de vocês
GPU NVIDIA com 80 GB+ de VRAM— A100 80GB, H100 ou RTX PRO 6000; o modelo ocupa ~58 GB carregado e ~67 GB em pico de geração
200 GB de disco NVMe — pesos dos modelos (~85 GB), ambientes e catálogo processado
64 GB de RAM e 16+ vCPUs — carga e pré-processamento
Linux com driver NVIDIA/CUDA 12.8+ — PyTorch 2.8, Python 3.12; entregamos os scripts de subida prontos
HTTPS na frente (reverse proxy) — o serviço expõe uma porta única + /health
Subida a frio: ~6 min até o modelo pronto na VRAM — medido; o /health informa carregando durante
Capacidade por GPU: uma prova a cada 5–12 s— fila embutida; escala horizontal = mais GPUs atrás do mesmo endpoint
Alternativa sem infra própria: a THM segue operando a GPU dedicada — requisito do lado de vocês passa a ser só a chamada HTTPS.
O que a THM entrega e opera
Endpoint único com TLS
GPU dedicada com controle de qualidade automático — regenera a prova quando detecta defeito
Foto do cliente processada em memória, nunca armazenada — aderente à LGPD
Monitoramento por /health e reprodutibilidade por seed
Óticas ParisProvador Virtual
THM-Glass-provadorvirtualprova virtual de óculos
Endpoint
# Teste rápido de terminal — prove a integração antes de escrever código
curl -X POST https://provador.paristeste.cloud/provar \
-H "content-type: application/json" \
-d '{
"images": ["<data URI da foto do cliente>",
"<data URI ou URL da foto do produto>"],
"tipo": "grau"
}'
# → {"status":"ok","image":"data:image/webp;base64,...","seed":123,"qc":{...}}
// Navegador (front da loja) — igual ao que esta página usa
const r = await fetch("https://provador.paristeste.cloud/provar", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ images: [fotoCliente, fotoProduto], tipo: "grau" })
});
const d = await r.json();
if (d.status === "revisar") mostrarOrientacao(d.aviso, d.recomendacao);
else if (d.image) exibirProva(d.image, d.seed);
<!-- Provador Virtual THM — widget de SANDBOX para a página de produto.
Cole antes do </body> do template da PDP:
botão → foto do cliente → prova no nosso servidor → resultado na tela.
A imagem do produto é capturada da própria página (og:image). -->
<script>
(function () {
var API = "https://provador.paristeste.cloud/provar";
// 1. imagem do produto: og:image existe em toda PDP VTEX e não depende de tema
var meta = document.querySelector('meta[property="og:image"]');
var fotoProduto = meta ? meta.content : null;
if (!fotoProduto) return; // não é página de produto: não faz nada
// 2. o botão — posicione onde preferir; aqui, depois da área de compra
var alvo = document.querySelector(".vtex-flex-layout-0-x-flexRow--product-main") || document.body;
var btn = document.createElement("button");
btn.textContent = "Provar virtual";
btn.style.cssText = "margin:12px 0;padding:12px 22px;border:0;border-radius:8px;" +
"background:#b07a4f;color:#fff;font-size:15px;cursor:pointer";
alvo.appendChild(btn);
// 3. entrada da foto (galeria ou câmera do celular)
var input = document.createElement("input");
input.type = "file"; input.accept = "image/*"; input.hidden = true;
document.body.appendChild(input);
btn.onclick = function () { input.click(); };
// 4. reduz a 1024px ANTES de subir — o motor trabalha nesse tamanho
input.onchange = function () {
var f = input.files[0]; if (!f) return;
var img = new Image();
img.onload = function () {
var M = 1024, e = Math.min(1, M / Math.max(img.width, img.height));
var c = document.createElement("canvas");
c.width = img.width * e; c.height = img.height * e;
c.getContext("2d").drawImage(img, 0, 0, c.width, c.height);
provar(c.toDataURL("image/jpeg", 0.85));
};
var r = new FileReader();
r.onload = function () { img.src = r.result; };
r.readAsDataURL(f);
};
// 5. chamada + resultado (um retry, timeout 100 s)
function provar(fotoCliente, retentou) {
btn.disabled = true; btn.textContent = "Gerando sua prova…";
var ac = new AbortController();
var t = setTimeout(function () { ac.abort(); }, 100000);
fetch(API, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ images: [fotoCliente, fotoProduto],
tipo: /sol/i.test(document.title) ? "sol" : "grau" }),
signal: ac.signal
})
.then(function (r) { return r.json(); })
.then(function (d) {
clearTimeout(t);
if (d.status === "revisar") alert(d.aviso + "\n" + (d.recomendacao || ""));
else if (d.image) mostrar(d.image);
else alert("Não foi possível gerar agora. Tente novamente.");
})
.catch(function () {
clearTimeout(t);
if (!retentou) return provar(fotoCliente, true); // rede oscilou: 1 retry
alert("Conexão instável — verifique o sinal e tente de novo.");
})
.finally(function () { btn.disabled = false; btn.textContent = "Provar virtual"; });
}
// 6. resultado num overlay simples (troque pelo modal do tema de vocês)
function mostrar(uri) {
var o = document.createElement("div");
o.style.cssText = "position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.7);" +
"display:grid;place-items:center;padding:20px";
o.innerHTML = '<img src="' + uri + '" style="max-height:85vh;max-width:95vw;border-radius:12px">';
o.onclick = function () { o.remove(); };
document.body.appendChild(o);
}
})();
</script>
// VTEX — na PDP, usando a imagem que a página já exibe
const fotoProduto = document.querySelector(".vtex-store-components-3-x-productImageTag")?.src;
// converta a foto do cliente (input file/câmera) para data URI e chame:
const prova = await fetch("https://provador.paristeste.cloud/provar", {
method: "POST", headers: { "content-type": "application/json" },
body: JSON.stringify({
images: [fotoClienteDataURI, fotoProduto], // URL do produto também vale
tipo: skuEhSol ? "sol" : "grau",
}),
}).then(r => r.json());
Códigos de resposta — o que fazer com cada um
ok
Exiba image (WebP, vertical). Registre seed, qc.nota e segundos nos seus logs — com a seed qualquer prova é reproduzível.
revisar · sem_rosto
Não é erro: oriente com a mensagem de recomendacao (foto de frente, bem iluminada).
revisar · foto_dificil
O motor não conseguiu preservar a foto exatamente como é — peça uma foto mais afastada, rosto inteiro.
revisar · arma_na_foto
Objeto bloqueado por segurança. Exiba a recomendação.
HTTP 422
Corpo malformado — confira o JSON e os dois itens de images.
HTTP 503
Motor reiniciando — repita em ~1 minuto.
Boas práticas de integração
foto
Reduza para 1024 px no lado maior, JPEG qualidade 0,85, antes de enviar. O motor trabalha nesse tamanho — acima disso é upload pago à toa, e upload é o elo fraco no 4G.
rede
Timeout de 100 s + 1 retry automático. A geração leva 5–12 s; em horário de pico a fila pode chegar a ~1 min.
fila
O motor processa uma prova por vez (GPU dedicada). Desabilite o botão durante a chamada e não dispare em paralelo para o mesmo usuário.
conversa
revisar é orientação, não erro: sempre exiba aviso e recomendacao ao cliente.
privacidade
A foto do cliente é processada em memória e não é armazenada pelo motor. Na loja, só persista com consentimento (LGPD).
Operação e monitoramento
GET /health
Vivacidade + modelo + versão + GPU. Monitore a cada minuto; é o mesmo endpoint que valida um deploy.
sinais
segundos subindo = fila crescendo · taxa de revisar subindo = fotos ruins chegando (reforce o guia da foto) · qc.nota < 3 recorrente = acione a THM.
reprodução
Qualquer prova questionada: mande sku + seed para a THM — a mesma prova é regenerada bit a bit para análise.
atividade
O painel à direita mostra as chamadas desta sessão em tempo real, com tamanhos, tempos e seeds.
Comportamento
entrada
foto do usuário + imagem da armação (base64)
saída
sempre vertical; a foto do usuário é preservada — só a região dos óculos muda
seed
opcional — mesma seed reproduz o resultado
Segurança
conteudo_impróprio
status "revisar" — bloqueia nudez/violência antes de gerar
demais fotos
a prova é sempre tentada; se não ficar boa, o usuário refaz
Atividade ao vivo
As chamadas aparecem aqui conforme você usa a ferramenta.
Experimente as armações sem sair de casa
Escolha um modelo, use sua foto e veja como fica no seu rosto em segundos.
Sua foto
rosto de frente, bem iluminado, sem óculos · leva poucos segundos