Transcrição de Chamadas Estéreo com Diarização
Quando você grava chamadas em formato estéreo—com cada falante em um canal de áudio separado—você consegue 100% de precisão na identificação de falantes. Este guia mostra como transcrever gravações estéreo, identificar falantes automaticamente e extrair insights estruturados das suas chamadas.
Por que Diarização Estéreo?
| Aspecto | Diarização Padrão | Diarização Estéreo |
|---|---|---|
| Identificação de falante | Detecção por IA | Baseada em canal (L/R) |
| Precisão | Boa | Perfeita (100%) |
| Performance | Normal | Mais rápida |
| Labels de falante | SPEAKER 1, SPEAKER 2... | SPEAKER_L, SPEAKER_R |
| Ideal para | Áudio mono, reuniões | Gravações de call center |
Ideal para Call Centers
A maioria dos sistemas PBX (FreeSWITCH, Asterisk) pode gravar chamadas em estéreo com cada parte em um canal separado. Isso elimina qualquer incerteza na identificação de falantes.
Pré-requisitos
- Arquivo de áudio estéreo: MP3, WAV ou outro formato suportado com falantes em canais separados
- Chave de API SipPulse AI: Obtenha a sua em sippulse.ai
- Acesso ao modelo Pro:
pulse-precision-pro
Modelo para Diarização Estéreo
O modelo pulse-precision-pro suporta diarização estéreo e mono:
| Modelo | Velocidade | Precisão | Ideal Para |
|---|---|---|---|
pulse-precision-pro | Otimizada | Máxima | Transcrições estéreo críticas de qualidade |
Recursos do Modelo Pro
O modelo pulse-precision-pro inclui recursos avançados:
- Diarização estéreo: 100% de precisão na identificação de falantes baseada em canal
- VAD preset: Use
vad_preset=telephonypara áudio otimizado de banda estreita 8kHz - Máxima precisão: Melhor Word Error Rate (WER) para analytics de call center
Passo 1: Prepare seu Áudio
Para que a diarização estéreo funcione corretamente, seu áudio deve ter:
- Canal esquerdo (L): Um falante (ex: o cliente)
- Canal direito (R): Outro falante (ex: o atendente)
Configuração de Gravação
A maioria dos sistemas PBX suporta gravação estéreo:
- FreeSWITCH: Use
RECORD_STEREO=trueno seu dialplan - Asterisk: Configure MixMonitor com a opção
Dpara estéreo
Consistência de Canal
Garanta uma atribuição consistente de canais em todas as gravações. Documente se os clientes estão sempre no canal esquerdo ou direito para análise precisa.
Passo 2: Transcreva com Diarização Estéreo
Use o endpoint /v1/asr/transcribe com response_format=stereo_diarization e um dos modelos Pro.
curl -X POST 'https://api.sippulse.ai/v1/asr/transcribe' \
-H 'api-key: $SIPPULSE_API_KEY' \
-F 'file=@gravacao-chamada.mp3' \
-F 'model=pulse-precision-pro' \
-F 'response_format=stereo_diarization' \
-F 'language=pt' \
-F 'vad_preset=telephony'import FormData from "form-data";
import fs from "fs";
async function transcreverChamadaEstereo(
caminhoArquivo: string
): Promise<TranscricaoEstereo> {
const form = new FormData();
form.append("file", fs.createReadStream(caminhoArquivo));
form.append("model", "pulse-precision-pro");
form.append("response_format", "stereo_diarization");
form.append("language", "pt");
form.append("vad_preset", "telephony"); // Otimizado para chamadas telefônicas
const response = await fetch("https://api.sippulse.ai/v1/asr/transcribe", {
method: "POST",
headers: {
"api-key": process.env.SIPPULSE_API_KEY!,
},
body: form,
});
if (!response.ok) {
throw new Error(`Erro na API: ${response.status}`);
}
return response.json();
}
interface TranscricaoEstereo {
text: string;
segments: Array<{
speaker: "SPEAKER_L" | "SPEAKER_R";
text: string;
initial_time: number;
end_time: number;
}>;
words: Array<{
word: string;
speaker: "SPEAKER_L" | "SPEAKER_R";
start: number;
end: number;
}>;
}import os
import requests
def transcrever_chamada_estereo(caminho_arquivo: str) -> dict:
"""
Transcreve uma gravação de chamada estéreo com diarização de falantes.
Args:
caminho_arquivo: Caminho para o arquivo de áudio estéreo
Returns:
Transcrição com segmentos e palavras rotulados por falante
"""
with open(caminho_arquivo, "rb") as arquivo_audio:
response = requests.post(
"https://api.sippulse.ai/v1/asr/transcribe",
headers={"api-key": os.getenv("SIPPULSE_API_KEY")},
files={"file": arquivo_audio},
data={
"model": "pulse-precision-pro",
"response_format": "stereo_diarization",
"language": "pt",
"vad_preset": "telephony", # Otimizado para chamadas telefônicas
},
)
response.raise_for_status()
return response.json()Passo 3: Entenda a Resposta
A resposta da diarização estéreo inclui três componentes principais:
Estrutura da Resposta
{
"text": "00:02-00:05 | SPEAKER L:\nOlá, como posso ajudá-lo hoje?\n\n00:05-00:08 | SPEAKER R:\nOi, estou ligando sobre minha conta...",
"segments": [
{
"speaker": "SPEAKER_L",
"text": "Olá, como posso ajudá-lo hoje?",
"initial_time": 2.1,
"end_time": 5.3
},
{
"speaker": "SPEAKER_R",
"text": "Oi, estou ligando sobre minha conta...",
"initial_time": 5.5,
"end_time": 8.2
}
],
"words": [
{
"word": "Olá,",
"speaker": "SPEAKER_L",
"start": 2.1,
"end": 2.5
},
{
"word": "como",
"speaker": "SPEAKER_L",
"start": 2.5,
"end": 2.7
}
]
}Campos Principais
| Campo | Descrição |
|---|---|
text | Transcrição formatada com timestamps e labels de falante |
segments | Array de segmentos de fala com falante, texto e timing |
words | Timestamps em nível de palavra com atribuição de falante |
speaker | SPEAKER_L (canal esquerdo) ou SPEAKER_R (canal direito) |
Passo 4: Analise com Análise Estruturada
Após a transcrição, use Análise Estruturada para extrair insights da conversação.
Configurando sua Análise
- Navegue até Análise Estruturada no dashboard do SipPulse AI
- Crie uma nova análise ou selecione um preset existente como "Análise de Conversação"
- Configure seu schema com os campos que deseja extrair
- Copie o ID da Análise usando o botão de copiar ao lado do nome da análise
O template Análise de Conversação extrai:
- Total de perguntas e taxa de resposta
- Se a chamada atingiu seu objetivo (venda, resolução, etc.)
- Nível de interesse do cliente (0-1)
- Principais objeções e se foram resolvidas
- Tom do atendimento e nível de empatia
- Score geral de sucesso (0-1)
- Recomendações de melhoria
Execute a Análise via API
Use o ID da Análise copiado para executar a análise programaticamente:
interface AnaliseConversacao {
total_perguntas: number;
perguntas_respondidas: string[];
taxa_resposta: number;
venda_realizada: boolean;
interesse_cliente: number;
objecoes_principais: string[];
objecoes_resolvidas: boolean;
tom_atendimento: string;
nivel_empatia: number;
pontuacao_geral: number;
recomendacoes: string[];
proximos_passos: string;
}
async function analisarConversacao(
analiseId: string,
textoTranscricao: string
): Promise<AnaliseConversacao> {
const response = await fetch(
`https://api.sippulse.ai/v1/structured-analyses/${analiseId}/execute`,
{
method: "POST",
headers: {
"api-key": process.env.SIPPULSE_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: textoTranscricao,
}),
}
);
if (!response.ok) {
throw new Error(`Erro na API: ${response.status}`);
}
const resultado = await response.json();
return resultado.content;
}import os
import requests
from typing import TypedDict
class AnaliseConversacao(TypedDict):
total_perguntas: int
perguntas_respondidas: list[str]
taxa_resposta: float
venda_realizada: bool
interesse_cliente: float
objecoes_principais: list[str]
objecoes_resolvidas: bool
tom_atendimento: str
nivel_empatia: float
pontuacao_geral: float
recomendacoes: list[str]
proximos_passos: str
def analisar_conversacao(
analise_id: str,
texto_transcricao: str
) -> AnaliseConversacao:
"""
Analisa uma transcrição de chamada usando Análise Estruturada.
Args:
analise_id: ID do preset de Análise de Conversação
texto_transcricao: O texto da transcrição formatada
Returns:
Resultados da análise estruturada
"""
response = requests.post(
f"https://api.sippulse.ai/v1/structured-analyses/{analise_id}/execute",
headers={
"api-key": os.getenv("SIPPULSE_API_KEY"),
"Content-Type": "application/json",
},
json={"content": texto_transcricao},
)
response.raise_for_status()
return response.json()["content"]Exemplo Completo: Pipeline End-to-End
Aqui está um exemplo completo que transcreve uma chamada estéreo e a analisa:
import FormData from "form-data";
import fs from "fs";
async function processarGravacaoChamada(
caminhoAudio: string,
analiseId: string
) {
// Passo 1: Transcrever com diarização estéreo
console.log("Transcrevendo áudio...");
const form = new FormData();
form.append("file", fs.createReadStream(caminhoAudio));
form.append("model", "pulse-precision-pro");
form.append("response_format", "stereo_diarization");
form.append("language", "pt");
form.append("vad_preset", "telephony");
const respostaTranscricao = await fetch(
"https://api.sippulse.ai/v1/asr/transcribe",
{
method: "POST",
headers: { "api-key": process.env.SIPPULSE_API_KEY! },
body: form,
}
);
const transcricao = await respostaTranscricao.json();
console.log(`Transcreveu ${transcricao.segments.length} segmentos`);
// Passo 2: Analisar a conversação
console.log("Analisando conversação...");
const respostaAnalise = await fetch(
`https://api.sippulse.ai/v1/structured-analyses/${analiseId}/execute`,
{
method: "POST",
headers: {
"api-key": process.env.SIPPULSE_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({ content: transcricao.text }),
}
);
const analise = await respostaAnalise.json();
// Passo 3: Retornar resultados combinados
return {
transcricao: {
text: transcricao.text,
segments: transcricao.segments,
quantidadeFalantes: 2,
},
analise: analise.content,
};
}
// Uso - obtenha o analiseId do dashboard clicando no botão de copiar
const resultado = await processarGravacaoChamada(
"./gravacoes/chamada-suporte.mp3",
"sa_abc123def456" // Seu ID de Análise do dashboard
);
console.log("Score Geral:", resultado.analise.pontuacao_geral);
console.log("Interesse do Cliente:", resultado.analise.interesse_cliente);
console.log("Recomendações:", resultado.analise.recomendacoes);import os
import requests
def processar_gravacao_chamada(caminho_audio: str, analise_id: str) -> dict:
"""
Pipeline completo: transcreve chamada estéreo e analisa.
Args:
caminho_audio: Caminho para o arquivo de áudio estéreo
analise_id: ID do preset de Análise de Conversação (copie do dashboard)
Returns:
Resultados combinados de transcrição e análise
"""
api_key = os.getenv("SIPPULSE_API_KEY")
# Passo 1: Transcrever com diarização estéreo
print("Transcrevendo áudio...")
with open(caminho_audio, "rb") as arquivo_audio:
resposta_transcricao = requests.post(
"https://api.sippulse.ai/v1/asr/transcribe",
headers={"api-key": api_key},
files={"file": arquivo_audio},
data={
"model": "pulse-precision-pro",
"response_format": "stereo_diarization",
"language": "pt",
"vad_preset": "telephony",
},
)
resposta_transcricao.raise_for_status()
transcricao = resposta_transcricao.json()
print(f"Transcreveu {len(transcricao['segments'])} segmentos")
# Passo 2: Analisar a conversação
print("Analisando conversação...")
resposta_analise = requests.post(
f"https://api.sippulse.ai/v1/structured-analyses/{analise_id}/execute",
headers={
"api-key": api_key,
"Content-Type": "application/json",
},
json={"content": transcricao["text"]},
)
resposta_analise.raise_for_status()
analise = resposta_analise.json()
# Passo 3: Retornar resultados combinados
return {
"transcricao": {
"text": transcricao["text"],
"segments": transcricao["segments"],
"quantidade_falantes": 2,
},
"analise": analise["content"],
}
if __name__ == "__main__":
# Obtenha o analise_id do dashboard clicando no botão de copiar
resultado = processar_gravacao_chamada(
"./gravacoes/chamada-suporte.mp3",
"sa_abc123def456" # Seu ID de Análise do dashboard
)
print(f"Score Geral: {resultado['analise']['pontuacao_geral']}")
print(f"Interesse do Cliente: {resultado['analise']['interesse_cliente']}")
print(f"Recomendações: {resultado['analise']['recomendacoes']}")Exemplo de Saída
Veja como a resposta completa fica para uma chamada de suporte:
{
"transcricao": {
"text": "00:00-00:03 | SPEAKER L:\nObrigado por ligar para o Suporte TechCorp, meu nome é Ana. Como posso ajudar?\n\n00:03-00:09 | SPEAKER R:\nOi Ana, estou tendo problemas para entrar na minha conta. Aparece que a senha está incorreta, mas tenho certeza que estou digitando certo.\n\n00:09-00:15 | SPEAKER L:\nSinto muito por esse inconveniente. Vou te ajudar com isso. Pode me informar o email associado à sua conta?\n\n00:15-00:18 | SPEAKER R:\nClaro, é joao.silva@email.com.\n\n00:18-00:25 | SPEAKER L:\nObrigada, João. Estou vendo sua conta aqui. Parece que houve várias tentativas de login, então a conta foi bloqueada temporariamente por segurança.\n\n00:25-00:28 | SPEAKER R:\nAh, isso explica. Como faço para desbloquear?\n\n00:28-00:38 | SPEAKER L:\nPosso desbloquear para você agora mesmo. Também vou enviar um link de redefinição de senha para seu email. Você deve receber nos próximos minutos. Posso ajudar em mais alguma coisa?\n\n00:38-00:42 | SPEAKER R:\nNão, era só isso mesmo. Muito obrigado pela ajuda, Ana!\n\n00:42-00:45 | SPEAKER L:\nDe nada, João! Tenha um ótimo dia!",
"segments": [
{
"speaker": "SPEAKER_L",
"text": "Obrigado por ligar para o Suporte TechCorp, meu nome é Ana. Como posso ajudar?",
"initial_time": 0.0,
"end_time": 3.2
},
{
"speaker": "SPEAKER_R",
"text": "Oi Ana, estou tendo problemas para entrar na minha conta. Aparece que a senha está incorreta, mas tenho certeza que estou digitando certo.",
"initial_time": 3.5,
"end_time": 9.1
},
{
"speaker": "SPEAKER_L",
"text": "Sinto muito por esse inconveniente. Vou te ajudar com isso. Pode me informar o email associado à sua conta?",
"initial_time": 9.4,
"end_time": 15.0
},
{
"speaker": "SPEAKER_R",
"text": "Claro, é joao.silva@email.com.",
"initial_time": 15.2,
"end_time": 18.0
},
{
"speaker": "SPEAKER_L",
"text": "Obrigada, João. Estou vendo sua conta aqui. Parece que houve várias tentativas de login, então a conta foi bloqueada temporariamente por segurança.",
"initial_time": 18.3,
"end_time": 25.5
},
{
"speaker": "SPEAKER_R",
"text": "Ah, isso explica. Como faço para desbloquear?",
"initial_time": 25.8,
"end_time": 28.2
},
{
"speaker": "SPEAKER_L",
"text": "Posso desbloquear para você agora mesmo. Também vou enviar um link de redefinição de senha para seu email. Você deve receber nos próximos minutos. Posso ajudar em mais alguma coisa?",
"initial_time": 28.5,
"end_time": 38.0
},
{
"speaker": "SPEAKER_R",
"text": "Não, era só isso mesmo. Muito obrigado pela ajuda, Ana!",
"initial_time": 38.3,
"end_time": 42.0
},
{
"speaker": "SPEAKER_L",
"text": "De nada, João! Tenha um ótimo dia!",
"initial_time": 42.2,
"end_time": 45.0
}
],
"quantidade_falantes": 2
},
"analise": {
"total_perguntas": 3,
"perguntas_respondidas": [
"Como posso ajudar?",
"Pode me informar o email?",
"Posso ajudar em mais alguma coisa?"
],
"taxa_resposta": 1.0,
"venda_realizada": false,
"interesse_cliente": 0.75,
"objecoes_principais": [],
"objecoes_resolvidas": true,
"tom_atendimento": "profissional, amigável e empático",
"nivel_empatia": 0.9,
"conhecimento_tecnico": 0.85,
"pontuacao_geral": 0.92,
"recomendacoes": [
"Considerar oferecer dicas proativas de segurança",
"Mencionar tempo estimado para email de redefinição"
],
"proximos_passos": "Cliente receberá email de redefinição e recuperará acesso à conta"
}
}Melhores Práticas
Qualidade do Áudio
- Taxa de amostragem: 16kHz ou superior para melhores resultados (áudio de telefonia 8kHz também é suportado)
- Profundidade de bits: Mínimo de 16 bits
- Formato: MP3 ou WAV funcionam bem
Atribuição de Canal
- Seja consistente: Sempre atribua a mesma parte ao mesmo canal
- Documente: Registre se os atendentes estão no L ou R na sua configuração
- Mapeie falantes: Na sua aplicação, mapeie
SPEAKER_L/SPEAKER_Rpara labels significativos (Atendente/Cliente)
Escolhendo a Abordagem Certa
| Cenário | Modelo Recomendado | Response Format |
|---|---|---|
| Gravações de chamadas estéreo | pulse-precision-pro | stereo_diarization |
| Gravações mono com múltiplos falantes | pulse-precision-pro | diarization |
Dicas de Performance
- Use
vad_preset=telephony: Otimizado para características de áudio de chamadas telefônicas - Processamento em lote: Para grandes volumes, processe arquivos em paralelo
- Combine com anonimização: Adicione
anonymize=truepara remover PII automaticamente
Próximos Passos
- Análise Estruturada - Crie schemas de análise personalizados
- Modelos Speech-to-Text - Explore todas as opções de STT
- Análise Avançada de Chamadas - Pipeline de processamento multi-etapas
- Rastreamento de Requisições - Monitore o uso da API
