Skip to content

Commit 1de978c

Browse files
committed
Merged API samples into the main project
1 parent 659ccc7 commit 1de978c

File tree

13 files changed

+397
-1
lines changed

13 files changed

+397
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ Other formats has to be converted before decoding.
3939

4040
## Other programming languages
4141

42-
See https://github.com/alphacep/api-samples
42+
Check other examples (Asterisk-EAGI, php, node, c#) in client-samples folder in this repository.

client-samples/asterisk/README-RU.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Использование сервера распознавания с Asterisk
2+
3+
### Устанавливаем зависимости
4+
5+
- asterisk
6+
- docker
7+
- пакеты для работы со звуком:
8+
9+
sudo apt install sox espeak
10+
11+
- пакет для python AGI и вебсокетов
12+
13+
sudo pip3 install pyst2 websocket-client
14+
15+
### Запускаем сервер распознавания
16+
17+
docker run -d -p 2700:2700 alphacep/kaldi-ru:latest
18+
19+
### Проверяем, что можем запустить EAGI скрипт
20+
21+
Код скрипта находится в файле [eagi-ru.py](https://github.com/alphacep/api-samples/blob/master/asterisk/eagi-ru.py) из этого пакета:
22+
23+
```
24+
cd /home/user
25+
git clone https://github.com/alphacep/api-samples
26+
cd api-samples/asterisk
27+
python3 eagi-ru.py
28+
ARGS: ['eagi-ru.py']
29+
^C
30+
```
31+
32+
### Настраиваем план звонков
33+
34+
В etc/extensions.conf
35+
36+
```
37+
exten => 200,1,Answer()
38+
same = n,EAGI(/home/user/api-samples/asterisk/eagi-ru.py)
39+
same = n,Hangup()
40+
```
41+
42+
### Звоним и проверяем работу
43+
44+
Для написания чатбота, сохранения результатов в базу, и так далее,
45+
изменяем код eagi-ru.py.
46+

client-samples/asterisk/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Using kaldi-websocket-python server with Asterisk
2+
3+
### Install dependencies
4+
5+
- asterisk
6+
- docker
7+
- TTS packages:
8+
9+
sudo apt install sox espeak
10+
11+
- AGI and websocket package
12+
13+
sudo pip3 install pyst2 websocket-client
14+
15+
### Start recognition server with docker
16+
17+
```
18+
docker run -d -p 2700:2700 alphacep/kaldi-en:latest
19+
```
20+
21+
alternatively, you can run https://github.com/alphacep/kaldi-websocket-python with your models.
22+
23+
### Test EAGI script
24+
25+
Script [eagi.py](https://github.com/alphacep/api-samples/blob/master/asterisk/eagi.py) is located here:
26+
27+
```
28+
cd /home/user
29+
git clone https://github.com/alphacep/api-samples
30+
cd api-samples/asterisk
31+
python3 eagi.py
32+
ARGS: ['eagi.py']
33+
^C
34+
```
35+
36+
### Configure dialplan for Asterisk
37+
38+
В etc/extensions.conf
39+
40+
```
41+
exten => 200,1,Answer()
42+
same = n,EAGI(/home/user/api-samples/asterisk/eagi.py)
43+
same = n,Hangup()
44+
```
45+
46+
### Call and check you get the response
47+
48+
For more advanced chatbot, database interoperation and other callflow adjustments modify eagi.py according to your needs.
49+
You can also use PHP/Perl, see other examples in this package.

client-samples/asterisk/eagi-ru.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/python3
2+
3+
from asterisk.agi import *
4+
import os
5+
from websocket import create_connection
6+
import json
7+
import uuid
8+
9+
AUDIO_FD = 3
10+
CONTENT_TYPE = 'audio/l16; rate=8000; channels=1'
11+
ACCEPT = 'audio/pcm'
12+
13+
def play_text(agi, text):
14+
fn = str(uuid.uuid4())
15+
os.system("espeak -v ru -w /tmp/%s.22.wav \"%s\"" % (fn, text))
16+
os.system("sox /tmp/%s.22.wav -r 8000 /tmp/%s.wav" % (fn, fn))
17+
agi.stream_file("/tmp/%s" % (fn))
18+
os.remove("/tmp/%s.22.wav" % (fn))
19+
os.remove("/tmp/%s.wav" % (fn))
20+
os.read(AUDIO_FD, 1000000) # Read remaining chunks
21+
22+
def process_chunk(agi, ws, buf):
23+
ws.send_binary(buf)
24+
res = json.loads(ws.recv())
25+
agi.verbose(str(res))
26+
if 'text' in res:
27+
play_text(agi, "Распознано " + res['text'])
28+
29+
def startAGI():
30+
agi = AGI()
31+
agi.verbose("EAGI script started...")
32+
ani = agi.env['agi_callerid']
33+
did = agi.env['agi_extension']
34+
agi.verbose("Call answered from: %s to %s" % (ani, did))
35+
play_text(agi, "Привет")
36+
37+
ws = create_connection("ws://localhost:2700")
38+
try:
39+
while True:
40+
data = os.read(AUDIO_FD, 8000)
41+
if not data:
42+
break
43+
process_chunk(agi, ws, data)
44+
finally:
45+
ws.close()
46+
47+
startAGI()

client-samples/asterisk/eagi.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/python3
2+
3+
from asterisk.agi import *
4+
import os
5+
from websocket import create_connection
6+
import json
7+
8+
AUDIO_FD = 3
9+
CONTENT_TYPE = 'audio/l16; rate=8000; channels=1'
10+
ACCEPT = 'audio/pcm'
11+
12+
13+
def process_chunk(agi, ws, buf):
14+
ws.send_binary(buf)
15+
res = json.loads(ws.recv())
16+
if 'result' in res:
17+
text = " ".join([w['word'] for w in res['result']])
18+
agi.verbose(text)
19+
os.system("espeak -w /tmp/response22.wav \"" + text.encode('utf-8') + "\"")
20+
os.system("sox /tmp/response22.wav -r 8000 /tmp/response.wav")
21+
agi.stream_file("/tmp/response")
22+
os.remove("/tmp/response.wav")
23+
24+
def startAGI():
25+
agi = AGI()
26+
agi.verbose("EAGI script started...")
27+
ani = agi.env['agi_callerid']
28+
did = agi.env['agi_extension']
29+
agi.verbose("Call answered from: %s to %s" % (ani, did))
30+
31+
ws = create_connection("wss://api.alphacephei.com/asr/en")
32+
try:
33+
while True:
34+
data = os.read(AUDIO_FD, 8000)
35+
if not data:
36+
break
37+
process_chunk(agi, ws, data)
38+
finally:
39+
ws.close()
40+
41+
startAGI()

client-samples/csharp/test.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Requires at least Mono 5.0 due to TLS issues
2+
3+
using System;
4+
using System.IO;
5+
using System.Text;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using System.Net.WebSockets;
9+
10+
11+
public class ASRTest
12+
{
13+
async Task RecieveResult(ClientWebSocket ws) {
14+
byte[] result = new byte[4096];
15+
Task<WebSocketReceiveResult> receiveTask = ws.ReceiveAsync(new ArraySegment<byte>(result), CancellationToken.None);
16+
await receiveTask;
17+
var receivedString = Encoding.UTF8.GetString(result, 0, receiveTask.Result.Count);
18+
Console.WriteLine("Result {0}", receivedString);
19+
}
20+
21+
async Task ProcessData(ClientWebSocket ws, byte[] data, int count) {
22+
await ws.SendAsync(new ArraySegment<byte>(data, 0, count), WebSocketMessageType.Binary, true, CancellationToken.None);
23+
await RecieveResult(ws);
24+
}
25+
26+
async Task ProcessFinalData(ClientWebSocket ws) {
27+
byte[] eof = Encoding.UTF8.GetBytes("{\"eof\" : 1}");
28+
await ws.SendAsync(new ArraySegment<byte>(eof), WebSocketMessageType.Text, true, CancellationToken.None);
29+
await RecieveResult(ws);
30+
}
31+
32+
async Task DecodeFile() {
33+
ClientWebSocket ws = new ClientWebSocket();
34+
await ws.ConnectAsync(new Uri("wss://api.alphacephei.com/asr/en/"), CancellationToken.None);
35+
36+
FileStream fsSource = new FileStream("test.wav",
37+
FileMode.Open, FileAccess.Read);
38+
39+
byte[] data = new byte[8000];
40+
while (true) {
41+
int count = fsSource.Read(data, 0, 8000);
42+
if (count == 0)
43+
break;
44+
await ProcessData(ws, data, count);
45+
}
46+
await ProcessFinalData(ws);
47+
48+
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "OK", CancellationToken.None);
49+
}
50+
51+
public static void Main() {
52+
Task.Run(async () => {
53+
await new ASRTest().DecodeFile();
54+
}).GetAwaiter().GetResult();
55+
}
56+
}

client-samples/node/test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const websocket = require('ws');
2+
const fs = require('fs');
3+
const ws = new websocket('wss://api.alphacephei.com/asr/en/');
4+
5+
ws.on('open', function open() {
6+
var readStream = fs.createReadStream('test.wav');
7+
readStream.on('data', function (chunk) {
8+
ws.send(chunk);
9+
});
10+
readStream.on('end', function () {
11+
ws.send('{"eof" : 1}');
12+
});
13+
});
14+
15+
ws.on('message', function incoming(data) {
16+
console.log(data);
17+
});
18+
19+
ws.on('close', function close() {
20+
process.exit()
21+
});

client-samples/php/asr-test.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
require_once("./vendor/autoload.php");
4+
5+
use WebSocket\Client;
6+
7+
$client = new Client("wss://api.alphacephei.com/asr/en/", array('timeout' => 200));
8+
$myfile = fopen("test.wav", "r");
9+
while(!feof($myfile)) {
10+
$data = fread($myfile, 8000);
11+
$client->send($data, 'binary');
12+
echo $client->receive() . "\n";
13+
}
14+
$client->send("{\"eof\" : 1}");
15+
echo $client->receive() . "\n";
16+
fclose($myfile);
17+
18+
?>

client-samples/php/composer.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"require": {
3+
"textalk/websocket": "1.0.*",
4+
"marcelog/pagi": "2.*"
5+
}
6+
}
7+

client-samples/php/tts-test.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
require_once("./vendor/autoload.php");
4+
5+
$url = 'https://api.alphacephei.com/tts';
6+
$data = array('text' => 'Hello world!');
7+
8+
$options = array(
9+
'http' => array(
10+
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
11+
'method' => 'POST',
12+
'content' => http_build_query($data)
13+
)
14+
);
15+
$context = stream_context_create($options);
16+
$result = file_get_contents($url, false, $context);
17+
if ($result === FALSE) { /* Handle error */ }
18+
file_put_contents("tts.wav", $result);
19+
?>

0 commit comments

Comments
 (0)