API Voice v1.0
Bienvenido a la documentación de API Voice v1.0 de netelip.
API Voice facilita a tus aplicaciones WEB el control en vivo de tus llamadas de teléfono, tanto entrantes como salientes, permitiéndote realizar acciones sobre estas en función de lo que el llamante o llamado diga o marque en el teclado de su teléfono. Podrás montar fácilmente servicios telefónicos de reservas, gestión de cobros, control de acceso a IVRs, encuestas telefónicas, etc
Tenemos ejemplos en lenguajes de shell, php y python que pueden ver en el área oscura de la derecha. Puede cambiar el lenguaje de programación de los ejemplos en las pestañas que aparecen arriba a la derecha.
Para conocer todas las APIs disponibles, información general y restricciones aplicadas a su uso consulte "Documentación APIs".
¿Qué necesito para utilizar API Voice?
Solo necesitarás tener una cuenta de cliente de netelip con el servicio API Voice activo, y un servidor WEB en el que correrán las aplicaciones que establecerán las comunicaciones con API Voice de netelip.
Si todavía no es cliente de netelip puede registrarse en el siguiente enlace.
¿Cómo funciona API Voice?
API Voice v1.0 de netelip tiene un conjunto de comandos que se utilizan para indicar a netelip qué hacer cuando se realiza o se recibe una llamada a través de API Voice.
Cuando alguien hace una llamada a uno de tus números de teléfono de API Voice, buscaremos la "URL de control para llamadas entrantes" asociada a ese número de teléfono, y se hará una petición a dicha URL, facilitando información de la llamada entrante y esperando recibir instrucciones sobre qué hacer con la llamada.
Algunas de las instrucciones disponibles son:
- Reproducir un fichero de audio.
- Lectura de los dígitos marcados por el llamante o llamado en el teclado de su teléfono.
- Iniciar la grabación de la llamada.
- Reproducir audio a través de un texto. Text To Speech.
- Convertir audio en texto. Voice to Text.
- Desviar la llamada a un número de teléfono.
- Desviar la llamada a una extensión de un servidor SIP.
- Colgar la llamada.
También se podrán realizar otras acciones si dispones del servicio vPBX, como:
- Terminar las llamadas entrantes en la vPBX para:
- Poner la llamada en una cola de llamadas con una prioridad.
- Pasar la llamada a una sala de conferencias.
- Desviar la llamada a una extensión o grupo de extensiones.
- Desviar la llamada al buzón de voz de una extensión.
- Reproducir un fichero de audio de vPBX.
- Desviar la llamada a un IVR.
- Gestionar las llamadas salientes de la extensiones de su vPBX.
- Podrá crear sus propias funcionalidades a medida, tanto para llamadas entrantes como salientes de su centralita virtual.
Así mismo, tus aplicaciones podrán lanzar llamadas a números de teléfono de la red telefónica pública, a través de envío de un POST con autentificación por Token + IP (si lo especifica). Una vez contestada la llamada, esta pasará a ser gestionada por la “URL de control para llamadas salientes” de su servidor WEB.
Puede consultar la lista completa de comandos en el apartado "Comandos disponibles".
Funcionalidades
Las aplicaciones de API Voice v1.0 de netelip son muchas pero las funcionalidades principales son:
- Controlador de llamadas
El control de las llamadas se realizará a través de las "URLs de control de llamadas" ubicadas en su servidor WEB.
Estas URLs realizarán las comprobaciones o tareas programadas a su interés, y enviarán a API Voice los comandos a ejecutar para la llamada en curso.
Cuando API Voice finalice la ejecución de un comando, conectará con su URL de control para indicar el resultado del comando previo, y mantendrá la llamada activa a la espera de recibir el siguiente comando a ejecutar.
Este comportamiento se repetirá indefinidamente hasta que alguno de los extremos cuelgue la llamada en curso, ya sea tu URL de control mediante el comando de colgado, o el llamante o llamado mediante la tecla de colgado de tu terminal telefónico.
Para ver como se implementa un servicio para controlar las "URLS de control de llamadas" consulte el apartado "Controlador de llamadas".
Puede consultar la lista completa de comandos en el apartado "Comandos disponibles" y ver un caso práctico en el apartado "Caso práctico: flujo".
- Informe de llamadas
API Voice de netelip ofrece la opción de enviar el estado de las llamadas realizadas a una "URL de reporte de llamadas".
Debe configurar su "URL de reporte de llamadas" en su panel de control de API Voice, inserta la dirección web donde recibir el registro de llamadas realizadas/recibidas.
Para ver como se implementa un servicio para gestionar la información de llamadas consulte el apartado "Informe de llamadas".
- Notificaciones de estados
El control de notificaciones de eventos de llamadas se realizará a través de la "URL enventos de llamadas" ubicada en su servidor WEB.
Esta URL realizará las comprobaciones y gestión de los eventos según su interés.
Para ver como se implementa un servicio para gestionar las notificacieones consulte el apartado "Notificaciones de estados".
Activar vPBX para API Voice
Para controlar las llamadas que realizan las extensiones de tu vPBX a través de API Voice, tiene que acceder al panel de control de netelip, sección "vPBX", editar una extensión e indicarle que la extensión va a utilizar el Plan de marcado API Voice y seleccionar uno de nuestros API Voice disponibles.
Seguridad
En este apartado se describen los mecanísmos de seguridad y algunas recomendaciones.
Autentificación
Todos los ejemplos de la documentación se basan en este esqueleto:
# Asegurese de pasar siempre las cabeceras correctamente.
curl -X POST https//api.netelip.com/v1/voice/{endpoint} \
--data "token=69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz"
<?php
$url="https://api.netelip.com/v1/voice/{endpoint}";
$post = array(
"token" => "69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz",
);
$request = curl_init($url);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_TIMEOUT, 180);
curl_setopt($request, CURLOPT_POSTFIELDS, $post);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($request);
if ($response !== false) {
// Manejar datos devueltos por la petición
} else {
// Manejar error de conexión
}
curl_close($request);
?>
#!/usr/bin/env python
import requests
url = 'https://api.netelip.com/v1/voice/{endpoint}'
data = {
'token': '69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz',
}
response = requests.post(url=url, data=data)
if response:
# Manejar datos devueltos por la petición
else:
# Manejar error de conexión
Reemplazar {endpoint} por el punto de entrada correcto.
El token usado es un token de ejemplo no válido.
API Voice de netelip usa autentificación por token, para obtener su token acceda a 'Token de seguridad' que encontrará en su 'Panel de control' en sección datos personales.
Si todavía no es cliente de netelip puede registrarse en el siguiente enlace.
API Voice de netelip espera en todas sus peticiones que se autentifique con un token similar a este:
69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz
Redes de confianza.
Para usar el servicio de API Voice v1.0 de netelip es necesario que desarrolle servicios (controladores) en sus propios servidores y esto supone tener abierto los servicios al público.
Se recomienda filtrar los accesos mediante IPs de confianza.
Las redes de confianza de netelip son:
Datacenter | Network |
---|---|
Europa | 185.8.244.0/24 |
América | 192.99.91.144/29 |
HTTPS
La comunitcación entre API Voice v1.0 de netelip y sus servidores se realiza mediante los protocolos HTTP y HTTPS.
netelip recomienda siempre el uso de HTTPS para garantizar que la comunicación entre sus servidores y API Voice viaje en un canal cifrado.
netelip no aplica restricciones en cuanto al uso de certificados autofirmados.
Controlador de llamadas
Ejemplo de controlador de llamadas que pide un código de usuario para poder acceder al menú
# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación.
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
// Obtenemos los datos de la llamada y las guardamos en variables
$src = $_POST["src"];
$dst = $_POST["dst"];
$id = $_POST["ID"];
if ($src == "" || $dst == "" || $id != "") die(); // Algo está mal, terminamos
$dtmf = $_POST["dtmf"];
// Datos del ultimo comando ejecutado si no estamos al comienzo de una llamada
$command = $_POST["command"];
$options = $_POST["options"];
$userfield = ($_POST["userfield"] == "") ? "1" : $_POST["userfield"];
$messages = array(
1 => "Bienvenido a mi empresa, por favor escriba a continuacion su usuario.",
2 => "Su usuario es correcto, accedemos al menu del servicio.",
3 => "Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.",
4 => "Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.",
);
switch($userfield) {
case "0": // colgamos la llamada
$command = "hangup";
$options = "";
$userfield = "";
break;
case "1": // reproducimos una locucion esperando una respuesta
$command = "speak_getdtmf";
$options = "google;es;".$messages[1].";5000;4;1.2";
$userfield = "2";
break;
case "2":
$command = "speak_getdtmf";
switch($dtmf) {
case "timeout": // tiempo agotado, locucion y repetimos
$options = "netelip;Pedro;".$messages[1].";5000;4";
$userfield = "2";
break;
case("1111"): // usuario correcto, locucion y a la cola
$options = "netelip;Pedro;".$messages[2].$messages[4].";5000;1";
$userfield = "3";
break;
default: // usuario incorrecto, locución de despedida y colgamos
$command = "speak";
$options = "netelip;Pedro;".$messages[3];
$userfield = "0";
}
}
break;
case "3":
$command = "queue";
$userfield = "0";
switch($dtmf) {
case "timeout": // tiempo agotado, locucion y repetimos
$command = "speak_getdtmf";
$options = "netelip;Pedro;".$messages[4].";5000;1";
$userfield = "3";
break;
case "1": // ejecutamos la cola de atencion de la vPBX con prioridad 2
$options = "colaatencion;2";
break;
case "2": // ejecutamos la cola de soporte de la vPBX con prioridad 1
$options = "colasoporte;1";
break;
}
break;
}
$cadena = array("command"=>$comand, "options"=>$options, "userfield"=>$userfield);
echo(json_encode($cadena));
?>
#!/usr/bin/env python
messages = [
'Bienvenido a mi empresa, por favor escriba a continuacion su usuario.',
'Su usuario es correcto, accedemos al menu del servicio.',
'Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.',
'Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.',
]
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/controller', methods=['GET','POST'])
def controller():
if request.method == 'POST':
# Obtenemos los datos de la llamada y las guardamos en variables
src = request.form.get('src')
dst = request.form.get('dst')
idc = request.form.get('ID')
if src == None or dst == None or idc == None:
return jsonify(error='No se han definido argumentos')
if src == "" or dst == "" or idc == "":
return jsonify(error='Los argumentos no pueden ir vacios')
dtmf = request.form.get("dtmf")
# Datos del ultimo comando ejecutado
c = {
'command' : request.form.get("command"),
'options' : request.form.get("options"),
'userfield': request.form.get("userfield")
}
if c['userfield'] == "0": # colgamos la llamada
c['command'] = "hangup"
c['options'] = ""
c['userfield'] = ""
elif c['userfield'] == "1" or c['userfield'] == "" or c['userfield'] == None:
# reproducimos una locucion esperando una respuesta (llamada entrante)
c['command'] = "speak_getdtmf"
c['options'] = "google;es;%s;5000;4;1.2" % messages[0]
c['userfield'] = "2"
elif c['userfield'] == "2":
c['command'] = "speak_getdtmf"
if dtmf == "timeout": # tiempo agotado, locucion y repetimos
c['options'] = "netelip;Pedro;%s;5000;1" % messages[0]
c['userfield'] = "2"
elif dtmf == "1111": # usuario correcto, locucion y a la cola
c['options'] = "netelip;Pedro;%s%s;5000;1" % (messages[1], messages[3])
c['userfield'] = "3"
else: # usuario incorrecto, locución de despedida y colgamos
c['command'] = "speak"
c['options'] = "netelip;Pedro;%s" % messages[2]
c['userfield'] = "0"
elif c['userfield'] == "3":
c['command'] = "queue"
c['userfield'] = "0"
if dtmf == "timeout": # tiempo agotado, locucion y repetimos
c['command'] = "speak_getdtmf"
c['options'] = "netelip;Pedro;%s;5000;1" % messages[3]
c['userfield'] = "3"
elif dtmf == "1": # ejecutamos la cola de atencion de la vPBX con prioridad 2
c['options'] = "colaatencion;2"
elif dtmf == "2": # ejecutamos la cola de soporte de la vPBX con prioridad 1
c['options'] = "colasoporte;1"
print(jsonify(c))
return jsonify(c)
else:
return jsonify(error='Metodo no permitido')
if __name__ == '__name__':
app.run()
Para controlar las llamadas que entran en su servicio de API Voice necesita desarrollar un controlador que gestione todas las peticiones que API Voice envíe a su "URLs de control de llamadas".
El código de este controlador puede estar escrito en cualquier lenguaje de programación web ya que la comunicación entre su servidor WEB y API Voice es mediante peticiones HTTP de tipo POST (Content-Type: text/html).
API Voice se comunicará con su servidor WEB mediante método HTTP POST o Secure HTTP POST, enviando a su URL de control los datos de la llamada y el resultado del comando ejecutado.
Una vez que API Voice realice una petición a su URL de control este quedará a la espera de que su URL de control conteste con el siguiente comando a ejecutar.
Petición
Contenido de la variable POST cuando se recibe un llamada y API Voice realiza la petición a su controlador:
{
"ID": "1576556033.1735",
"api": "Mi API",
"src": "638829213",
"dst": "34951504990",
"startcall": "2019-11-12 11:04:26",
"typesrc": "did",
"usersrc": "638829213"
}
Las posibles variables que se incluirán en la petición POST cuando API Voice conecte con su URL de control serán:
Clave | Descripción |
---|---|
ID | ID único de la llamada |
api | Nombre del API destino de la llamada |
src | Número de origen de la llamada |
dst | Número de destino de la llamada |
startcall | Fecha y hora en la que comenzó la llamada |
durationcall | Duración actual de la llamada |
durationcallanswered | Duración de la llamada una vez atendida por un agente |
command | Comando ejecutado |
options | Opciones del comando ejecutado |
description | Descripción del resultado de la ejecución del comando |
statuscode | Código de estado de la ejecución |
statuscall | Estado de la llamada, ver valores |
userfield | Variable establecida por el usuario |
userdata | Variable opcional reservada para el usuario. |
typesrc | Tipo de origen, ver valores |
usersrc | Usuario del origen de la llamada, ver valores |
diversion | Información sobre el desvío de llamada, si existiera. Sólo para llamadas entrantes, ver información |
statuscall
Posibles valores de statuscall:
Valor | Descripción |
---|---|
CHANUNAVAIL | El número llamado no existe |
BUSY | El número llamado está ocupado |
NOANSWER | El número llamado no contesta |
ANSWER | El número llamado ha contestado |
CANCEL | El número llamado ha colgado |
CONGESTION | Fallo en red telefónica por congestión |
UNKNOW | Fallo en red telefónica desconocido |
typesrc
Posibles valores de typesrc:
Valor | Descripción |
---|---|
ext | Llamada con origen una extensión de tu vPBX cuando ésta tiene el asociado el "Plan de marcado de API Voice". |
did | Llamada con destino un número de teléfono de netelip gestionado por API Voice. |
usersrc
Este valor depende directamente de la clave typesrc.
Si typesrc es "ext", el valor de usersrc será el usuario SIP de la extensión que realiza la llamada.
Y si typesrc es "did" el valor de usersrc será el número de teléfono de origen de la llamada, tendrá el mismo valor que src.
diversion
Muestra información sobre el desvío de llamada si existiera, mostrando el número de teléfono llamado originariamente y la causa del desvío.
El valor de este campo tiene la siguiente estructura:
n_telefono;reason=razón
siendo n_telefono, el número de teléfono llamado originariamente; y razón, la causa del desvío de la llamada.
Ejemplo:
El usuario A llama a usuario B y este se desvía al número de teléfono de APIVoice, APIVoice mostrará como src el número de teléfono del usuario A y diversion tendrá el valor del número de teléfono del usuario B más la causa del desvío de llamada.
Respuesta
Ejemplo de una respuesta a API Voice:
{
"command": "speak",
"options": "netelip;Pedro;Espere por favor.",
"userfield":"2;espera;200"
}
API Voice quedará a la espera de que su URL de control conteste con el siguiente comando a ejecutar, siempre que la variable statuscall se mantenga con valor ANSWER o sea la primera petición de recepción de llamada.
Su URL de control debe responder con una cadena de texto con estructura json indicando el comando u orden que API Voice debe ejecutar (command), las opciones de configuración del comando (options) y datos personalizados que puede indicar el controlador (userfield).
Una vez procesado el comando API Voice volverá a conectar con su URL de control para indicarle el estado de la llamada y esperará a la siguiente orden.
Este proceso ser repetirá hasta que la llamada termine.
Puede consultar la lista completa de comandos y su configuración en el apartado "Comandos disponibles".
Lanzador de llamadas
Ejemplo de petición de llamada:
curl -X POST https://api.netelip.com/v1/voice \
--data "token=69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz" \
--data "api=Mi API" \
--data "src=34951223344" \
--data "dst=0034666554433" \
--data "duration=30" \
--data "typedst=pstn"
<?php
$url="https://api.netelip.com/v1/voice";
$post = array(
"token" => "69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz",
"api" => "Mi API",
"src" => "34951223344",
"dst" => "0034666554433",
"duration" => "30",
"typedst" => "pstn",
);
$request = curl_init($url);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($request, CURLOPT_POSTFIELDS, $post);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($request);
$response_code = curl_getinfo($request, CURLINFO_HTTP_CODE);
if ($response !== false) {
if ($response_code == 200) {
echo $response;
}
} else {
echo "Error: ".$response_code;
}
curl_close($request);
?>
#!/usr/bin/env python
import requests
url = 'https://api.netelip.com/v1/voice'
data = {
'token' : '69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz',
'api' : 'Mi API',
'src' : '34951223344',
'dst' : '0034666554433',
'duration' : '30',
'typedst' : 'pstn',
}
response = requests.post(url=url, data=data, timeout=(5, 5), max_redirects=3)
if response:
if response.status_code == 200:
print(response.text)
else:
print("Error: %s" % $response.status_code)
Para realizar una llamada a través de API Voice solo es necesario enviar a la URL, 'https://api.netelip.com/v1/voice', mediante método POST, los siguientes datos:
Clave | Descripción |
---|---|
api | Nombre de la API a utilizar. |
token | Palabra de seguridad asociada a la API a utilizar. |
src | Identificador de llamada que se mostrará al usuario que recepciona la llamada. |
dst | Número de teléfono a llamar. |
duration | Duración máxima del intento de llamada en segundos. Entre 1 y 60. |
userdata | Variable opcional reservada para el usuario. |
typedst | Tipo de destino de la llamada, ver valores |
typedst
Posibles valores de typedst:
Valor | Descripción |
---|---|
pstn | Llamada hacia la red pública. |
extension | Llamada hacia una extensión de tu vpbx. |
Llamada rechazada
Respuesta de llamada rechazada:
{
"response": "400"
}
API Voice podrá rechazar la llamada con un código 400 (unauthorized) en formato json, si el token enviado o la IP desde la que se origina la petición no es válida.
Llamada aceptada
Respuesta de llamada aceptada:
{
"response": "200",
"ID": "1576556033.1735"
}
Si API Voice acepta la llamada lo indicará con un código 200 (OK) y el ID único de la llamada a través de una cadena con estructura json.
El resultado del lanzamiento de la llamada se enviará a su URL de control de llamadas como se indica en el apartado "Controlador de llamadas - Petición".
La petición se realizará con la siguiente información:
Clave | Descripción |
---|---|
ID | ID único de la llamada |
api | Nombre del API destino de la llamada |
src | Número de origen de la llamada |
dst | Número de destino de la llamada |
startcall | Fecha y hora en la que comenzó la llamada |
statuscall | Estado de la llamada, ver valores |
De este modo, tu URL de control llamadas salientes tomará el control de la llamada en curso y podrá contestar a API Voice con el siguiente comando a ejecutar como se indica en el apartado "Controlador de llamadas - Respuesta".
Puede consultar la lista completa de comandos y su configuración en el apartado "Comandos disponibles".
Destino no contesta
En caso de responder el lanzador de llamadas satisfactoriamente pero el destinatario no coger la llamada, se devolverá el estado de tal llamada a la URL de control de llamadas salientes, con la siguiente información:
Clave | Descripción |
---|---|
ID | ID único de la llamada |
token | Token que se utilizó en el lanzador de llamadas |
api | Nombre del API destino de la llamada |
src | Número de origen de la llamada |
dst | Número de destino de la llamada |
duration | Duración del ring de la llamada |
typedst | Tipo de destino de la llamada |
userdata | Variable establecida por el usuario |
startcall | Fecha de la llamada |
statuscall | Estado de la llamada |
Para ver como API Voice trata las peticiones consultar el apartado "Controlador de llamadas - Respuesta".
Puede consultar la lista completa de comandos y su configuración en el apartado "Comandos disponibles".
Integraciones
La realización de llamadas puede ser ejecutada desde una aplicación de escritorio o web, solo es necesario que la aplicación integre el protocolo de comunicación HTTPS.
Puede consultar todos los ejemplos de esta API para ver como se realizan peticiones HTTP con curl, php y python.
Informe de llamadas
Ejemplo para almacenar en un fichero la información de las llamadas:
# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación.
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$file = "calls.csv";
$linecall = "";
$calls = json_decode($_POST["calls"], true);
//recorremos las llamadas
foreach($calls as $call){
// recorremos cada uno de los valores de la llamada para montar una linea csv
foreach($call as $value) {
$linecall = $linecall.";".$value;
}
$linecall=$linecall."\n";
}
// añadimos la linea de registro de la llamada a nuestro fichero de llamadas
file_put_contents($file, $linecall, FILE_APPEND);
?>
#!/usr/bin/env python
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/reporter', methods=['GET','POST'])
def controller():
if request.method == 'POST':
calls = json.loads(request.form.get('calls'))
with open('calls.csv', 'a') as f:
for call in calls:
line = ','.join(call.values()) + '\n'
f.write(line)
return jsonify(calls=len(calls))
else:
return jsonify(error='Metodo no permitido')
if __name__ == '__name__':
app.run()
Para gestionar la información de las llamadas que entran en su servicio de API Voice necesita desarrollar un controlador que gestione todas las peticiones que API Voice envíe a su "URL de reporte de llamadas".
El código de este controlador puede estar escrito en cualquier lenguaje de programación web, ya que la comunicación entre su servidor WEB y API Voice es mediante peticiones HTTP de tipo POST con una estructura "json".
API Voice se comunicará periódicamente con su servidor WEB mediante método HTTP POST o Secure HTTP POST, enviando a su "URL de reporte de llamadas" los datos de las llamadas del último periódo y el resultado del comando ejecutado.
Informe
Ejemplo de dos registros (genérico y vPBX) en el array 'calls':
[
...
{
"ID": "",
"startdate": "2020-04-23 12:17:40.897837",
"stopdate": "2020-04-23 12:17:45.897837",
"src": "667001122",
"dst": "34915221100",
"dstname": "",
"duration": "5",
"cost":0,
"status": "answer",
"ip": "",
"useragent": "",
"plan":""
},
...
{
"ID": "",
"startdate": "2020-04-23 12:29:01.47034",
"stopdate": "2020-04-23 12:29:06.47034",
"src": "34815111000 (Ext 101)","dst":"666334455",
"dstname": "Espa\\u00f1a - m\\u00f3vil",
"duration": "5",
"cost": 0.0024,
"status": "answer",
"ip": "192.168.1.33",
"useragent": "MyAgent\\/SPA333-1.2.3","plan":""
}
...
]
El registro de llamadas se enviará a la "URL de reporte de llamadas" mediante método POST y se entregará una lista con indice "calls" en formato "json".
La estructura de los registros de la lista en "json" que API Voice entregará al conectar con su "URL de reporte de llamadas" será:
Clave | Descripción |
---|---|
startdate | Fecha de inicio de la llamada. |
stopdate | Fecha de finalización de la llamada. |
src | Origen de la llamada. |
dst | Destino de la llamada. |
dstname | Nombre del destino de la llamada. |
cost | Coste de la llamada. |
status | Estado de la llamada. |
ip | IP del dispositivo desde la que ha realizado la llamada |
duration | Duración de la llamada. |
useragent | Nombre del dispositivo que ha realizado la llamada. |
plan | Plan de llamadas utilizado en la llamada. |
Notificaciones de estado
Ejemplo para gestionar las notificaciones:
# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación.
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$call = json_decode($_POST["call"], true);
switch ($call['status']) {
case 'ring':
...
break;
case 'answer':
...
case 'hangup':
...
break;
case 'busy':
...
break;
case 'noanswer':
...
break;
case 'notavailable':
...
break;
}
?>
#!/usr/bin/env python
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/notifications', methods=['POST'])
def controller():
if request.method == 'POST':
call = json.loads(request.form.get('call'))
if call['status'] == 'ring':
...
elif call['status'] == 'answer':
...
elif call['status'] == 'hangup':
...
elif call['status'] == 'busy':
...
elif call['status'] == 'noanswer':
...
elif call['status'] == 'notavailable':
...
return jsonify(call=len(call))
else:
return jsonify(error='Metodo no permitido')
if __name__ == '__name__':
app.run()
Las notificaciones de estado de extensiones en vPBX, permiten comunicar los cambios de estado de su extensiones, indicando cuando una llamada ha sido contestada, colgada, cancelada, etc, en sus extensiones. Estas notificaciones se realizaran a una URL de control ("URL eventos de llamada" o "URL eventos de registro") y que usted definirá y programara en sus servidores.
El código del manejador de su URL de control puede estar escrito en cualquier lenguaje de programación web, ya que la comunicación entre su servidor WEB y API Voice es mediante peticiones HTTP de tipo POST con una estructura "json".
API Voice se comunicará con su servidor WEB cada vez que se produzca un evento mediante método HTTP POST o Secure HTTP POST, enviando a su URL de control los datos del evento.
Notificación de llamadas
Ejemplo de contenido del índice 'call' de la variable POST cuando se envía una notificación a su URL de notificación de eventos en llamadas:
{
"uniqueid": "1576556033.1735",
"src": "638829213",
"dst": "34951504990",
"userexten": "7491464423100",
"status": "ring",
"date": "2020-04-21",
"time": "10:44:10",
"type": "inbound",
"idapivoice": "1600429592.18200"
}
Los eventos de las llamadas se enviará a la url "URL eventos de llamada" mediante método POST con el índice "call" en formato "json".
La estructura de comunicación "json" será:
Clave | Descripción |
---|---|
uniqueid | ID de llamada único |
src | Origen de la llamada |
dst | Destino de la llamada |
userexten | Usuario SIP de la extensión que notifica el evento |
status | Estado del evento. Valores: ring, answer, hangup, busy, noanswer o notavailable |
date | Fecha del evento, con formato YYYY-MM-DD |
time | Hora del evento, con formato HH:MM:SS. La hora se presentará en la zona horaria GMT |
type | Tipo de llamada. Valores: inbound o outbound |
transferid | ID de llamada transferida, aparecerá cuando se transfiere la llamada a otra extensión |
transferuserexten | usuario SIP de la extensión que transfiere la llamada, aparecerá cuando se transfiere la llamada a otra extensión |
idapivoice | ID de llamada único de API Voice. Este valor solo aparecerá cuando la llamada provenga de hacer una llamada desde el lanzador de API Voice o recibida a traves de API Voice y transferidas a vPBX. |
viacall | Indica que la llamada recibida en tu extensión ha sido mediante una cola de llamadas (valor queue-IDcolallamada) o una llamada a tu extensión (valor directcall). Únicamente para llamadas entrantes. |
Notificación de registro
Ejemplo de contenido del índice 'register' de la variable POST cuando se envía una notificación a su URL de notificación de eventos de registro:
{
"userexten": "8466271361103",
"registered": "1",
"IP": "185.8.245.123",
"useragent": "Yealink SIP-T21P_E2 52.80.0.60",
"datetime": "2020-10-30 22:33:56"
}
Los eventos de registro se enviará a la url "URL eventos de registro" mediante método POST con el índice "register" en formato "json".
La estructura de comunicación "json" será:
Clave | Descripción |
---|---|
userexten | Usuario SIP de la extensión que notifica el evento |
registered | Si el dispositivo está registrado, 1 está registrado, 0 no registrado |
IP | Dirección IP del dispositivo registrado |
useragent | Nombre del dispositivo registrado |
expirationdate | Fecha de expiración de registro del dispositivo registrado. La fecha se presentará en la zona horaria GMT, en formato YYYY-MM-DD HH:MM:SS |
Notificación de grabación de llamadas
Ejemplo de contenido del índice 'callrecording' de la variable POST cuando se envía una notificación a su URL de notificación de eventos en llamadas:
{
"uniqueid": "1576556033.1735",
"src": "638829213",
"dst": "34951504990",
"userexten": "7491464423100",
"status": "ANSWERED",
"duration": "64",
"file": "vPBX/callrecords/in/2022-11-15/2022_11_15_08_47_05_34951504990_638829213_1668498425.mp3",
"URLAudio": "https://vdrive.netelip.com/index.php/apps/audioplayer/getaudiostream?file=vPBX/callrecords/in/2022-11-15/2022_11_15_08_47_05_34951504990_638829213_1668498425.mp3",
"URLDownload": "https://vdrive.netelip.com/downloadAudioApivoice?file=Jc5AZoeuWBpYdQgBlZy9Zp62KuYDcpJF2PPUa3i2tvu3SI36izklk"
}
El evento de la grabación de llamadas se enviará a la url "URL eventos de llamada" mediante método POST con el índice "callrecording" en formato "json".
La estructura de comunicación "json" será:
Clave | Descripción |
---|---|
uniqueid | ID de llamada único |
src | Origen de la llamada |
dst | Destino de la llamada |
userexten | Usuario SIP de la extensión que notifica el evento |
status | Estado del evento. Valores: CHANUNAVAIL, BUSY, NOANSWER, ANSWERED, CANCEL, CONGESTION |
duration | Duración de la llamada en segundos |
file | Ubicación del fichero en vDrive |
URLAudio | URL en donde escuchar el fichero. |
URLDownload | URL de descarga del fichero. |
Importante: La notificación de la grabación de llamadas es automática. Para tener activo el servicio es necesario tener la grabación de llamadas en vPBX, tenerla integradas con vDrive y activo en API Voice los eventos de llamadas.
Comandos disponibles
Esquema de un comando:
{
"command": "nombrecomando",
"options": "option1[;option2;option3]",
"userfield": "customvalue"
}
Para controlar la realización y recepción de llamadas API Voice de netelip admite un conjunto de comandos amplio.
Cada comando está definido por 3 argumento y se entrega a API Voice en formato json.
Argumento | Descripción |
---|---|
command | Nombre de la orden o comando |
options | Valores separados por "," o ";" que modifican el comportamiento del comando |
userfield | Campo de uso libre para el usuario, se suele usar para indicar el estado o fase en el que se encuentra la llamada. |
userfield es un valor definido por tu URL de control y que podrás aprovechar
para indicarle en que momento de la ejecución se encuentra la llamada dentro del
flujo de llamada planificado por ti.
Este campo no se procesa por API Voice y es devuelto exactamente igual en la
siguiente petición.
answermachinedetect
Ejemplos de answermachinedetect:
{
"command" : "answermachinedetect",
"options" : "",
"userfield": 2
}
{
"command" : "answermachinedetect",
"options" : "5.1,1.5,0.8,5,0.1,0.05,3,256",
"userfield": 2
}
Intenta detectar un contestador automático basándose en los patrones de tiempo. Solo para llamadas salientes originadas desde el lanzador de llamadas.
Valores que contiene options
"options": "{initialSilence},{greeting},{afterGreetingSilence},{totalAnalysisTime},{minimumWordLength},{betweenWordsSilence},{maximumNumberOfWords},{silenceThreshold}",
ó
"options": "",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
initialSilence | Duración máxima en segundos de silencio antes del saludo. Si se excede se devuelve machine | De 0 a 60 | 5.1 |
greeting | Duración máxima en segundos del saludo. Si se excede se devuelve machine | De 0 a 60 | 1.5 |
afterGreetingSilence | Duración máxima de silencio en segundos tras detectar un saludo. Si se excede se devuelve machine | De 0 a 60 | 0.8 |
totalAnalysisTime | Tiempo máximo permitido en segundos para que el algoritmo decida si ha contestado un ser humano o un contestador automático | De 0 a 60 | 5 |
minimumWordLength | Duración mínima en segundos de la voz para ser considerada como una palabra | De 0 a 60 | 0.1 |
betweenWordsSilence | Duración mínima de silencio en segundos después de una palabra para considerar que el audio que le sigue es una palabra nueva | De 0 a 60 | 0.05 |
maximumNumberOfWords | Número máximo de palabras detectadas en el saludo. Si se excede se devuelve machine | De 0 a 100 | 3 |
silenceThreshold | Nivel medio de ruido que se considera como silencio | De 0 a 256 | 256 |
Respuesta
La ejecución de “answermachinedetect” devolverá el estado de la detección de la contestación de la llamada dentro de la variable "statusanswermachinedetect".
Valor | Descripción |
---|---|
machine | Se detecta que la llamada fue contestada por un constestador automático |
human | Se detecta que la llamada fue contestada por un ser humano y no un contestador automático |
notsure | No se puede determinar si la llamada fue contestada por un ser humano o un contestador automático |
hangup | Se detecta un cuelge de la llamada |
busy
Ejemplo de busy:
{
"command" : "busy",
"options" : "10",
"userfield": "ocupado"
}
Dar señal de ocupado en la llamada actual.
Valores que contiene options
"options": "{seconds}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
seconds | Duración en segundos de los tonos de ocupado antes de colgar | De 0 a 30 | 30 |
callerid
Ejemplo de callerid:
{
"command": "callerid",
"options": "netelip;951223344",
"userfield": "1"
}
Cambia el identificador llamada y se suele usar antes de realizar un desvío o transferencia. Por ejemplo antes de ejecutar un comando dial.
El nombre a mostrar es un texto breve que sólo será visible en la recepción de llamadas en aplicaciones o dispositivos de VoIP.
El número de teléfono a mostrar, será visible en la recepción de llamadas en aplicaciones o dispositivos de VoIP y en llamadas a números de teléfono de la red telefónica publica.
Valores que contiene options
"options": "{name};{phone}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
name | Nombre a mostrar | string | |
phone | Número de teléfono a mostrar | phone |
conferenceroom
Ejemplo de conferenceroom:
{
"command" : "conferenceroom",
"options" : "",
"userfield": "4"
}
Transfiere una llamada a su sala de conferencias de vPBX.
Valores que contiene options
El argumento options no se usa con el comando conferenceroom, se recomienda poner una cadena vacía o un valor 0.
congestion
Ejemplo de congestion:
{
"command" : "congestion",
"options" : "10",
"userfield": "congestionado"
}
Dar señal de congestion en la red en la llamada actual.
Valores que contiene options
"options": "{seconds}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
seconds | Duración en segundos de los tonos de congestion antes de colgar | De 0 a 30 | 30 |
dial
Ejemplo de dial a una extensión:
{
"command": "dial",
"options": "extension,102,10,called,180",
"userfield": "3"
}
Ejemplo dial a un número:
{
"command": "dial",
"options": "pstn,0034951223344,15,calling,180",
"userfield": "3"
}
Ejemplo dial a un cuenta sip:
{
"command": "dial",
"options": "sipserver,103@pbx.midominio.com:5060,15,calling,180",
"userfield": "3"
}
Ejemplo dial a un número con anuncio de locución de vPBX:
{
"command": "dial",
"options": "pstn,0034951223344,15,calling,180,local|bienvenido",
"userfield": "3"
}
Ejemplo dial a un número con anuncio de audio remoto:
{
"command": "dial",
"options": "pstn,0034951223344,15,calling,180,remote|https://miservidor.com/ficheroaudio.mp3",
"userfield": "3"
}
Hace una llamada a un destino, ya sea extensión de vPBX, teléfono de la red pública o extensión de un servidor SIP.
Puedes añadir varios destinos a la llamada concatenando cada número de teléfono o extensión por “&”.
Valores que contiene options
"options": "{type},{destination},{max_ring},{transfer},{timeout},{announce}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
type | Destino de la llamada | string | |
destination | Extensión, número o cuenta sip de destino | string | |
max_ring | Duración máxima del ring en segundos | integer | |
transfer | Permiso de transferencia de llamadas | string | |
timeout | Tiempo máximo de duración de la llamada | integer | |
announce | Ubicación del fichero de audio a reproducir como anuncio al destino de la llamada | string | |
musiconhold | Categoría de la música en espera | string |
"type" puede tomar los valores "extension", "pstn" o "sipserver".
- "extension": La llamada se hace a una o varias extensiones de vPBX.
- "pstn": La llamada se hace a un número de teléfono de la red de telefonía pública.
- "sipserver": La llamada se hace a un servidor SIP, indicando extensión, ip y puerto del servidor SIP de destino
Se pueden añadir varios destionos a llamada concatenado cada número, extensión o cuenta sip con "&" en "destination".
"transfer" puede tomar los valores "calling" o "called".
- "calling": Permite al usuario llamante transferir la llamada pulsando “#”.
- "called": Permite al usuario llamado transferir la llamada pulsando “#”.
"timeout" permite al usuario establecer la duración máxima de conversación en la llamada, siendo el valor mínimo de 5 segundos y máximo de 10 horas (36000 segundos).
"announce", ubicación del fichero de audio a reproducir como anuncio al destino de la llamada. Su sintaxis es "locatefileaudio|fileaudio", pudiendo ser
- locatefileaudio,
- "local": El fichero de audio se encuentra en el panel de netelip.
- "remote": El fichero de audio se encuentra en un servidor remoto, una url.
- fileaudio, Nombre de fichero de audio de locución de vPBX o url del audio remoto
"musiconhold", nombre de la categoría de música en espera de vPBX.
Respuesta
La ejecución de “dial” devolverá el estado de la llamada dentro de la variable "description".
Valor | Descripción |
---|---|
CHANUNAVAIL | No existe destinatario de la llamada |
BUSY | El destinatario de la llamada da ocupado |
NOANSWER | El destinatario de la llamada no contesta la llamada |
ANSWER | El destinatario de la llamada contesta la llamada |
CANCEL | El llamante cuelga la llamada antes de que el destinatario la descuelgue |
CONGESTION | La llamada no se establece por problemas en la red telefónica. |
google_voice2text
Ejemplo de google_voice2text:
{
"command": "google_voice2text",
"options": "AIzaSyBgfkU6CBytS1i9cbQKPX5zATwRQ2ml5Qo;es;15;0",
"userfield": "3"
}
Se utiliza el servicio de reconocimiento de voz de Google para convertir la voz del llamante o llamado en texto legible por la aplicación del cliente.
Valores que contiene options
"options": "{key};{language};{wait};{beep};{rtimeout};{intkey}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
key | Generada en la API de reconocimiento de voz de Google APIs. | string | |
language | Código del idioma a reconocer de la "Tabla de idiomas de reconocimiento de voz" | string | |
wait | Número de segundos de duración del silencio necesario para interrumpir la escucha y mandar la petición a Google | integer | |
beep | Reproducir el sonido "beep" para indicar el comienzo de la escucha | 0 o 1 | |
rtimeout | Número de segundos de duración global de la escucha hasta mandar la petición a Google | integer | |
intkey | Tecla que al ser presionada interrumpirá la escucha de voz y será mandada la petición a Google | integer | # |
"key" debe ser una Key de Google válida y para obtener una consulta el apartado para "Voice to Text".
"beep" solo tiene dos valores: 0 reproduce el sonido "Beep" y 1 no lo reproduce.
"rtimeout" Si el valor es establecido, el valor de la opción "wait" dejará de ser usado, de forma que solo se escuchará hasta los n segundos de voz establecidos y mandada la petición a Google.
"intkey" Si el valor es establecido y presionada la tecla durante la escucha de la voz, justo en ese momento será mandada la petición a Google. El valor por defecto es la "#".
Importante: En caso de tener establecido los valores para "rtimeout" y "intkey", la petición a Google se mandará en cuanto ocurra el primero de los dos casos, que llegue al final de los n segundos de escucha o se presione antes la tecla.
Respuesta
La ejecución de este comando devolverá dos valores:
- "textvoice": el texto de la voz reconocida
- "confidence": fiabilidad del reconocimiento realizado. Este valor estará comprendido entre 0 y 1, siendo 0 el 0% de fiabilidad y 1 el 100% de fiabilidad.
google_voice2textSTR
Ejemplo de google_voice2textSTR (reconocimento solo por voz):
{
"command": "google_voice2textSTR",
"options": "palabrasofrase;es;local;audio",
"userfield": "3"
}
Ejemplo de google_voice2textSTR (reconocimento por voz y marcación DTMF simultánea):
{
"command": "google_voice2textSTR",
"options": "palabrasofrase;es;local;audio;digitosadetectar;tiempodeespera",
"userfield": "3"
}
Se utiliza el servicio de reconocimiento de voz de Google para convertir la voz del llamante o llamado en texto legible. A diferencia de "google_voice2text", el reconocimiento de voz es en tiempo real, no hay que esperar un determinado nº de segundos de silencio ni de escucha para convertir la voz en texto, sino que mientras se habla se va detectando la voz, de forma que si se detecta una palabra clave, detiene la conversión y devuelve el texto del audio detectado hasta ese momento.
Si al comando se le añade los parámetros de detección de DTMF (ndtmf, timeoutdtmf) será capaz de detectar voz y marcación DTMF simultáneamente.
Valores que contiene options
"options": "{keywords};{language};{locationfile};{fileaudio};{ndtmf};{timeoutdtmf}",
Valor | Descripción | Tipo |
---|---|---|
keywords | Palabras o frases clave a detectar para finalizar la escucha y devolver el texto del audio. Una o más palabras/frases separados por coma ",". | string |
language | Código del idioma a reconocer de la "Tabla de idiomas de reconocimiento de voz de Google" | string |
locationfile | Localización del fichero a reproducir. "local", se reproducirá el fichero de audio localizado el panel de netelip, "remote", se reproducirá el fichero de una url | "local" o "remote" |
fileaudio | Nombre de fichero de audio de locución de vPBX o url del audio remoto | string |
ndtmf | Nº máximo de digitos a detectar | integer |
timeoutdtmf | Tiempo de espera en segundos para marcar | integer |
Respuesta
La ejecución de este comando devolverá dos valores:
- "textvoice": el texto de la voz o marcación DTMF reconocida
- "confidence": fiabilidad del reconocimiento realizado tanto por voz o marcación DTMF. Este valor estará comprendido entre 0 y 1, siendo 0 el 0% de fiabilidad y 1 el 100% de fiabilidad.
hangup
Ejemplo de hangup:
{
"command" : "hangup",
"options" : "",
"userfield": "colgando"
}
Cuelga la llamada en curso.
Valores que contiene options
El argumento options no se usa con el comando hangup, se recomienda poner una cadena vacía o un valor 0.
ivr
Ejemplo de ivr:
{
"command" : "ivr",
"options" : "eligedepartamento",
"userfield": 3
}
Transfiere una llamada a un IVR existente en vPBX.
Valores que contiene options
"options": "{name}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
name | Nombre del ivr |
language
Ejemplo de language:
{
"command" : "language",
"options" : "es",
"userfield": 2
}
Establece el idioma para las locuciones predeterminadas cuando una llamada se desvía a vPBX.
Un ejemplo de locución puede ser "Por favor deje su mensaje después de la señal".
Por defecto el valor es el inglés (en).
Valores que contiene options
"options": "{language}",
Valor | Descripción | Valores | Defecto |
---|---|---|---|
language | Dos caracteres que indican el idioma de las locuciones | "en" o "es" | "en" |
play
Ejemplos de play:
{
"command" : "play",
"options" : "local;musica1&musica2&musica3",
"userfield": 4
}
{
"command" : "play",
"options" : "remote;http://www.midominio.com/mimusica.mp3",
"userfield": "musica"
}
Reproduce un fichero de sonido guardado en vPBX.
La localización del fichero se indica con "local" o "remote", se usa ";" para separar la localización del nombre del fichero.
"local" indica un fichero ubicado en vPBX y "remote" indica una url accesible públicamente donde se encuentra el fichero de audio.
Se pueden reproducir varios ficheros de forma secuencial usando como separador entre ficheros "&" (solo disponible para localización "local").
Valores que contiene options
"options": "{location};{files}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
location | Localización | "local" o "remote" | |
files | fichero o ficheros separados por "&" | string |
play_getdtmf
Ejemplos de play_getdtmf:
{
"command" : "play_getdtmf",
"options" : "local;musicadtmf;6000;3",
"userfield": 2
}
{
"command" : "play_getdtmf",
"options" : "remote;http://www.midominio.com/mimusicadtmf.mp3;6000;2",
"userfield": 2
}
Reproduce un fichero de sonido guardado en vPBX y espera a que sea marcada una opción DTMF.
La localización del fichero se indica con "local" o "remote", se usa ";" para separar la localización del nombre del fichero.
Una vez se pulse la cantidad máxima de dígitos DTMF parará la reproducción del fichero de audio y se enviara en la variable "dtmf" los dígitos marcados. En caso de no marcar ninguna tecla y pasado el tiempo de espera se enviará la variable "dtmf" con el valor “timeout”.
Valores que contiene options
"options": "{location};{files};{wait};{digits}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
location | Localización | "local" o "remote" | |
file | nombre de fichero o url | string | |
wait | Tiempo de espera en milisegundos | integer | |
digits | Máximo de dígitos DTMF | integer |
queue
Ejemplo de queue:
{
"command": "queue",
"options": "soporte;3",
"userfield": ""
}
Transfiere una llamada a una cola de llamadas existente en vPBX con o sin prioridad.
La prioridad tiene un valor entre 1 y 10 siendo 1 la mayor prioridad. El valor por defecto es 0 (sin prioridad). Cada llamada es encolada por orden de entrada (FIFO).
Valores que contiene options
"options": "{name};{priority}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
name | Nombre de la cola | ||
priority | Valor de la prioridad | De 0 a 10 | 0 |
record
Ejemplo de record:
{
"command": "record",
"options": "",
"userfield": 1
}
{
"command": "record",
"options": "noconnect",
"userfield": 1
}
Inicia la grabación de la llamada y finalizará cuando finalice la llamada.
La grabación de llamadas se realizará sobre el almacenamiento de netelip vDrive, con lo que será necesario activarlo antes de utilizar este comando (vDrive en su versión gratuita).
Una vez finalizada la llamada y realizada la grabación se devolverá la ruta del fichero en vDrive en la variable "description" con valor “/APIVoice/Record/fecha_llamada/nombre_fichero”, en la variable "URLAudio", la url del fichero para acceder a él sin necesidad de descargar y en la variable "URLDownload", la url del fichero para descargar.
Valores que contiene options
"options": {option},
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
option | vacío o "noconnect" | "" |
Options puede estar vacío "" o tener el valor "noconnect". Cuando se activa "noconnect" la grabación comenzará en el mismo momento en el que se ejecute el comando. Por defecto cuando no se añade esta opción la grabación de la llamada comienza cuando se conecta con una extensión, número de teléfono o servidor.
send_dtmf
Ejemplo de send_dtmf:
{
"command": "send_dtmf",
"options": "123;0.25",
"userfield": "1"
}
Genera tonos DTMF en la llamada en curso.
Valores que contiene options
"options": "{digits};{timeout}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
digits | Lista de dítgitos, comprendidos entre 0-9,a-d,A-D,# y * | string | |
timeout | Duración en segundos entre tono y tono. Enter 1 y 60 | float |
speak
Ejemplos de speak:
{
"command" : "speak",
"options" : "netelip;Pedro;Bienvenido a netelip;1.2",
"userfield": 2
}
{
"command" : "speak",
"options" : "google_TTS;es-ES-Standard-A;Bienvenido a netelip;1.2",
"userfield": 2
}
Reproduce el texto con la voz que se especifica (Text to speech).
Los proveedores de TTS disponibles son "netelip" y "google_TTS".
Para ver el código de voz que usará el proveedor consultar el apartado con la tabla de códigos TTS.
Valores que contiene options
"options": "{provider};{code};{text};{speed}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
provider | Proveedor: netelip o google_TTS | ||
code | Tabla de idiomas TTS. Consultar apartado. | ||
text | Texto a reproducir | string | |
speed | Velocidad de reproducción entre 1 y 2 | float |
speak_getdtmf
Ejemplos de speak_getdtmf:
{
"command" : "speak_getdtmf",
"options" : "netelip;Pedro;Introduzca su código de cliente;10000;5;1.2",
"userfield": 2
}
{
"command" : "speak_getdtmf",
"options" : "google_TTS;es-ES-Standard-A;Introduzca su código de cliente;10000;5;1.2",
"userfield": 2
}
Reproduce el texto con la voz que se especifica (Text to speech) y espera a que sea marcada una opción DTMF.
Los proveedores de TTS disponibles son "netelip" y "google_TTS".
Para ver el código de voz que usará el proveedor consultar el apartado con la tabla de códigos TTS.
Una vez se pulse la cantidad máxima de dígitos DTMF se enviara en la variable "dtmf" los dígitos marcados. En caso de no marcar ninguna tecla y pasado el tiempo de espera se enviará la variable "dtmf" con el valor “timeout”.
Valores que contiene options
"options": "{provider};{code};{text};{wait};{digits};{speed}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
provider | Proveedor: netelip o google_TTS | ||
code | Tabla de idiomas TTS. Consultar apartado. | ||
text | Texto a reproducir | string | |
wait | Tiempo de espera en milisegundos | integer | |
digits | Máximo de dígitos DTMF | integer | |
speed | Velocidad de reproducción entre 1 y 2 | float |
voicemail
Ejemplos de voicemail:
{
"command": "voicemail",
"options": "100",
"userfield": 9
}
{
"command": "voicemail",
"options": "110&112",
"userfield": 11
}
Deja un mensaje en el buzón de voz de una o varias extensiones de vPBX. Si se añaden varias extensiones deben ir separadas por "&".
Valores que contiene options
"options": "{extensions}",
Valor | Descripción | Tipo | Defecto |
---|---|---|---|
extensions | Extensión o extensiones de vPBX separadas por "&" | De 100 a 199 |
Errores
API Voice de netelip usa los siguientes códigos de error.
Estatos | Descripción | Cód. Respuesta |
---|---|---|
OK | OK | 200 |
ERROR | Unauthorized | 400 |
ERROR | Command not found | 401 |
ERROR | Language not found | 402 |
ERROR | Invalid audio file | 403 |
ERROR | Invalid option/s | 404 |
ERROR | Options or userfield is empty | 405 |
ERROR | Userfield is empty | 406 |
ERROR | Invalid voicemail status | 407 |
ERROR | Voicemail do not exist | 408 |
ERROR | Extension/s do not exist | 409 |
ERROR | Invalid phone number | 410 |
ERROR | Queue do not exist | 411 |
ERROR | Conference room is not activated | 412 |
ERROR | vDrive service is not activated | 413 |
ERROR | netelip user do not exist or is not activated | 414 |
ERROR | Voice to text failed | 415 |
ERROR | Unable to get data recognition | 416 |
ERROR | Invalid send_dtmf options | 417 |
ERROR | Invalid SIP server port | 418 |
ERROR | Invalid SIP server IP address | 419 |
ERROR | File greater than 2MB | 420 |
ERROR | Invalid option timeout for dial command | 422 |
ERROR | Invalid option announce for dial command | 423 |
ERROR | Busy destination | 424 |
ERROR | Internal error server | 500 |
ERROR | Service Unavailable | 503 |
Text to Speech (TTS)
API Voice de netelip dispone de dos proveedores para usar Text to Speech (TTS), netelip o Google_TTS.
netelip
Tabla de idiomas:
Proveedor | Idioma | Código | Ejemplo options para speak |
---|---|---|---|
netelip | Español masculino | Pedro | options: "netelip;Pedro;Bienvenido a netelip;1.2" |
netelip | Español femenino | Silvia | options: "netelip;Silvia;Bienvenido a netelip;1.2" |
netelip | Catalan masculino | Jordi | options: "netelip;Jordi;Bienvenido a netelip;1.2" |
netelip | Ingles masculino | Brian | options: "netelip;Brian;Bienvenido a netelip;1.2" |
google_TTS
Tabla de idiomas:
Proveedor | Idioma | Código | Género | Ejemplo options para speak |
---|---|---|---|---|
google_TTS | Afrikáans (Sudáfrica) | af-ZA-Standard-A | FEMENINO | options: "google_TTS;af-ZA-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Standard-A | FEMENINO | options: "google_TTS;ar-XA-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Standard-B | MASCULINO | options: "google_TTS;ar-XA-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Standard-C | MASCULINO | options: "google_TTS;ar-XA-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Standard-D | FEMENINO | options: "google_TTS;ar-XA-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Wavenet-A | FEMENINO | options: "google_TTS;ar-XA-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Wavenet-B | MASCULINO | options: "google_TTS;ar-XA-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Wavenet-C | MASCULINO | options: "google_TTS;ar-XA-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Árabe | ar-XA-Wavenet-D | FEMENINO | options: "google_TTS;ar-XA-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Bengalí (India) | bn-IN-Standard-A | FEMENINO | options: "google_TTS;bn-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Bengalí (India) | bn-IN-Standard-B | MASCULINO | options: "google_TTS;bn-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Bengalí (India) | bn-IN-Wavenet-A | FEMENINO | options: "google_TTS;bn-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Bengalí (India) | bn-IN-Wavenet-B | MASCULINO | options: "google_TTS;bn-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Búlgaro (Bulgaria) | bg-bg-Standard-A | FEMENINO | options: "google_TTS;bg-bg-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Catalán (España) | ca-es-Standard-A | FEMENINO | options: "google_TTS;ca-es-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Chino (Hong Kong) | yue-HK-Standard-A | FEMENINO | options: "google_TTS;yue-HK-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Chino (Hong Kong) | yue-HK-Standard-B | MASCULINO | options: "google_TTS;yue-HK-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Chino (Hong Kong) | yue-HK-Standard-C | FEMENINO | options: "google_TTS;yue-HK-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Chino (Hong Kong) | yue-HK-Standard-D | MASCULINO | options: "google_TTS;yue-HK-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Checo (República Checa) | cs-CZ-Standard-A | FEMENINO | options: "google_TTS;cs-CZ-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Checo (República Checa) | cs-CZ-Wavenet-A | FEMENINO | options: "google_TTS;cs-CZ-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Standard-A | FEMENINO | options: "google_TTS;da-DK-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Standard-C | MASCULINO | options: "google_TTS;da-DK-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Standard-D | FEMENINO | options: "google_TTS;da-DK-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Standard-E | FEMENINO | options: "google_TTS;da-DK-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Wavenet-A | FEMENINO | options: "google_TTS;da-DK-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Wavenet-C | MASCULINO | options: "google_TTS;da-DK-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Wavenet-D | FEMENINO | options: "google_TTS;da-DK-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Danés (Dinamarca) | da-DK-Wavenet-E | FEMENINO | options: "google_TTS;da-DK-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Bélgica) | nl-BE-Standard-A | FEMENINO | options: "google_TTS;nl-BE-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Bélgica) | nl-BE-Standard-B | MASCULINO | options: "google_TTS;nl-BE-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Bélgica) | nl-BE-Wavenet-A | FEMENINO | options: "google_TTS;nl-BE-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Bélgica) | nl-BE-Wavenet-B | MASCULINO | options: "google_TTS;nl-BE-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Standard-A | FEMENINO | options: "google_TTS;nl-NL-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Standard-B | MASCULINO | options: "google_TTS;nl-NL-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Standard-C | MASCULINO | options: "google_TTS;nl-NL-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Standard-D | FEMENINO | options: "google_TTS;nl-NL-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Standard-E | FEMENINO | options: "google_TTS;nl-NL-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Wavenet-A | FEMENINO | options: "google_TTS;nl-NL-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Wavenet-B | MASCULINO | options: "google_TTS;nl-NL-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Wavenet-C | MASCULINO | options: "google_TTS;nl-NL-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Wavenet-D | FEMENINO | options: "google_TTS;nl-NL-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Holandés (Países Bajos) | nl-NL-Wavenet-E | FEMENINO | options: "google_TTS;nl-NL-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Standard-A | FEMENINO | options: "google_TTS;en-AU-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Standard-B | MASCULINO | options: "google_TTS;en-AU-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Standard-C | FEMENINO | options: "google_TTS;en-AU-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Standard-D | MASCULINO | options: "google_TTS;en-AU-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Wavenet-A | FEMENINO | options: "google_TTS;en-AU-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Wavenet-B | MASCULINO | options: "google_TTS;en-AU-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Wavenet-C | FEMENINO | options: "google_TTS;en-AU-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Australia) | en-AU-Wavenet-D | MASCULINO | options: "google_TTS;en-AU-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Standard-A | FEMENINO | options: "google_TTS;en-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Standard-B | MASCULINO | options: "google_TTS;en-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Standard-C | MASCULINO | options: "google_TTS;en-IN-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Standard-D | FEMENINO | options: "google_TTS;en-IN-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Wavenet-A | FEMENINO | options: "google_TTS;en-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Wavenet-B | MASCULINO | options: "google_TTS;en-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Wavenet-C | MASCULINO | options: "google_TTS;en-IN-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (India) | en-IN-Wavenet-D | FEMENINO | options: "google_TTS;en-IN-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Standard-A | FEMENINO | options: "google_TTS;en-GB-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Standard-B | MASCULINO | options: "google_TTS;en-GB-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Standard-C | FEMENINO | options: "google_TTS;en-GB-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Standard-D | MASCULINO | options: "google_TTS;en-GB-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Standard-F | FEMENINO | options: "google_TTS;en-GB-Standard-F;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Wavenet-A | FEMENINO | options: "google_TTS;en-GB-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Wavenet-B | MASCULINO | options: "google_TTS;en-GB-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Wavenet-C | FEMENINO | options: "google_TTS;en-GB-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Wavenet-D | MASCULINO | options: "google_TTS;en-GB-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (Reino Unido) | en-GB-Wavenet-F | FEMENINO | options: "google_TTS;en-GB-Wavenet-F;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-A | MASCULINO | options: "google_TTS;en-US-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-B | MASCULINO | options: "google_TTS;en-US-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-C | FEMENINO | options: "google_TTS;en-US-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-D | MASCULINO | options: "google_TTS;en-US-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-E | FEMENINO | options: "google_TTS;en-US-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-F | FEMENINO | options: "google_TTS;en-US-Standard-F;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-G | FEMENINO | options: "google_TTS;en-US-Standard-G;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-H | FEMENINO | options: "google_TTS;en-US-Standard-H;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-I | MASCULINO | options: "google_TTS;en-US-Standard-I;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Standard-J | MASCULINO | options: "google_TTS;en-US-Standard-J;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-A | MASCULINO | options: "google_TTS;en-US-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-B | MASCULINO | options: "google_TTS;en-US-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-C | FEMENINO | options: "google_TTS;en-US-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-D | MASCULINO | options: "google_TTS;en-US-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-E | FEMENINO | options: "google_TTS;en-US-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-F | FEMENINO | options: "google_TTS;en-US-Wavenet-F;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-G | FEMENINO | options: "google_TTS;en-US-Wavenet-G;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-H | FEMENINO | options: "google_TTS;en-US-Wavenet-H;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-I | MASCULINO | options: "google_TTS;en-US-Wavenet-I;Bienvenido a netelip;1.2" |
google_TTS | Inglés (EE.UU.) | en-US-Wavenet-J | MASCULINO | options: "google_TTS;en-US-Wavenet-J;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Standard-A | FEMENINO | options: "google_TTS;fil-PH-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Standard-B | FEMENINO | options: "google_TTS;fil-PH-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Standard-C | MASCULINO | options: "google_TTS;fil-PH-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Standard-D | MASCULINO | options: "google_TTS;fil-PH-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Wavenet-A | FEMENINO | options: "google_TTS;fil-PH-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Wavenet-B | FEMENINO | options: "google_TTS;fil-PH-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Wavenet-C | MASCULINO | options: "google_TTS;fil-PH-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Filipino (Filipinas) | fil-PH-Wavenet-D | MASCULINO | options: "google_TTS;fil-PH-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Finés (Finlandia) | fi-FI-Standard-A | FEMENINO | options: "google_TTS;fi-FI-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Finés (Finlandia) | fi-FI-Wavenet-A | FEMENINO | options: "google_TTS;fi-FI-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Standard-A | FEMENINO | options: "google_TTS;fr-CA-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Standard-B | MASCULINO | options: "google_TTS;fr-CA-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Standard-C | FEMENINO | options: "google_TTS;fr-CA-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Standard-D | MASCULINO | options: "google_TTS;fr-CA-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Wavenet-A | FEMENINO | options: "google_TTS;fr-CA-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Wavenet-B | MASCULINO | options: "google_TTS;fr-CA-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Wavenet-C | FEMENINO | options: "google_TTS;fr-CA-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Francés (Canadá) | fr-CA-Wavenet-D | MASCULINO | options: "google_TTS;fr-CA-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Standard-A | FEMENINO | options: "google_TTS;fr-FR-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Standard-B | MASCULINO | options: "google_TTS;fr-FR-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Standard-C | FEMENINO | options: "google_TTS;fr-FR-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Standard-D | MASCULINO | options: "google_TTS;fr-FR-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Standard-E | FEMENINO | options: "google_TTS;fr-FR-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Wavenet-A | FEMENINO | options: "google_TTS;fr-FR-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Wavenet-B | MASCULINO | options: "google_TTS;fr-FR-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Wavenet-C | FEMENINO | options: "google_TTS;fr-FR-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Wavenet-D | MASCULINO | options: "google_TTS;fr-FR-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Francés (Francia) | fr-FR-Wavenet-E | FEMENINO | options: "google_TTS;fr-FR-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Standard-A | FEMENINO | options: "google_TTS;de-DE-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Standard-B | MASCULINO | options: "google_TTS;de-DE-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Standard-C | FEMENINO | options: "google_TTS;de-DE-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Standard-D | MASCULINO | options: "google_TTS;de-DE-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Standard-E | MASCULINO | options: "google_TTS;de-DE-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Standard-F | FEMENINO | options: "google_TTS;de-DE-Standard-F;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Wavenet-A | FEMENINO | options: "google_TTS;de-DE-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Wavenet-B | MASCULINO | options: "google_TTS;de-DE-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Wavenet-C | FEMENINO | options: "google_TTS;de-DE-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Wavenet-D | MASCULINO | options: "google_TTS;de-DE-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Wavenet-E | MASCULINO | options: "google_TTS;de-DE-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Alemán (Alemania) | de-DE-Wavenet-F | FEMENINO | options: "google_TTS;de-DE-Wavenet-F;Bienvenido a netelip;1.2" |
google_TTS | Griego (Grecia) | el-GR-Standard-A | FEMENINO | options: "google_TTS;el-GR-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Griego (Grecia) | el-GR-Wavenet-A | FEMENINO | options: "google_TTS;el-GR-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Guyaratí (India) | gu-IN-Standard-A | FEMENINO | options: "google_TTS;gu-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Guyaratí (India) | gu-IN-Standard-B | MASCULINO | options: "google_TTS;gu-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Guyaratí (India) | gu-IN-Wavenet-A | FEMENINO | options: "google_TTS;gu-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Guyaratí (India) | gu-IN-Wavenet-B | MASCULINO | options: "google_TTS;gu-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Standard-A | FEMENINO | options: "google_TTS;hi-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Standard-B | MASCULINO | options: "google_TTS;hi-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Standard-C | MASCULINO | options: "google_TTS;hi-IN-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Standard-D | FEMENINO | options: "google_TTS;hi-IN-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Wavenet-A | FEMENINO | options: "google_TTS;hi-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Wavenet-B | MASCULINO | options: "google_TTS;hi-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Wavenet-C | MASCULINO | options: "google_TTS;hi-IN-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Hindi (India) | hi-IN-Wavenet-D | FEMENINO | options: "google_TTS;hi-IN-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Húngaro (Hungría) | hu-HU-Standard-A | FEMENINO | options: "google_TTS;hu-HU-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Húngaro (Hungría) | hu-HU-Wavenet-A | FEMENINO | options: "google_TTS;hu-HU-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Islandés (Islandia) | is-is-Standard-A | FEMENINO | options: "google_TTS;is-is-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Standard-A | FEMENINO | options: "google_TTS;id-ID-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Standard-B | MASCULINO | options: "google_TTS;id-ID-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Standard-C | MASCULINO | options: "google_TTS;id-ID-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Standard-D | FEMENINO | options: "google_TTS;id-ID-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Wavenet-A | FEMENINO | options: "google_TTS;id-ID-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Wavenet-B | MASCULINO | options: "google_TTS;id-ID-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Wavenet-C | MASCULINO | options: "google_TTS;id-ID-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Indonesio (Indonesia) | id-ID-Wavenet-D | FEMENINO | options: "google_TTS;id-ID-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Standard-A | FEMENINO | options: "google_TTS;it-IT-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Standard-B | FEMENINO | options: "google_TTS;it-IT-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Standard-C | MASCULINO | options: "google_TTS;it-IT-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Standard-D | MASCULINO | options: "google_TTS;it-IT-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Wavenet-A | FEMENINO | options: "google_TTS;it-IT-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Wavenet-B | FEMENINO | options: "google_TTS;it-IT-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Wavenet-C | MASCULINO | options: "google_TTS;it-IT-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Italiano (Italia) | it-IT-Wavenet-D | MASCULINO | options: "google_TTS;it-IT-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Standard-A | FEMENINO | options: "google_TTS;ja-JP-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Standard-B | FEMENINO | options: "google_TTS;ja-JP-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Standard-C | MASCULINO | options: "google_TTS;ja-JP-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Standard-D | MASCULINO | options: "google_TTS;ja-JP-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Wavenet-A | FEMENINO | options: "google_TTS;ja-JP-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Wavenet-B | FEMENINO | options: "google_TTS;ja-JP-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Wavenet-C | MASCULINO | options: "google_TTS;ja-JP-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Japonés (Japón) | ja-JP-Wavenet-D | MASCULINO | options: "google_TTS;ja-JP-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Canarés (India) | kn-IN-Standard-A | FEMENINO | options: "google_TTS;kn-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Canarés (India) | kn-IN-Standard-B | MASCULINO | options: "google_TTS;kn-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Canarés (India) | kn-IN-Wavenet-A | FEMENINO | options: "google_TTS;kn-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Canarés (India) | kn-IN-Wavenet-B | MASCULINO | options: "google_TTS;kn-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Standard-A | FEMENINO | options: "google_TTS;ko-KR-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Standard-B | FEMENINO | options: "google_TTS;ko-KR-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Standard-C | MASCULINO | options: "google_TTS;ko-KR-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Standard-D | MASCULINO | options: "google_TTS;ko-KR-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Wavenet-A | FEMENINO | options: "google_TTS;ko-KR-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Wavenet-B | FEMENINO | options: "google_TTS;ko-KR-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Wavenet-C | MASCULINO | options: "google_TTS;ko-KR-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Coreano (Corea del Sur) | ko-KR-Wavenet-D | MASCULINO | options: "google_TTS;ko-KR-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Letón (Letonia) | lv-lv-Standard-A | MASCULINO | options: "google_TTS;lv-lv-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Standard-A | FEMENINO | options: "google_TTS;ms-MY-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Standard-B | MASCULINO | options: "google_TTS;ms-MY-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Standard-C | FEMENINO | options: "google_TTS;ms-MY-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Standard-D | MASCULINO | options: "google_TTS;ms-MY-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Wavenet-A | FEMENINO | options: "google_TTS;ms-MY-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Wavenet-B | MASCULINO | options: "google_TTS;ms-MY-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Wavenet-C | FEMENINO | options: "google_TTS;ms-MY-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Malayo (Malasia) | ms-MY-Wavenet-D | MASCULINO | options: "google_TTS;ms-MY-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Malabar (India) | ml-IN-Standard-A | FEMENINO | options: "google_TTS;ml-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Malabar (India) | ml-IN-Standard-B | MASCULINO | options: "google_TTS;ml-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Malabar (India) | ml-IN-Wavenet-A | FEMENINO | options: "google_TTS;ml-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Malabar (India) | ml-IN-Wavenet-B | MASCULINO | options: "google_TTS;ml-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Standard-A | FEMENINO | options: "google_TTS;cmn-CN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Standard-B | MASCULINO | options: "google_TTS;cmn-CN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Standard-C | MASCULINO | options: "google_TTS;cmn-CN-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Standard-D | FEMENINO | options: "google_TTS;cmn-CN-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Wavenet-A | FEMENINO | options: "google_TTS;cmn-CN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Wavenet-B | MASCULINO | options: "google_TTS;cmn-CN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Wavenet-C | MASCULINO | options: "google_TTS;cmn-CN-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-CN-Wavenet-D | FEMENINO | options: "google_TTS;cmn-CN-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-TW-Standard-A | FEMENINO | options: "google_TTS;cmn-TW-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-TW-Standard-B | MASCULINO | options: "google_TTS;cmn-TW-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-TW-Standard-C | MASCULINO | options: "google_TTS;cmn-TW-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-TW-Wavenet-A | FEMENINO | options: "google_TTS;cmn-TW-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-TW-Wavenet-B | MASCULINO | options: "google_TTS;cmn-TW-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Chino mandarín | cmn-TW-Wavenet-C | MASCULINO | options: "google_TTS;cmn-TW-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Standard-A | FEMENINO | options: "google_TTS;nb-NO-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Standard-B | MASCULINO | options: "google_TTS;nb-NO-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Standard-C | FEMENINO | options: "google_TTS;nb-NO-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Standard-D | MASCULINO | options: "google_TTS;nb-NO-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Wavenet-A | FEMENINO | options: "google_TTS;nb-NO-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Wavenet-B | MASCULINO | options: "google_TTS;nb-NO-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Wavenet-C | FEMENINO | options: "google_TTS;nb-NO-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-NO-Wavenet-D | MASCULINO | options: "google_TTS;nb-NO-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-no-Standard-E | FEMENINO | options: "google_TTS;nb-no-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-no-Standard-E | FEMENINO | options: "google_TTS;nb-no-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Noruego (Noruega) | nb-no-Wavenet-E | FEMENINO | options: "google_TTS;nb-no-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Standard-A | FEMENINO | options: "google_TTS;pl-PL-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Standard-B | MASCULINO | options: "google_TTS;pl-PL-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Standard-C | MASCULINO | options: "google_TTS;pl-PL-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Standard-D | FEMENINO | options: "google_TTS;pl-PL-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Standard-E | FEMENINO | options: "google_TTS;pl-PL-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Wavenet-A | FEMENINO | options: "google_TTS;pl-PL-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Wavenet-B | MASCULINO | options: "google_TTS;pl-PL-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Wavenet-C | MASCULINO | options: "google_TTS;pl-PL-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Wavenet-D | FEMENINO | options: "google_TTS;pl-PL-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Polaco (Polonia) | pl-PL-Wavenet-E | FEMENINO | options: "google_TTS;pl-PL-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Brasil) | pt-BR-Standard-A | FEMENINO | options: "google_TTS;pt-BR-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Brasil) | pt-BR-Standard-B | MASCULINO | options: "google_TTS;pt-BR-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Brasil) | pt-BR-Wavenet-A | FEMENINO | options: "google_TTS;pt-BR-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Brasil) | pt-BR-Wavenet-B | MASCULINO | options: "google_TTS;pt-BR-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Standard-A | FEMENINO | options: "google_TTS;pt-PT-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Standard-B | MASCULINO | options: "google_TTS;pt-PT-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Standard-C | MASCULINO | options: "google_TTS;pt-PT-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Standard-D | FEMENINO | options: "google_TTS;pt-PT-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Wavenet-A | FEMENINO | options: "google_TTS;pt-PT-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Wavenet-B | MASCULINO | options: "google_TTS;pt-PT-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Wavenet-C | MASCULINO | options: "google_TTS;pt-PT-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Portugués (Portugal) | pt-PT-Wavenet-D | FEMENINO | options: "google_TTS;pt-PT-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Standard-A | FEMENINO | options: "google_TTS;pa-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Standard-B | MASCULINO | options: "google_TTS;pa-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Standard-C | FEMENINO | options: "google_TTS;pa-IN-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Standard-D | MASCULINO | options: "google_TTS;pa-IN-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Wavenet-A | FEMENINO | options: "google_TTS;pa-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Wavenet-B | MASCULINO | options: "google_TTS;pa-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Wavenet-C | FEMENINO | options: "google_TTS;pa-IN-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Panyabí (India) | pa-IN-Wavenet-D | MASCULINO | options: "google_TTS;pa-IN-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Rumano (Rumania) | ro-RO-Standard-A | FEMENINO | options: "google_TTS;ro-RO-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Rumano (Rumania) | ro-RO-Wavenet-A | FEMENINO | options: "google_TTS;ro-RO-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Standard-A | FEMENINO | options: "google_TTS;ru-RU-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Standard-B | MASCULINO | options: "google_TTS;ru-RU-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Standard-C | FEMENINO | options: "google_TTS;ru-RU-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Standard-D | MASCULINO | options: "google_TTS;ru-RU-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Standard-E | FEMENINO | options: "google_TTS;ru-RU-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Wavenet-A | FEMENINO | options: "google_TTS;ru-RU-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Wavenet-B | MASCULINO | options: "google_TTS;ru-RU-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Wavenet-C | FEMENINO | options: "google_TTS;ru-RU-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Wavenet-D | MASCULINO | options: "google_TTS;ru-RU-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Ruso (Rusia) | ru-RU-Wavenet-E | FEMENINO | options: "google_TTS;ru-RU-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Serbio (cirílico) | sr-rs-Standard-A | FEMENINO | options: "google_TTS;sr-rs-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Eslovaco (Eslovaquia) | sk-SK-Standard-A | FEMENINO | options: "google_TTS;sk-SK-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Eslovaco (Eslovaquia) | sk-SK-Wavenet-A | FEMENINO | options: "google_TTS;sk-SK-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Standard-A | FEMENINO | options: "google_TTS;es-ES-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Standard-B | MASCULINO | options: "google_TTS;es-ES-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Standard-C | FEMENINO | options: "google_TTS;es-ES-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Standard-D | FEMENINO | options: "google_TTS;es-ES-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Wavenet-B | MASCULINO | options: "google_TTS;es-ES-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Wavenet-C | FEMENINO | options: "google_TTS;es-ES-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Español (España) | es-ES-Wavenet-D | FEMENINO | options: "google_TTS;es-ES-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Español (EE.UU.) | es-US-Standard-A | FEMENINO | options: "google_TTS;es-US-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Español (EE.UU.) | es-US-Standard-B | MASCULINO | options: "google_TTS;es-US-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Español (EE.UU.) | es-US-Standard-C | MASCULINO | options: "google_TTS;es-US-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Español (EE.UU.) | es-US-Wavenet-A | FEMENINO | options: "google_TTS;es-US-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Español (EE.UU.) | es-US-Wavenet-B | MASCULINO | options: "google_TTS;es-US-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Español (EE.UU.) | es-US-Wavenet-C | MASCULINO | options: "google_TTS;es-US-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Standard-A | FEMENINO | options: "google_TTS;sv-SE-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Standard-B | FEMENINO | options: "google_TTS;sv-SE-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Standard-C | FEMENINO | options: "google_TTS;sv-SE-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Standard-D | MASCULINO | options: "google_TTS;sv-SE-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Standard-E | MASCULINO | options: "google_TTS;sv-SE-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Wavenet-A | FEMENINO | options: "google_TTS;sv-SE-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Wavenet-B | FEMENINO | options: "google_TTS;sv-SE-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Wavenet-C | MASCULINO | options: "google_TTS;sv-SE-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Wavenet-D | FEMENINO | options: "google_TTS;sv-SE-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Sueco (Suecia) | sv-SE-Wavenet-E | MASCULINO | options: "google_TTS;sv-SE-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Tamil (India) | ta-IN-Standard-A | FEMENINO | options: "google_TTS;ta-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Tamil (India) | ta-IN-Standard-B | MASCULINO | options: "google_TTS;ta-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Tamil (India) | ta-IN-Wavenet-A | FEMENINO | options: "google_TTS;ta-IN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Tamil (India) | ta-IN-Wavenet-B | MASCULINO | options: "google_TTS;ta-IN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Telugu (India) | te-IN-Standard-A | FEMENINO | options: "google_TTS;te-IN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Telugu (India) | te-IN-Standard-B | MASCULINO | options: "google_TTS;te-IN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Tailandés (Tailandia) | th-TH-Standard-A | FEMENINO | options: "google_TTS;th-TH-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Standard-A | FEMENINO | options: "google_TTS;tr-TR-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Standard-B | MASCULINO | options: "google_TTS;tr-TR-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Standard-C | FEMENINO | options: "google_TTS;tr-TR-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Standard-D | FEMENINO | options: "google_TTS;tr-TR-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Standard-E | MASCULINO | options: "google_TTS;tr-TR-Standard-E;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Wavenet- | FEMENINO | options: "google_TTS;tr-TR-Wavenet-;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Wavenet-B | MASCULINO | options: "google_TTS;tr-TR-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Wavenet-C | FEMENINO | options: "google_TTS;tr-TR-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Wavenet-D | FEMENINO | options: "google_TTS;tr-TR-Wavenet-D;Bienvenido a netelip;1.2" |
google_TTS | Turco (Turquía) | tr-TR-Wavenet-E | MASCULINO | options: "google_TTS;tr-TR-Wavenet-E;Bienvenido a netelip;1.2" |
google_TTS | Ucraniano (Ucrania) | uk-UA-Standard-A | FEMENINO | options: "google_TTS;uk-UA-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Ucraniano (Ucrania) | uk-UA-Wavenet-A | FEMENINO | options: "google_TTS;uk-UA-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Standard-A | FEMENINO | options: "google_TTS;vi-VN-Standard-A;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Standard-B | MASCULINO | options: "google_TTS;vi-VN-Standard-B;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Standard-C | FEMENINO | options: "google_TTS;vi-VN-Standard-C;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Standard-D | MASCULINO | options: "google_TTS;vi-VN-Standard-D;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Wavenet-A | FEMENINO | options: "google_TTS;vi-VN-Wavenet-A;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Wavenet-B | MASCULINO | options: "google_TTS;vi-VN-Wavenet-B;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Wavenet-C | FEMENINO | options: "google_TTS;vi-VN-Wavenet-C;Bienvenido a netelip;1.2" |
google_TTS | Vietnamita (Vietnam) | vi-VN-Wavenet-D | MASCULINO | options: "google_TTS;vi-VN-Wavenet-D;Bienvenido a netelip;1.2" |
Voice to Text
Para poder usar el servicio de Google se deben seguir estos pasos:
1 Ir a la consola de Google Cloud
2 Habilitar el producto y servicio "Google Cloud Speech API"
3 Acceder a 'APIs y servicios -> Credenciales' y crear una clave de API. Para restringir el acceso por IP a la key generada para la API se debe pulsar sobre ella y añadir la IP, por ejemplo la ip de apivoice 185.8.244.102.
4 Obtenida la key ya está listo para añadirlo como parámetro en el comando.
Tabla de idiomas de reconocimiento de voz de Google:
País | Idioma | Código |
---|---|---|
Afrikaans | af-ZA | |
Indonesia | Bahasa Indonesia | id-ID |
Malasia | Bahasa Melayu | ms-MY |
España | Català | ca-ES |
Rep. Checa | Čeština | cs-CZ |
Alemania | Deutsch | de-DE |
Australia | English | en-AU |
Canada | English | en-CA |
India | English | en-IN |
New Zealand | English | en-NZ |
South Africa | English | en-ZA |
United Kingdom | English | en-GB |
United States | English | en-US |
Argentina | Español | es-AR |
Bolivia | Español | es-BO |
Chile | Español | es-CL |
Colombia | Español | es-CO |
Costa Rica | Español | es-CR |
Ecuador | Español | es-EC |
El Salvador | Español | es-SV |
España | Español | es-ES |
Estados Unidos | Español | es-US |
Guatemala | Español | es-GT |
Honduras | Español | es-HN |
México | Español | es-MX |
Nicaragua | Español | es-NI |
Panamá | Español | es-PA |
Paraguay | Español | es-PY |
Perú | Español | es-PE |
Puerto Rico | Español | es-PR |
República Dominicana | Español | es-DO |
Uruguay | Español | es-UY |
Venezuela | Español | es-VE |
Euskara | eu-ES | |
Français | fr-FR | |
Galego | gl-ES | |
Hrvatski | hr_HR | |
IsiZulu | zu-ZA | |
Íslenska | is-IS | |
Italia | Italiano | it-IT |
Svizzera | Italiano | it-CH |
Magyar | hu-HU | |
Nederlands | nl-NL | |
Norsk bokmål | nb-NO | |
Polski | pl-PL | |
Brasil | Português | pt-BR |
Portugal | Português | pt-PT |
Română | ro-RO | |
Slovenčina | sk-SK | |
Suomi | fi-FI | |
Svenska | sv-SE | |
Türkçe | tr-TR | |
български | bg-BG | |
Pусский | ru-RU | |
Српски | sr-RS | |
한국어 | ko-KR | |
普通� (中国大�) | 中文 | cmn-Hans-CN |
普通� (香港) | 中文 | cmn-Hans-HK |
中文 (台灣) | 中文 | cmn-Hant-TW |
�語 (香港) | 中文 | yue-Hant-HK |
日本語 | ja-JP | |
Lingua latīna | la |
Caso práctico
Flujo de llamada recibida
Para ver el funcionamiento de API Voice se muestra a continuación el flujo de una llamada recibida. Las peticiones que realiza API Voice se indican con "P:" y las respuestas del controlador del cliente con "R:".
P: Recepción de llamada
Petición #1:
{
"ID": "1576556033.1735",
"api": "API 13a05",
"src": "638829213",
"dst": "34951504990",
"startcall": "2019-11-14 11:04:26",
"typesrc": "did",
"usersrc": "638829213"
}
API Voice recibe una llamada y realiza una petición a su URL de control de llamadas con todos los datos en POST.
R: Locución de espera
Respuesta #1:
{
"command" : "speak",
"options" : "google;es;Espere por favor.",
"userfield": "1"
}
El controlador recibe los datos de la llamada y le contesta a API Voice para que reproduzca una locución a partir del text con el comando speak.
P: Espera terminada
Petición #2:
{
"ID": "1576556033.1735",
"api": "API 13a05",
"src": "638829213",
"dst": "34951504990",
"startcall": "2019-11-14 11:04:26",
"typesrc": "did",
"usersrc": "638829213",
"command": "speak",
"options": "google;es;Espere por favor.",
"userfield": "1",
"description": "OK",
"statuscode": "200",
"startcall": "2019-11-14 11:04:26",
"durationcall": "3",
"durationcallanswered": "",
"statuscall": "ANSWER",
"channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
"typesrc": "did",
"usersrc": "683282931"
}
API Voice reproduce el texto y envía una nueva petición con el estado de la llamada.
API Voice copia los tres parámetros command, options y userfield tal como los recibió para que el controlador pueda saber que es lo último que hizo.
R: Grabar la llamada
Respuesta #2:
{
"command": "record",
"options": "",
"userfield": "2"
}
El controlador responde a API Voice indicando que active la grabación de la llamada.
P: Grabando
Petición #3:
{
"ID": "1576556033.1735",
"api": "API 13a05",
"src": "638829213",
"dst": "34951504990",
"userfield": "2",
"command": "record",
"options": "",
"description": "OK",
"statuscode": "200",
"startcall": "2019-11-14 11:04:26",
"durationcall": "4",
"durationcallanswered": "",
"dtmf": "",
"statuscall": "ANSWER",
"channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
"typesrc": "did",
"usersrc": "638829213"
}
API Voice activa la grabación de la llamada, crea el fichero de audio y envía una petición a su URL de control de llamadas con la información de la llamada y el comando ejecutado.
R: Identificador de llamada
Respuesta #3
{
"command": "callerid",
"options": "638829213;34951504990",
"userfield":"3"
}
El controlador indica a API Voice que cambie el identificador de llamada.
P: Identificador cambiado
Petición #4
{
"ID": "1576556033.1735",
"api": "API 13a05",
"src": "638829213",
"dst": "34951504990",
"userfield": "3",
"command": "callerid",
"options": "638829213;34951504990",
"description": "CallerID is updated 34951504990",
"statuscode": "200",
"startcall": "2019-11-14 11:04:26",
"durationcall": "4",
"durationcallanswered": "",
"dtmf": "",
"statuscall": "ANSWER",
"channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
"typesrc": "did",
"usersrc": "638829213"
}
API Voice cambia el identificador de llamada y envía una petición a su controlador indicando el estado de la llamada y espera nuevo comando.
R: Realizar una llamada
Respuesta #4
{
"command": "dial",
"options": "pstn,655443322,60",
"userfield": "4"
}
El controlador responde indicando a API Voice que realice una llamada a un número de la red pública.
P: Llamada terminada
Petición #4: NOANSWER
{
"ID": "1576556033.1735",
"api": "API 13a05",
"src": "638829213",
"dst": "34951504990",
"userfield": "4",
"command": "dial",
"options": "pstn,655443322,60",
"description": "NOANSWER",
"statuscode": "200",
"startcall": "2019-11-14 11:04:26",
"durationcall": "64",
"durationcallanswered": "",
"dtmf": "",
"statuscall": "ANSWER",
"channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
"typesrc": "did",
"usersrc": "638829213"
}
Petición #4: ANSWER
{
"ID": "1576556033.1735",
"api": "API 13a05",
"src": "638829213",
"dst": "34951504990",
"userfield": "4",
"command": "dial",
"options": "pstn,655443322,60",
"description": "ANSWER",
"statuscode": "200",
"startcall": "2019-11-14 11:04:26",
"durationcall": "96",
"durationcallanswered": "92",
"dtmf": "",
"statuscall": "ANSWER",
"channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
"typesrc": "did",
"usersrc": "638829213"
}
Una vez que API Voice realiza la llamada enviará el resultado de ésta en una petición a su URL de control de llamadas.
El el campo description se indicará el resultado de la llamada realizada por el comando dial.
Los campos durationcall y durationcallanswered reflejarán la duración de la llamada.
Terminada la llamada API Voice envía la petición y espera la siguiente orden.
R: Colgando la llamada
Respuesta #5
{
"command": "hangup",
"options": "",
"userfield":""
}
El controlador recibe el estado de la llamada realizada por API Voice e indica que se debe colgar la llamada y terminar el flujo de peticiones.
Flujo de llamada realizada desde lanzador
Para ver el funcionamiento de API Voice se muestra a continuación el flujo de una llamada realizada desde el lanzador de llamadas del cliente. Las peticiones que realiza API Voice se indican con "P:", las respuestas del controlador del cliente con "R:", las peticiones del script del lanzador de llamadas del cliente "PC:" y la respuesta de API Voice al lanzador "RC".
PC: script de lanzador de llamada
Petición #1
<?php
$url="https://api.netelip.com/v1/voice";
$data=array(
"token"=>"06d636492dc510e3e84884f886691766af15d8c58181d4178d79aba85181ab3d",
"api"=>"API eaba7",
"src"=>"34851000127",
"dst"=>"100",
"typedst"=>"extension",
"duration"=>60,
"userdata"=>"1");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result_curl= curl_exec($ch);
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close($ch);
echo $result_curl;
error_log($result_curl);
?>
RC: Lanzada la llamada
Respuesta #1
{
"response": "200",
"ID": "1671637004.1996"
}
En caso de recuperar un valor disinto de 200 en "response" y no obtener "ID", es porque ha ocurrido un error. Para más información sobre errores acceder a la sección Errores.
P: Recepción de llamada
Petición #2:
{
"ID": "1671637004.1996",
"api": "API eaba7",
"src": "34851000127",
"dst": "100",
"startcall": "2022-12-21 16:52:54",
"userdata": "1"
}
API Voice recibe una llamada y realiza una petición a su URL de control de realización de llamadas con todos los datos en POST.
R: Cambio de idioma
Respuesta #2:
{
"command" : "language",
"options" : "es",
"userfield": "1"
}
El controlador recibe los datos de la llamada y le contesta a API Voice para que cambie el idioma de las posibles locuciones con el comando language.
P: Cambiando de idioma
Petición #3:
{
"ID": "1671637004.1996",
"api": "API eaba7",
"src": "34851000127",
"dst": "100",
"userfield": "1",
"command": "language",
"options": "es",
"description": "OK",
"statuscode": "200",
"startcall": "2022-12-21 16:52:54",
"durationcall": "6",
"durationcallanswered": "",
"statuscall": "ANSWER",
"userdata": "1",
}
API Voice cambia el idioma en la llamada y envía una petición a su controlador indicando el estado de la llamada y espera nuevo comando.
R: Hacemos llamada al número de teléfono
Respuesta #3:
{
"command" : "dial",
"options" : "pstn,0034638829213,20",
"userfield": "2"
}
P: Haciendo la llamada
Petición #4:
{
"ID": "1671637004.1996",
"api": "API eaba7",
"src": "34851000127",
"dst": "100",
"userfield": "2",
"command": "dial",
"options": "pstn,0034638829213,20",
"startcall": "2022-12-21 16:53:18",
"durationcall": "0",
"durationcallanswered": "7",
"userdata": "1",
}
El controlador recibe los datos de la llamada y le contesta a API Voice para que llame al numero de teléfono 0034638829213 con el comando dial.
R: Colgamos la llamada
Respuesta #4:
{
"command" : "hangup",
"options" : "",
"userfield": ""
}
El controlador recibe los datos de la llamada y le contesta a API Voice para que cuelgue la llamada con el comando hangup y terminar el flujo de peticiones.
Ejemplos de apps de APIVoice
Se solicita un código apara acceder al menú del servicio
La aplicación de APIVoice controla el acceso a usuarios de un servicio telefónico solicitando al usuario que llama un código de acceso. El script se colocará en la URL recepción de llamadas.
# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación.
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
// Obtenemos los datos de la llamada y las guardamos en variables
$src = $_POST["src"];
$dst = $_POST["dst"];
$id = $_POST["ID"];
if ($src == "" || $dst == "" || $id != "") die(); // Algo está mal, terminamos
$dtmf = $_POST["dtmf"];
// Datos del ultimo comando ejecutado si no estamos al comienzo de una llamada
$command = $_POST["command"];
$options = $_POST["options"];
$userfield = ($_POST["userfield"] == "") ? "1" : $_POST["userfield"];
$messages = array(
1 => "Bienvenido a mi empresa, por favor escriba a continuacion su usuario.",
2 => "Su usuario es correcto, accedemos al menu del servicio.",
3 => "Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.",
4 => "Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.",
);
switch($userfield) {
case "0": // colgamos la llamada
$command = "hangup";
$options = "";
$userfield = "";
break;
case "1": // reproducimos una locucion esperando una respuesta
$command = "speak_getdtmf";
$options = "google;es;".$messages[1].";5000;4;1.2";
$userfield = "2";
break;
case "2":
$command = "speak_getdtmf";
switch($dtmf) {
case "timeout": // tiempo agotado, locucion y repetimos
$options = "netelip;Pedro;".$messages[1].";5000;4";
$userfield = "2";
break;
case("1111"): // usuario correcto, locucion y a la cola
$options = "netelip;Pedro;".$messages[2].$messages[4].";5000;1";
$userfield = "3";
break;
default: // usuario incorrecto, locución de despedida y colgamos
$command = "speak";
$options = "netelip;Pedro;".$messages[3];
$userfield = "0";
}
}
break;
case "3":
$command = "queue";
$userfield = "0";
switch($dtmf) {
case "timeout": // tiempo agotado, locucion y repetimos
$command = "speak_getdtmf";
$options = "netelip;Pedro;".$messages[4].";5000;1";
$userfield = "3";
break;
case "1": // ejecutamos la cola de atencion de la vPBX con prioridad 2
$options = "colaatencion;2";
break;
case "2": // ejecutamos la cola de soporte de la vPBX con prioridad 1
$options = "colasoporte;1";
break;
}
break;
}
$cadena = array("command"=>$comand, "options"=>$options, "userfield"=>$userfield);
echo(json_encode($cadena));
?>
#!/usr/bin/env python
messages = [
'Bienvenido a mi empresa, por favor escriba a continuacion su usuario.',
'Su usuario es correcto, accedemos al menu del servicio.',
'Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.',
'Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.',
]
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/controller', methods=['GET','POST'])
def controller():
if request.method == 'POST':
# Obtenemos los datos de la llamada y las guardamos en variables
src = request.form.get('src')
dst = request.form.get('dst')
idc = request.form.get('ID')
if src == None or dst == None or idc == None:
return jsonify(error='No se han definido argumentos')
if src == "" or dst == "" or idc == "":
return jsonify(error='Los argumentos no pueden ir vacios')
dtmf = request.form.get("dtmf")
# Datos del ultimo comando ejecutado
c = {
'command' : request.form.get("command"),
'options' : request.form.get("options"),
'userfield': request.form.get("userfield")
}
if c['userfield'] == "0": # colgamos la llamada
c['command'] = "hangup"
c['options'] = ""
c['userfield'] = ""
elif c['userfield'] == "1" or c['userfield'] == "" or c['userfield'] == None:
# reproducimos una locucion esperando una respuesta (llamada entrante)
c['command'] = "speak_getdtmf"
c['options'] = "google;es;%s;5000;4;1.2" % messages[0]
c['userfield'] = "2"
elif c['userfield'] == "2":
c['command'] = "speak_getdtmf"
if dtmf == "timeout": # tiempo agotado, locucion y repetimos
c['options'] = "netelip;Pedro;%s;5000;1" % messages[0]
c['userfield'] = "2"
elif dtmf == "1111": # usuario correcto, locucion y a la cola
c['options'] = "netelip;Pedro;%s%s;5000;1" % (messages[1], messages[3])
c['userfield'] = "3"
else: # usuario incorrecto, locución de despedida y colgamos
c['command'] = "speak"
c['options'] = "netelip;Pedro;%s" % messages[2]
c['userfield'] = "0"
elif c['userfield'] == "3":
c['command'] = "queue"
c['userfield'] = "0"
if dtmf == "timeout": # tiempo agotado, locucion y repetimos
c['command'] = "speak_getdtmf"
c['options'] = "netelip;Pedro;%s;5000;1" % messages[3]
c['userfield'] = "3"
elif dtmf == "1": # ejecutamos la cola de atencion de la vPBX con prioridad 2
c['options'] = "colaatencion;2"
elif dtmf == "2": # ejecutamos la cola de soporte de la vPBX con prioridad 1
c['options'] = "colasoporte;1"
print(jsonify(c))
return jsonify(c)
else:
return jsonify(error='Metodo no permitido')
if __name__ == '__name__':
app.run()
Lanzador de llamada a un número de teléfono
La aplicación de APIVoice lanza una llamada a un número de teléfono (a esta aplicación le faltaría el script correspondiente a la URL realización de llamadas).
curl -X POST https://api.netelip.com/v1/voice \
--data "token=11111112222222" \
--data "api=Mi API" \
--data "src=34951223344" \
--data "dst=0034666554433" \
--data "duration=30" \
--data "typedst=pstn"
<?php
$url="https://api.netelip.com/v1/voice";
$post = array(
"token" => "11111112222222",
"api" => "Mi API",
"src" => "34951223344",
"dst" => "0034666554433",
"duration" => "30",
"typedst" => "pstn",
);
$request = curl_init($url);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($request, CURLOPT_POSTFIELDS, $post);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($request);
$response_code = curl_getinfo($request, CURLINFO_HTTP_CODE);
if ($response !== false) {
if ($response_code == 200) {
echo $response;
}
} else {
echo "Error: ".$response_code;
}
curl_close($request);
?>
#!/usr/bin/env python
import requests
url = 'https://api.netelip.com/v1/voice'
data = {
'token' : '11111112222222',
'api' : 'Mi API',
'src' : '34951223344',
'dst' : '0034666554433',
'duration' : '30',
'typedst' : 'pstn',
}
response = requests.post(url=url, data=data, timeout=(5, 5), max_redirects=3)
if response:
if response.status_code == 200:
print(response.text)
else:
print("Error: %s" % $response.status_code)
Llamada a un contacto de nuestro listado
La aplicación de APIVoice llama a nuestra extensión y una vez contestada conectará con el número de teléfono de nuestro contacto. Script en nuestro lanzador de llamadas
curl -X POST https://api.netelip.com/v1/voice \
--data "token=11111112222222" \
--data "api=Mi API" \
--data "src=34951223344" \
--data "dst=100" \
--data "duration=30" \
--data "typedst=extension" \
--data "userdata=0034666554433"
<?php
$url="https://api.netelip.com/v1/voice";
$data=array(
"token"=>"11111112222222",
"api"=>"Mi API",
"src"=>"34951223344",
"dst"=>"100",
"typedst"=>"extension",
"duration"=>30,
"userdata"=>"0034666554433");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result_curl= curl_exec($ch);
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close($ch);
echo $result_curl;
error_log($result_curl);
?>
Script de la URL realización de llamadas
# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación.
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$telefono=$_POST["userdata"];
if ($_POST["userfield"]=="")
{
$userfield="0";
}
else
{
$userfield=$_POST["userfield"];
}
switch($userfield)
{
case "0":
$cadena=array("command"=>"language","options"=>"es","userfield"=>"1");
break;
case "1":
$cadena=array("command"=>"dial","options"=>"pstn,".$telefono.",20,calling,36000","userfield"=>"2");
break;
case "2":
$cadena=array("command"=>"hangup","options"=>"","userfield"=>"");
break;
}
echo json_encode($cadena);
?>
Llamada a un contacto de nuestro listado con cambio de identificador de llamada
La aplicación de APIVoice llama a nuestra extensión y una vez contestada conectará con el número de teléfono de nuestro contacto modificando antes el identificador de llamada que se le mostrará.
Script en nuestro lanzador de llamadas
curl -X POST https://api.netelip.com/v1/voice \
--data "token=11111112222222" \
--data "api=Mi API" \
--data "src=34951223344" \
--data "dst=100" \
--data "duration=30" \
--data "typedst=extension" \
--data "userdata=0034666554433"
<?php
$url="https://api.netelip.com/v1/voice";
$data=array(
"token"=>"11111112222222",
"api"=>"Mi API",
"src"=>"34951223344",
"dst"=>"100",
"typedst"=>"extension",
"duration"=>30,
"userdata"=>"0034666554433");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result_curl= curl_exec($ch);
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close($ch);
echo $result_curl;
error_log($result_curl);
?>
Script de la URL realización de llamadas
# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación.
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$telefono=$_POST["userdata"];
$callerid="netelip;XXXXXXXXXXX";
if ($_POST["userfield"]=="")
{
$userfield="0";
}
else
{
$userfield=$_POST["userfield"];
}
switch($userfield)
{
case "0":
$cadena=array("command"=>"language","options"=>"es","userfield"=>"1");
break;
case "1":
$cadena=array("command"=>"callerid","options"=>$callerid,"userfield"=>"2");
break;
case "2":
$cadena=array("command"=>"dial","options"=>"pstn,".$telefono.",20,calling,36000","userfield"=>"3");
break;
case "3":
$cadena=array("command"=>"hangup","options"=>"","userfield"=>"");
break;
}
echo json_encode($cadena);
?>