Не может отключить микрофон на вызове TwilioJavascript

Форум по Javascript
Ответить
Anonymous
 Не может отключить микрофон на вызове Twilio

Сообщение Anonymous »

Я внедряю экран для звонков из службы Twilio: < /p>
На данный момент вызовы Connect Connect, и я могу повесить трубку. Проблема в том, что я не могу отключить микрофон или вызов (кнопка ничего не делает), и «Статус (эстадо)» текст обновляется только от «Отключить (desconectado)» до «по вызову (en llamada.)». Вот код фронта: < /p>











Llamadas en linea

#contenido_cliente table td {
vertical-align: top;
padding: 0.25rem 0.5rem;
}
#contenido_cliente td {
padding: 4px 8px;
vertical-align: top;
}










Llamadas en linea



Llamadas Telefónicas






Número a llamar


Llamar
Colgar
Silenciar

Estado: Desconectado

Duración: 00:00






1
2
3


4
5
6


7
8
9


*
0
#

Borrar último
Borrar todo












Nombre
Celular
Estatus numero











Información del Cliente
Seleccione un contacto para ver los detalles.













< /code>
Вот скрипт: < /p>
let device;
let currentConnection;
let isMuted = false;
let callStartTime;
let durationInterval;

function actualizarEstado(estado) {
document.getElementById("estado_llamada").textContent = estado;
}

function actualizarDuracion() {
if (!callStartTime) return;
const now = new Date();
const diff = Math.floor((now - callStartTime) / 1000);
const minutes = String(Math.floor(diff / 60)).padStart(2, '0');
const seconds = String(diff % 60).padStart(2, '0');
document.getElementById("duracion_llamada").textContent = `${minutes}:${seconds}`;
}

let listaContactos = [];

function cargarContactos() {
fetch('php/llamadas.php?accion=contactos')
.then(res => res.json())
.then(clientes => {
listaContactos = clientes; // Guardamos para filtrar después
renderizarContactos(clientes);
})
.catch(err => {
console.error("Error al cargar contactos:", err);
});
}

function renderizarContactos(clientes) {
const tabla = document.getElementById("tabla_contactos");
tabla.innerHTML = "";

const agrupado = {};

// Agrupar por ID_Cliente
clientes.forEach(c => {
if (!agrupado[c.ID_Cliente]) {
agrupado[c.ID_Cliente] = [];
}
agrupado[c.ID_Cliente].push(c);
});

// Dibujar por cada grupo
Object.values(agrupado).forEach(grupo => {
grupo.forEach(c => {
const fila = document.createElement("tr");
fila.style.cursor = "pointer";

let numero = '';
let etiqueta = '';

if (c.Estatus === "1") {
numero = c.Telefono;
etiqueta = 'Actual';
} else if (c.Estatus === "0") {
numero = c.Telefono;
etiqueta = 'Anterior';
} else {
numero = c.Celular;
etiqueta = ''; // Sin etiqueta visible
}

// Acción al hacer clic
fila.addEventListener("click", () => seleccionarNumero(numero));

fila.innerHTML = `
${c.NombreCompleto}
${numero}
${etiqueta}
`;

tabla.appendChild(fila);
});
});

if (tabla.innerHTML.trim() === "") {
const fila = document.createElement("tr");
fila.innerHTML = `Información del cliente no disponible`;
tabla.appendChild(fila);
}
}

function filtrarContactos() {
const filtro = document.getElementById("filtro_contactos").value.toLowerCase();
const filtrados = listaContactos.filter(c =>
c.NombreCompleto.toLowerCase().includes(filtro)
);
renderizarContactos(filtrados);
}

function seleccionarNumero(numero) {
document.getElementById("numero_llamar").value = numero;
const contenedor = document.getElementById("contenido_cliente");
contenedor.innerHTML = `Cargando información del cliente...`;

fetch(`php/llamadas.php?accion=reporte_contratos&telefono=${numero}`)
.then(res => res.json())
.then(data => {
if (!Array.isArray(data) || data.length === 0) {
contenedor.innerHTML = `Información del cliente no disponible.`;
return;
}

contenedor.innerHTML = ""; // Limpiar contenido

// Si hay más de un contrato, usar pestañas
if (data.length > 1) {
const navTabs = document.createElement("ul");
navTabs.classList.add("nav", "nav-tabs");
navTabs.role = "tablist";

const tabContent = document.createElement("div");
tabContent.classList.add("tab-content");

data.forEach((contrato, index) => {
const contratoId = contrato.ID_Contrato || `Contrato ${index + 1}`;
const tabId = `contrato-${index}`;

// Crear pestaña
const tab = document.createElement("li");
tab.classList.add("nav-item");
tab.innerHTML = `
${contratoId}
`;
navTabs.appendChild(tab);

// Crear contenido de la pestaña
const tabPane = document.createElement("div");
tabPane.classList.add("tab-pane", "fade");
if (index === 0) {
tabPane.classList.add("show", "active");
}
tabPane.id = tabId;
tabPane.role = "tabpanel";
tabPane.appendChild(crearTablaCliente(contrato));

tabContent.appendChild(tabPane);
});

contenedor.appendChild(navTabs);
contenedor.appendChild(tabContent);
} else {
// Solo un contrato
contenedor.appendChild(crearTablaCliente(data[0]));
}
})
.catch(err => {
console.error("Error al obtener reporte del cliente:", err);
contenedor.innerHTML = `Ocurrió un error al obtener la información del cliente.`;
});
}

function crearTablaCliente(data) {
const tabla = document.createElement("table");
tabla.classList.add("table", "table-bordered", "table-sm", "mb-0", "w-100");
tabla.style.tableLayout = "fixed";

for (const [key, value] of Object.entries(data)) {
const fila = document.createElement("tr");

const celdaClave = document.createElement("td");
celdaClave.classList.add("fw-bold", "text-end", "bg-light");
celdaClave.style.width = "45%"; // Aumentamos para dejar más espacio
celdaClave.style.paddingRight = "1rem";
celdaClave.style.whiteSpace = "nowrap";
celdaClave.textContent = key;

const celdaValor = document.createElement("td");
celdaValor.classList.add("text-start");
celdaValor.style.width = "55%";
celdaValor.style.paddingLeft = "1rem";
celdaValor.textContent = formatearValor(key, value);

fila.appendChild(celdaClave);
fila.appendChild(celdaValor);
tabla.appendChild(fila);
}

return tabla;
}

function formatearValor(key, valor) {
if (!valor) return "";

// Fechas (YYYY-MM-DD)
if (/fecha/i.test(key) && /^\d{4}-\d{2}-\d{2}/.test(valor)) {
const fecha = new Date(valor);
if (!isNaN(fecha)) {
return fecha.toLocaleDateString("es-MX", {
day: '2-digit',
month: 'long',
year: 'numeric'
}).replace(/^(\d+)\sde\s(\w+)\sde\s(\d{4})$/, (_, d, m, y) => `${d}-${m.charAt(0).toUpperCase() + m.slice(1)}-${y}`);
}
}

// Monto / dinero
if (/monto|precio|cuota|total|costo|pago|importe/i.test(key)) {
const num = parseFloat(valor);
if (!isNaN(num)) {
return num.toLocaleString('es-MX', {
style: 'currency',
currency: 'MXN',
minimumFractionDigits: 2
});
}
}

return valor;
}

function inicializarTwilio() {
fetch('{Servidor}/Twilio/example/token.php')
.then(response => response.json())
.then(data => {
device = new Twilio.Device(data.token, { debug: true });

device.on('ready', () => {
actualizarEstado('Listo para llamar');
});

device.on('error', (error) => {
actualizarEstado(`Error: ${error.message}`);
});

device.on('connect', (conn) => {
currentConnection = conn;
conn.on('disconnect', () => currentConnection = null);
});

device.on('disconnect', () => currentConnection = null);
})
.catch(err => {
actualizarEstado('Error al obtener token');
console.error(err);
});
}

function realizarLlamada() {
const numero = document.getElementById("numero_llamar").value;
if (!device) {
alert("Dispositivo aún no inicializado.");
return;
}

fetch('{Servidor}/Twilio/example/voice.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `To=+52${encodeURIComponent(numero)}`
}).then(() => {
device.connect();
callStartTime = new Date();
durationInterval = setInterval(actualizarDuracion, 1000);
actualizarEstado('En llamada');
document.getElementById("llamar").disabled = true;
}).catch(err => {
console.error("Error al enviar número al backend:", err);
alert("No se pudo iniciar la llamada.");
});
}

function colgarLlamada() {
if (device) device.disconnectAll();
callStartTime = null;
clearInterval(durationInterval);
document.getElementById("duracion_llamada").textContent = '00:00';
actualizarEstado('Desconectado');
document.getElementById("llamar").disabled = false;
}

function toggleMute() {
if (!currentConnection) return;

const localStream = currentConnection.mediaStream?.stream;
if (localStream) {
const audioTrack = localStream.getAudioTracks()[0];
if (audioTrack) {
isMuted = !isMuted;
audioTrack.enabled = !isMuted;
actualizarEstado(isMuted ? "Silenciado (micrófono apagado)" : "En llamada");
}
}
}

function agregarNumero(digito) {
const input = document.getElementById("numero_llamar");
input.value += digito;
}

function borrarUltimoDigito() {
const input = document.getElementById("numero_llamar");
input.value = input.value.slice(0, -1);
}

function llenarNumero(numero) {
document.getElementById("numero_llamar").value = numero;
}

function borrarTodoNumero() {
document.getElementById("numero_llamar").value = '';
}

window.addEventListener('DOMContentLoaded', () => {
inicializarTwilio();
});

document.addEventListener("DOMContentLoaded", () => {
cargarContactos();
});
< /code>
В разделе Twilio API у меня есть два файла настроены. Первый - это "token.php", где настроено соединение: < /p>

< /code>
и, наконец, "vicom.php", где выполняется запрос на подключение вызова. Оба файла существуют на одном уровне API: < /p>







No se proporcionó un número para llamar.


< /code>
Главное, что мне нужно исправить, - это микрофон, не приглушенный, но я открыт для любых других улучшений кода, которые вы можете предложить. Спасибо за помощь!

Подробнее здесь: https://stackoverflow.com/questions/796 ... wilio-call
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»