Como transcrever reunião por API e virar ata com quem falou
Da gravação ao texto separado por falante, com o código que agrupa palavras em turnos. E onde a separação erra em reunião de verdade, que é sempre no mesmo lugar.
Gravação de reunião é o pior áudio que um sistema de transcrição recebe. Microfone longe, gente falando por cima, participante em rede ruim, cadeira arrastando. Ainda assim é o caso de uso mais pedido, porque ninguém quer escrever ata.
O caminho da gravação até a ata tem três partes: mandar o áudio pedindo separação de falantes, agrupar as palavras em turnos, e saber quais partes do resultado você pode confiar sem revisão.
Mandar a gravação
Se a gravação já está num bucket com URL pública, uma requisição resolve. Se ela
está na sua máquina ou num bucket privado, sobe pelo upload e você usa o
uploadId no lugar da url. Os dois caminhos estão em
envio de arquivos.
curl https://api.transcrevo.com/v1/transcripts \
-H "Authorization: Bearer $TRANSCREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/reuniao.mp3",
"speakers": 5,
"language": "pt",
"webhookUrl": "https://seu-servidor.com/hooks/transcrevo"
}'Três coisas nessa requisição merecem explicação.
speakers: 5 só deve ser informado quando você sabe. Numa reunião você
normalmente sabe: o convite tem a lista de participantes. E aí informar ajuda,
porque a contagem automática acerta o número exato em 146 de 216 arquivos
medidos. Mas chute errado é pior que não chutar: ele força a separação para a
contagem que você inventou, e o sistema passa a dividir uma voz em duas. Quando
você não tem a lista, mande true e deixe a decisão com quem está com o áudio.
language: "pt" evita que a detecção automática decida sozinha. Em reunião
com abertura curta ou muito ruído, informar o idioma erra menos.
webhookUrl existe porque reunião é longa. Uma gravação de duas horas leva
minutos para processar, e perguntar de três em três segundos são umas cem
requisições só para ouvir processing.
De palavras para turnos
A resposta vem como lista de palavras, cada uma com o rótulo do falante. Ata se
escreve em turnos. A conversão é um reduce:
type Word = { start: number; end: number; text: string; speaker: string | null };
type Turn = { speaker: string | null; start: number; end: number; text: string };
function turns(words: Word[]): Turn[] {
return words.reduce<Turn[]>((acc, word) => {
const last = acc.at(-1);
if (last !== undefined && last.speaker === word.speaker && word.start - last.end < 2) {
last.text += ` ${word.text}`;
last.end = word.end;
return acc;
}
acc.push({ speaker: word.speaker, start: word.start, end: word.end, text: word.text });
return acc;
}, []);
}A folga de 2 segundos é o que impede que uma pausa para respirar vire dois turnos da mesma pessoa. Aumente para reunião com muita hesitação, diminua para conversa rápida.
Com isso na mão a ata vira formatação:
[00:04:12] A: Então o prazo do fornecedor mudou para dezembro.
[00:04:31] C: Isso muda o cronograma da integração inteira?
[00:04:36] A: Muda a data de entrega, não o escopo.Os rótulos A e B são anônimos por natureza: significam "primeira voz" e
"segunda voz", nunca nomes. Amarrar rótulo a pessoa vem de fora do áudio. Numa
reunião gravada por uma ferramenta que registra ordem de entrada, ou numa que
grava uma faixa por participante, a amarração é confiável. Sem isso, o mais
honesto é deixar A e B na ata e o revisor batizar.
Onde isso erra em reunião de verdade
Medimos a diarização em 216 arquivos, 19,6 horas de fala com anotação humana. DER de 4,6% sem colar, 2,8% com colar de 0,25 s. Esse é o número bom. Os dois números ruins são exatamente os que reunião produz o dia inteiro:
| Situação | Acerto |
|---|---|
| Turno acima de 15 segundos | 95 a 99% |
| Turno abaixo de 5 segundos | 59 a 75% |
| Fala sobreposta | DER de 14,8%, contra 4,6% no geral |
A leitura prática disso é direta. A ata de conteúdo funciona. Quem defendeu o quê, qual foi a decisão, quem ficou com a tarefa: são blocos longos de fala, e o sistema acerta entre 95 e 99% deles.
A métrica de comportamento não funciona. Contar quantas vezes cada pessoa falou, quem interrompeu quem, quanto tempo cada um ocupou: essas contas vivem justamente dos "uhum", "sim", "concordo" de dois segundos, que é onde o acerto cai para a faixa de 59 a 75%. Um produto que promete esse tipo de análise a partir de gravação de sala está prometendo o que a fatia mais difícil do problema não entrega. O detalhamento completo, com JER e falso alarme separados, está em precisão e qualidade.
E quando duas pessoas falam ao mesmo tempo, o trecho recebe um rótulo só. Numa discussão acalorada, esse é o pedaço que o revisor vai reescrever.
O que melhora o resultado antes de sair da gravação
- Uma faixa por participante, quando a ferramenta de reunião permite. Aí não existe problema de diarização: você transcreve cada faixa separada e sabe de quem é. Custa o mesmo, porque a cobrança é por hora de áudio, e cinco faixas de uma hora são cinco horas.
glossarycom os nomes da empresa. Nome próprio, marca e jargão são o erro mais comum de qualquer sistema de transcrição, porque são as palavras que menos aparecem em treino. Uma reunião interna é feita disso: nome de projeto, nome de cliente, sigla. Mande{ "o que ele ouve": "o que escrever" }, até 100 entradas, e a correção vale só para aquele áudio.- Áudio da sala com um microfone só é o pior caso. Não há truque de API que resolva distância de microfone.
Guardar e apagar
Gravação de reunião costuma ter política de retenção, e ata de RH ou jurídico
quase sempre tem. DELETE /v1/transcripts/{id} apaga o texto, as palavras e o
áudio guardado; o registro de uso continua, porque é dele que sai a fatura, mas
o conteúdo some e não volta. Transcrição ainda em processing não pode ser
apagada: o resultado chegaria depois e repovoaria o que você apagou.
Vale lembrar que a saída não é reproduzível. Mandar o mesmo arquivo duas vezes
pode devolver transcritos ligeiramente diferentes, e não existe seed. Para
auditar uma reclamação sobre uma ata, guarde o transcrito que você entregou em
vez de gerar de novo.
A conta
US$ 0,05 por hora com separação de falantes, proporcional ao segundo. Uma reunião semanal de uma hora, o ano inteiro, custa US$ 2,60. Cem reuniões por mês numa empresa média, digamos 150 horas, custam US$ 7,50 por mês. É barato o suficiente para a decisão passar a ser sobre revisão humana, não sobre o preço da transcrição. Os limites e o desconto acima de 10.000 horas estão em preços e limites.