{"id":571,"date":"2026-07-31T13:49:24","date_gmt":"2026-07-31T16:49:24","guid":{"rendered":"https:\/\/carloslopes.programandosolucoes.com.br\/index.php\/portfolio-analise-audio\/"},"modified":"2026-08-05T17:05:20","modified_gmt":"2026-08-05T20:05:20","slug":"portfolio-analise-audio","status":"publish","type":"page","link":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/portfolio-analise-audio\/","title":{"rendered":"An\u00e1lise de Qualidade de Chamadas por Processamento de Sinais"},"content":{"rendered":"<style>\n.pf-wrap{max-width:1100px;margin:0 auto;font-size:16px;line-height:1.65}\n.pf-chamada{font-size:1.15rem;opacity:.85;margin:0 0 2rem}\n.pf-grade{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:1.5rem}\n.pf-card{border:1px solid rgba(128,128,128,.3);border-radius:10px;overflow:hidden;display:flex;flex-direction:column;transition:transform .15s ease,box-shadow .15s ease}\n.pf-card:hover{transform:translateY(-3px);box-shadow:0 8px 24px rgba(0,0,0,.12)}\n.pf-card img{width:100%;height:180px;object-fit:cover;display:block;background:rgba(128,128,128,.12)}\n.pf-card-corpo{padding:1rem 1.1rem 1.2rem;display:flex;flex-direction:column;gap:.6rem;flex:1}\n.pf-card h3{margin:0;font-size:1.05rem;line-height:1.35}\n.pf-card p{margin:0;font-size:.92rem;opacity:.85;flex:1}\n.pf-chips{display:flex;flex-wrap:wrap;gap:.35rem}\n.pf-chip{font-size:.75rem;padding:.18rem .55rem;border-radius:999px;border:1px solid rgba(128,128,128,.35);opacity:.9}\n.pf-meta{font-size:.8rem;opacity:.7}\n.pf-cadeado{font-size:.8rem;opacity:.75}\n.pf-hero{margin:0 0 1.5rem}\n.pf-hero h1{margin:0 0 .4rem;line-height:1.2}\n.pf-secao{margin:2rem 0}\n.pf-secao h2{font-size:1.15rem;margin:0 0 .6rem;text-transform:uppercase;letter-spacing:.06em;opacity:.75}\n.pf-galeria{display:grid;gap:1.2rem;margin:2rem 0}\n.pf-galeria figure{margin:0}\n.pf-galeria img{width:100%;border:1px solid rgba(128,128,128,.3);border-radius:8px;display:block}\n.pf-galeria figcaption{font-size:.85rem;opacity:.75;margin-top:.4rem}\n.pf-repo{border:1px solid rgba(128,128,128,.35);border-left-width:4px;border-radius:8px;padding:1rem 1.2rem;margin:2rem 0}\n.pf-repo h2{margin:0 0 .5rem;font-size:1rem;text-transform:uppercase;letter-spacing:.06em}\n.pf-repo pre{background:rgba(128,128,128,.12);padding:.7rem .9rem;border-radius:6px;overflow-x:auto;margin:.6rem 0;font-size:.85rem}\n.pf-contato{margin:2rem 0;padding-top:1.2rem;border-top:1px solid rgba(128,128,128,.3);font-size:.95rem}\n.pf-voltar{display:inline-block;margin-bottom:1rem;font-size:.9rem}\n@media (max-width:600px){.pf-card img{height:150px}}\n<\/style>\n<div class=\"pf-wrap\">\n  <a class=\"pf-voltar\" href=\"\/index.php\/portfolio-frontend\/\">\u2190 voltar ao portf\u00f3lio<\/a><\/p>\n<header class=\"pf-hero\">\n<p class=\"pf-meta\">07\/2026 &#8211; atual \u00b7 3 meses<\/p>\n<p>Detecta picote, dropout e falha de \u00e1udio em grava\u00e7\u00f5es de chamadas por processamento de sinais \u2014 sem depender de transcri\u00e7\u00e3o.<\/p>\n<div class=\"pf-chips\"><span class=\"pf-chip\">Python 3.14<\/span><span class=\"pf-chip\">NumPy<\/span><span class=\"pf-chip\">FFT<\/span><span class=\"pf-chip\">ITU-T G.107<\/span><span class=\"pf-chip\">Flask<\/span><span class=\"pf-chip\">SQLite WAL<\/span><span class=\"pf-chip\">faster-whisper<\/span><span class=\"pf-chip\">llama.cpp<\/span><span class=\"pf-chip\">ONNX Runtime<\/span><span class=\"pf-chip\">ffmpeg<\/span><span class=\"pf-chip\">Docker<\/span><span class=\"pf-chip\">gunicorn<\/span><span class=\"pf-chip\">DNSMOS P.835<\/span><span class=\"pf-chip\">NISQA<\/span><span class=\"pf-chip\">SQUIM<\/span><\/div>\n<\/header>\n<section class=\"pf-secao\">\n<h2>O problema<\/h2>\n<p>Quando o cliente reclama que &quot;a liga\u00e7\u00e3o estava picotando&quot;, n\u00e3o h\u00e1 prova: a opera\u00e7\u00e3o s\u00f3 tem a grava\u00e7\u00e3o e a percep\u00e7\u00e3o de quem ouviu. Transcrever tudo com IA \u00e9 caro, lento e n\u00e3o mede qualidade de \u00e1udio, mede palavra.<\/p>\n<\/section>\n<section class=\"pf-secao\">\n<h2>A arquitetura<\/h2>\n<p>Todo o DSP \u00e9 NumPy: energia RMS por frame de 20 ms com hop de 10 ms convertida em dBFS, janelas deslizantes vetorizadas, e estimativa de ru\u00eddo de fundo por percentil \u2014 que \u00e9 o discriminador que separa picote de pausa natural na conversa. A an\u00e1lise espectral usa FFT para spectral flatness. O E-model da ITU-T G.107, que converte fator R em MOS, foi implementado do zero. O decodificador de \u00e1udio \u00e9 o ffmpeg, escolhido em vez da libsndfile por preservar os canais separados, o que \u00e9 essencial para detectar \u00e1udio em uma via s\u00f3. Onde h\u00e1 IA, ela roda local em CPU: faster-whisper em int8 e um LLM GGUF via llama.cpp, sem mandar \u00e1udio de cliente para fora. A decis\u00e3o de n\u00e3o usar rede neural para a nota de qualidade n\u00e3o foi por prefer\u00eancia: foi medida. Um corpus real de telefonia em 8 kHz foi rotulado em quatro categorias \u2014 chamada boa, picote, queda e ru\u00eddo \u2014 e quatro modelos foram comparados pela separa\u00e7\u00e3o que cada um produz entre a categoria boa e cada categoria ruim. O painel \u00e9 Flask com SQLite em modo WAL e uma SPA em JavaScript puro, sem build.<\/p>\n<\/section>\n<section class=\"pf-secao\">\n<h2>O resultado<\/h2>\n<p>Ferramenta multi-tenant com isolamento f\u00edsico por cliente, rodando em Docker com gunicorn e systemd. A valida\u00e7\u00e3o \u00e9 por inje\u00e7\u00e3o: o selftest insere picote e clipping em sinal sint\u00e9tico e confere se a detec\u00e7\u00e3o pega, o que testa o DSP sem depender do PABX. O comparativo de modelos neurais exp\u00f4s duas coisas. A primeira \u00e9 t\u00e9cnica: os modelos neurais s\u00e3o cegos a sil\u00eancio, porque avaliam a qualidade da fala presente e n\u00e3o penalizam um trecho mudo \u2014 por isso o E-model pr\u00f3prio separa queda por 3,39 contra 0,17 do melhor neural. A segunda \u00e9 de licenciamento: o NISQA \u00e9 o melhor detector de picote medido, com separa\u00e7\u00e3o 1,00, e mesmo assim n\u00e3o pode entrar no produto porque os pesos s\u00e3o CC BY-NC. Escolher modelo aqui foi decis\u00e3o t\u00e9cnica e jur\u00eddica ao mesmo tempo, e ficou registrada.<\/p>\n<\/section>\n<div class=\"pf-galeria\">\n<figure>\n      <img decoding=\"async\" src=\"https:\/\/carloslopes.programandosolucoes.com.br\/wp-content\/uploads\/portfolio\/analise-audio-01-relatorio.png\" alt=\"Relat\u00f3rio de an\u00e1lise: eventos de picote e dropout por chamada\" loading=\"lazy\"><figcaption>Relat\u00f3rio de an\u00e1lise: eventos de picote e dropout por chamada<\/figcaption><\/figure>\n<figure>\n      <img decoding=\"async\" src=\"https:\/\/carloslopes.programandosolucoes.com.br\/wp-content\/uploads\/portfolio\/analise-audio-02-detalhe.png\" alt=\"Detalhe da chamada, com as m\u00e9tricas de sinal\" loading=\"lazy\"><figcaption>Detalhe da chamada, com as m\u00e9tricas de sinal<\/figcaption><\/figure>\n<figure>\n      <img decoding=\"async\" src=\"https:\/\/carloslopes.programandosolucoes.com.br\/wp-content\/uploads\/portfolio\/analise-audio-03-comparativo.png\" alt=\"O comparativo que decidiu a arquitetura: qual modelo detecta o qu\u00ea, e qual pode ir para o produto\" loading=\"lazy\"><figcaption>O comparativo que decidiu a arquitetura: qual modelo detecta o qu\u00ea, e qual pode ir para o produto<\/figcaption><\/figure>\n<\/p><\/div>\n<div class=\"pf-repo\">\n<h2>\ud83d\udd12 C\u00f3digo-fonte<\/h2>\n<pre><code>git clone https:\/\/git.programandosolucoes.com.br\/git\/repos\/analisador-chamadas.git<\/code><\/pre>\n<p>C\u00f3digo-fonte privado. As credenciais de leitura s\u00e3o liberadas sob solicita\u00e7\u00e3o \u2014 me chame para conversar sobre o projeto.<\/p>\n<\/p><\/div>\n<div class=\"pf-contato\">\n    <strong>Carlos Alberto<\/strong> \u2014 carlosalberto4ti@gmail.com \u00b7 +55 11 2615-2880\n  <\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u2190 voltar ao portf\u00f3lio 07\/2026 &#8211; atual \u00b7 3 meses Detecta picote, dropout e falha de \u00e1udio em grava\u00e7\u00f5es de chamadas por processamento de sinais \u2014 sem depender de transcri\u00e7\u00e3o. Python 3.14NumPyFFTITU-T G.107FlaskSQLite WALfaster-whisperllama.cppONNX RuntimeffmpegDockergunicornDNSMOS P.835NISQASQUIM O problema Quando o cliente reclama que &quot;a liga\u00e7\u00e3o estava picotando&quot;, n\u00e3o h\u00e1 prova: a opera\u00e7\u00e3o s\u00f3 tem a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-571","page","type-page","status-publish","hentry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"br","enabled_languages":["en","br","it"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"br":{"title":false,"content":false,"excerpt":false},"it":{"title":false,"content":false,"excerpt":false}}},"_links":{"self":[{"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/pages\/571","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/comments?post=571"}],"version-history":[{"count":2,"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/pages\/571\/revisions"}],"predecessor-version":[{"id":606,"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/pages\/571\/revisions\/606"}],"wp:attachment":[{"href":"https:\/\/carloslopes.programandosolucoes.com.br\/br\/index.php\/wp-json\/wp\/v2\/media?parent=571"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}