Skip to main content
Uma transcrição não é uma nota. Ela é a reunião de novo, só que mais demorada de ler do que foi de assistir. O que as pessoas realmente querem depois é curto: o que decidimos, quem se comprometeu a fazer o quê, e o que ainda está em aberto. Este tutorial constrói isso e liga cada item de volta ao segundo em que foi dito, para você poder ouvir a parte com a qual discorda:
Ao longo do caminho, vamos:
  1. Transcrever uma gravação com /audio/transcriptions
  2. Pedir marcações de tempo, que nem todo modelo entrega
  3. Extrair decisões e itens de ação contra um schema
  4. Lidar com o fato de a transcrição nunca dizer quem está falando
  5. Dividir uma gravação longa sem perder o relógio

Configuração

Você precisa do Python 3.9 ou superior, do pacote requests e de uma chave da API Venice. Veja Gerando uma Chave de API caso ainda não tenha uma. Traga qualquer gravação de uma conversa, em wav, mp3, m4a, flac, aac, mp4, ogg ou webm.

1. Transcreva a gravação

/audio/transcriptions é compatível com OpenAI e aceita um upload multipart. O arquivo tem que ser uma parte de arquivo de verdade, já que base64 não é aceito nesse endpoint.
A transcrição é cobrada pela duração do áudio, não pelo quanto foi dito nele, o que torna o custo de uma reunião fácil de prever antes mesmo de executar: Chame GET /models?type=asr para a lista atual, em vez de fixar esses valores, já que o catálogo muda.

2. Peça marcações de tempo

Timestamps são o que torna as notas verificáveis, então essa é a escolha que mais importa, e o padrão não vai te dar isso:
nvidia/parakeet-tdt-0.6b-v3 é o modelo padrão, e ele aceita timestamps=true e depois ignora o parâmetro. Não há erro nem aviso, apenas uma resposta contendo somente text. Se você precisa das marcações, peça um modelo que as retorne e verifique se a chave está presente.
Quando um modelo retorna marcações, timestamps é um objeto em vez de uma lista, e a chave dentro dele depende do modelo. O Whisper agrupa por frase, o Scribe por palavra:
Segmentos no nível de frase são o tamanho certo para esse trabalho. Marcações por palavra são úteis para legendas e são finas demais para pendurar uma decisão nelas. Vamos achatar esses segmentos em linhas com um tempo na frente de cada uma, que é tudo de que o modelo precisa para citá-las depois:

3. Extraia as notas

Descreva as notas que você quer como um schema, para que o resultado seja um registro em vez de prosa que você tem que parsear:
disable_thinking está aí pela mesma razão que cabe em qualquer passo de extração. O schema já decide o formato da resposta, então pagar um modelo de raciocínio para deliberar sobre isso não compra nada e faz com que o custo de cada execução seja diferente do anterior. Extraindo Dados Estruturados de Documentos mede essa diferença. Rode em uma daily de cinquenta e três segundos e as notas voltam com o relógio anexado:
Todo spoken_at é real. Pule para 19,6 segundos e você ouve a frase que criou a tarefa.
Dê ao modelo linhas sem tempos e todo spoken_at volta como 0. O campo é obrigatório, o modelo não tem nada para colocar nele, e um campo obrigatório é uma instrução para produzir algo, não um convite para dizer que não sabe. Vale lembrar disso sempre que um schema parecer estar funcionando: o formato estar certo não é a mesma coisa que os valores estarem certos.

4. Ninguém está identificado

Duas coisas nessa saída estão erradas, e ambas vêm do mesmo lugar. A dona do rollout é May. O nome dela é Mei. Reconhecimento de fala é menos confiável em substantivos próprios, e nomes são exatamente o que a atribuição precisa, então essa é a falha que você deve esperar em vez da azarada. O último item ficou como unassigned, embora alguém claramente tenha assumido. A linha foi “I’ll ask legal today and report back tomorrow”, e a transcrição registra as palavras sem registrar quem as disse. Esse segundo caso não é um bug que você consiga consertar. Nenhum modelo de transcrição da Venice faz diarização, então não existe um campo speaker para consultar em qualquer um deles. A transcrição é um fluxo de texto sem voz, e tarefas só podem ser atribuídas quando um nome é dito em voz alta, como em “Tomas, can you put the deprecation notice in the changelog”. O primeiro caso você pode consertar, contando ao modelo quem estava na sala:
May resolve para Mei Lin porque o modelo agora tem uma lista curta para casar, e os responsáveis têm nomes completos que seu tracker de tarefas pode buscar. O terceiro item continua sem responsável, corretamente. Uma lista de participantes corrige uma escuta errada, e nada recupera informação que a gravação nunca carregou.
Se você precisa de atribuição real de quem falou, capture isso na fonte em vez de inferir na saída. Ferramentas de conferência conseguem gravar uma faixa por participante, e transcrever cada faixa separadamente te dá os falantes de graça, ao custo de uma requisição por pessoa.

5. Maior do que uma requisição

Uploads são limitados a 25 MB, o que chega mais rápido do que você imagina para áudio não comprimido, e uma reunião longa vale a pena dividir de qualquer forma, para que uma falha não custe a transcrição inteira. Para arquivos WAV a biblioteca padrão basta, sem precisar de ffmpeg:
O offset é o ponto principal. Cada pedaço é transcrito como se começasse em zero, então as marcações têm que ser deslocadas de volta para a linha do tempo da gravação original antes que o modelo as veja. É para isso que serve o argumento offset em timed_lines:
Divida a mesma daily em pedaços de vinte segundos e o relógio se mantém honesto ao longo das emendas. As palavras, não:
Uma única frase foi dita ali: “Tomas, can you put the deprecation notice in the changelog by Friday?” O corte caiu no meio dela, então o nome foi para uma requisição e a pergunta foi para outra. O Whisper ouviu o nome órfão como uma pergunta, inventou um awesome. para preencher a lacuna no fim do chunk, e transformou uma linha em três. As marcações ainda estão corretas, e o passo de notas ainda encontra a tarefa. O que ele perde é o nome, que é aquilo de que a atribuição depende.
Dividir por duração fixa corta alguém em cada fronteira. Vinte segundos é curto o suficiente para acertar uma frase quase sempre; dez minutos torna isso raro, mas não impossível, e vai eventualmente cair justo na frase que atribui o trabalho. Dividir em silêncios evita o problema como deveria e exige uma ferramenta que consiga encontrar as pausas, como ffmpeg ou pydub. Divida apenas quando o arquivo realmente exigir.
Formatos comprimidos não podem ser fatiados assim, já que você não consegue cortar um MP3 em uma fronteira de frame com a biblioteca padrão. Use ffmpeg para esses:

Juntando tudo

Próximos passos

Speech-to-Text

Referência para o endpoint de transcrições.

Extraindo Dados Estruturados de Documentos

A mesma extração orientada a schema, aplicada a arquivos.

Respostas Estruturadas

Como o json_schema restringe uma completion.

Clonagem de Voz

Dê ao resumo uma voz própria.