vosk-ASR asterisk调用[AI人工智能(五十三)]—东方仙盟

核心代码

目录结构

完整代码python

复制代码
#!/usr/bin/python3

from asterisk.agi import *
import os
from websocket import create_connection
import json
import traceback

AUDIO_FD = 3
CONTENT_TYPE = 'audio/l16; rate=8000; channels=1'
ACCEPT = 'audio/pcm'

def process_chunk(agi, ws, buf):
    agi.verbose("Processing chunk")
    ws.send_binary(buf)
    res = json.loads(ws.recv())
    agi.verbose("Result: " + str(res))
    if 'result' in res:
        text = " ".join([w['word'] for w in res['result']])
        os.system("espeak -w /tmp/response22.wav \"" + text.encode('utf-8') + "\"")
        os.system("sox /tmp/response22.wav -r 8000 /tmp/response.wav")
        agi.stream_file("/tmp/response")
        os.remove("/tmp/response.wav")

def startAGI():
    agi = AGI()
    agi.verbose("EAGI script started...")
    ani = agi.env['agi_callerid']
    did = agi.env['agi_extension']
    agi.verbose("Call answered from: %s to %s" % (ani, did))

    ws = create_connection("ws://localhost:2700")
    ws.send('{ "config" : { "sample_rate" : 8000 } }')
    agi.verbose("Connection created")

    try:
        while True:
            data = os.read(AUDIO_FD, 8000)
            if not data:
                break
            process_chunk(agi, ws, data)
    except Exception as err:
        agi.verbose(''.join(traceback.format_exception(type(err), err, err.__traceback__)).replace('\n', ' '))
    finally:
        ws.close()

startAGI()

完整php

复制代码
#!/usr/bin/php -q
<?php
/*
 * @author mihail.belobrov@gmail.com
 * For FreePBX
 */
ob_implicit_flush(false);
set_time_limit(0);
error_reporting(0);
 
$VersionPath    = dirname(__FILE__);
$LibPath        = $VersionPath.'/lib';

$voskServer = 'ws://127.0.0.1:2700';
$FD3 = 'php://fd/3';
require_once '/etc/freepbx.conf'; // Configure DB and other things
require_once '/var/lib/asterisk/agi-bin/phpagi.php'; // Load php-agi in FreePBX

$module_name	= 'eagiVosk';

$dbh = \FreePBX::Database(); // Connect to database
$outGoingPath = \FreePBX::Config()->get("ASTSPOOLDIR")."/outgoing"; // Recieve FreePBX settings
$monitorPath = \FreePBX::Config()->get("ASTSPOOLDIR")."/monitor"; // Call recordings storage

// Keywords for call directions
$word_arr = array(
		'tech' => 'ext-queues,8001,1',  	 // queue 8001
		'accountant' => 'from-did-direct,102,1', // accountant 202
		'operator' => 'ext-queues,800,1',	 // quue 800
);

$myagi = new AGI();
$myagi->answer();

// Loads websocket library
require_once("/var/www/html/tts/vosk/scripts/websocket-php-1.3.1/vendor/autoload.php"); 
use WebSocket\Client;
$client = new Client($voskServer, array('timeout' => 20,'fragment_size'=> 8192));
$client->send('{ "config" : { "sample_rate" : 8000 } }', 'text');

// Play hello sound
$myagi->exec('PLAYBACK',array('/var/lib/asterisk/sounds/ru/hello-world'));

$myText = array();
$totalText = '';
$mydata = fopen($FD3, "rb"); // opens file descriptor 3
$previous_text = '';
while(!feof($mydata)) {
	$data = fread($mydata,8192);
	$client->send($data, 'binary');
	$receive = $client->receive();
	
	$result = json_decode($receive, true);
	if(!empty($result['partial'])) {
		$myagi->verbose($result['partial'],3);
		if($previous_text != $result['partial']){
			$previous_text = $result['partial'];
			foreach ($word_arr as $word => $destination){
				if (preg_match('/'.$word.'/u', $previous_text , $matches) ){
					list($context,$ext,$priority) = explode(',',$destination);
					$myagi->exec_dial('Local',$ext.'@'.$context); // calls required direction
					break;
				}
			}
			
		}
		
	}
}
$client->send("{\"eof\" : 1}");
$receive = $client->receive();
fclose($mydata);

$myagi->hangup(); 
?>

Asterisk 插件

Asterisk 插件独立维护在专属项目中:https://github.com/alphacep/vosk-asterisk

我们提供 Asterisk 模块以最大限度简化集成流程,你只需编写如下拨号计划即可实现语音识别功能:

plaintext

复制代码
[internal]
exten = 1,1,Answer          ; 接听来电
same = n,Wait(1)            ; 等待1秒
same = n,SpeechCreate       ; 创建语音识别会话
same = n,SpeechBackground(hello) ; 播放hello语音并启动识别
same = n,Verbose(0,Result was ${SPEECH_TEXT(0)}) ; 打印识别结果

EAGI 方式

你也可以将音频流转发至 AMI/ARI/AGI 接口,由独立的 Web 应用处理音频数据。但从长期来看,这种方式需要你基于 Statis 自行重构 Asterisk 的全部语音处理逻辑,因此我们认为这并非实现语音交互界面的合理方案

从长远角度,实现具备自然用户体验的语音输入功能,最佳方案是采用异步处理机制。而异步输入处理需要比当前 Asterisk 语音 API 更复杂的技术架构支撑。未来我们可能会为 Asterisk 开发更完善的语音处理模块。

你仍可参考本项目中的 eagi.py 文件体验 EAGI 功能,使用方法如下:

安装依赖项

  • asterisk(Asterisk 核心程序)

  • docker(容器运行环境)

  • TTS 语音合成包: bash

    运行

    复制代码
    sudo apt install sox espeak
  • AGI 及 WebSocket 开发包: bash

    运行

    复制代码
    sudo pip3 install pyst2 websocket-client

通过 Docker 启动识别服务器

bash

运行

复制代码
docker run -d -p 2700:2700 alphacep/kaldi-en:latest

你也可选择自行部署 https://github.com/alphacep/vosk-server 并加载自定义模型。

测试 EAGI 脚本

示例脚本 eagi.py 可通过以下方式运行:

bash

运行

复制代码
cd /home/user
git clone https://github.com/alphacep/api-samples
cd api-samples/asterisk
python3 eagi.py
ARGS: ['eagi.py']  # 脚本启动成功提示
^C                 # 按Ctrl+C终止脚本

配置 Asterisk 拨号计划

编辑 /etc/asterisk/extensions.conf(原文笔误为 etc/extensions.conf):

plaintext

复制代码
exten => 200,1,Answer()                ; 匹配200号码,接听来电
same = n,EAGI(/home/user/api-samples/asterisk/eagi.py) ; 调用EAGI脚本处理语音
same = n,Hangup()                      ; 挂断通话

测试通话并验证响应

拨打 200 号码即可验证语音识别功能是否正常响应。

如需实现更复杂的聊天机器人、数据库交互或呼叫流程定制,可根据业务需求修改 eagi.py。你也可使用 PHP/Perl 开发(本项目中提供了对应示例)。

基于 PHP 的 EAGI 实现

如需在 FreePBX(原文笔误为 FreePBS)环境下使用 PHP 实现 EAGI,可参考示例脚本 eagi_phpagi.php

东方仙盟:拥抱知识开源,共筑数字新生态

在全球化与数字化浪潮中,东方仙盟始终秉持开放协作、知识共享的理念,积极拥抱开源技术与开放标准。我们相信,唯有打破技术壁垒、汇聚全球智慧,才能真正推动行业的可持续发展。

开源赋能中小商户:通过将前端异常检测、跨系统数据互联等核心能力开源化,东方仙盟为全球中小商户提供了低成本、高可靠的技术解决方案,让更多商家能够平等享受数字转型的红利。
共建行业标准:我们积极参与国际技术社区,与全球开发者、合作伙伴共同制定开放协议 与技术规范,推动跨境零售、文旅、餐饮等多业态的系统互联互通,构建更加公平、高效的数字生态。
知识普惠,共促发展:通过开源社区 、技术文档与培训体系,东方仙盟致力于将前沿技术转化为可落地的行业实践,赋能全球合作伙伴,共同培育创新人才,推动数字经济 的普惠式增长

阿雪技术观

在科技发展浪潮中,我们不妨积极投身技术共享。不满足于做受益者,更要主动担当贡献者。无论是分享代码、撰写技术博客,还是参与开源项目 维护改进,每一个微小举动都可能蕴含推动技术进步的巨大能量。东方仙盟是汇聚力量的天地,我们携手在此探索硅基 生命,为科技进步添砖加瓦。

Hey folks, in this wild tech - driven world, why not dive headfirst into the whole tech - sharing scene? Don't just be the one reaping all the benefits; step up and be a contributor too. Whether you're tossing out your code snippets , hammering out some tech blogs, or getting your hands dirty with maintaining and sprucing up open - source projects, every little thing you do might just end up being a massive force that pushes tech forward. And guess what? The Eastern FairyAlliance is this awesome place where we all come together. We're gonna team up and explore the whole silicon - based life thing, and in the process, we'll be fueling the growth of technology

相关推荐
橘bird2 小时前
Transformer 简介
人工智能·深度学习·transformer
阴阳怪气乌托邦2 小时前
请注意!AI低代码正在干掉传统开发
人工智能·低代码·工作流引擎
KG_LLM图谱增强大模型2 小时前
Palantir官方揭秘AIP:企业级人工智能平台的端到端架构
大数据·人工智能
hughnz2 小时前
Agentic LLM工作流在钻井日报分析中的应用
人工智能·钻井
arvin_xiaoting2 小时前
常驻Agent vs无状态Agent:多渠道AI架构的两条路
人工智能·ai agent·claude code·openclaw
新缸中之脑2 小时前
实战建筑智能体
人工智能
AI攻城狮2 小时前
小白如何选择LLM引擎:从架构视角看懂本地大模型的前台、后端与推理核心
人工智能·云原生·aigc
冴羽2 小时前
OpenClaw 龙虾零成本快速安装教程,不用花钱,无须 API Key
人工智能·aigc
RPA机器人就用八爪鱼2 小时前
RPA+AI赋能数字化办公:告别机械劳作,解锁全场景自动化
人工智能·机器人·自动化·rpa