💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 1、安装 GatewayWorker ~~~ composer require workerman/gateway-worker composer require workerman/gatewayclient ~~~ ## 2、创建 Workerman 启动文件 创建一个 artisan 命令行工具来启动 Socket 服务端,在`app/Console/Commands`目录下建立命令行文件。 ~~~ php artisan make:command GatewayworkerCommandAsr1 ~~~ ~~~ <?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; use Workerman\Worker; use GatewayWorker\Gateway; use GatewayWorker\Register; use GatewayWorker\BusinessWorker; use App\Gatewayworker\Asr1Events; class GatewayworkerCommandAsr1 extends Command { /** 命令 php artisan workerman start * @var string */ protected $worker_name = 'asr1'; protected $gate_port = '5752'; protected $register_port = '5751'; protected $start_port = '5000'; protected $signature = ''; protected $description = 'Start a Workerman server'; public function __construct() { $this->signature = $this->worker_name. ' {action} {--d}'; parent::__construct(); } public function handle() { global $argv; if (!in_array($action = $this->argument('action'), ['start', 'stop', 'restart', 'status','reload'])) { $this->error('Error Arguments'); exit; } $argv[0] = $this->worker_name; $argv[1] = $action; $argv[2] = $this->option('d') ? '-d' : '';//该参数是以daemon(守护进程)方式启动 $this->startRun(); } public function startRun(){ $this->startGateWay(); $this->startBusinessWorker(); $this->startRegister(); Worker::$pidFile = '/www/wwwroot/admin/vendor/workerman/'.$this->worker_name.'.pid'; Worker::runAll(); } private function startBusinessWorker() { $worker = new BusinessWorker(); $worker->name = $this->worker_name; $worker->count = 4; $worker->registerAddress = '127.0.0.1:'. $this->register_port; $worker->eventHandler = Asr1Events::class; } private function startGateWay() { $context = array( 'ssl' => array( // 使用绝对路径 'local_cert' => '/www/wwwroot/admin/app/socket_exam/ssl/server.pem' , 'local_pk' => '/www/wwwroot/admin/app/socket_exam/ssl/server.key' , 'verify_peer' => false, 'allow_self_signed' => true ) ); $gateway = new Gateway("websocket://0.0.0.0:". $this->gate_port); //$gateway->transport = 'ssl'; $gateway->name = $this->worker_name; $gateway->count = 4; $gateway->lanIp = '127.0.0.1'; $gateway->registerAddress = '127.0.0.1:'. $this->register_port; $gateway->startPort = $this->start_port; // 心跳间隔 $gateway->pingInterval = 30; // 发给客户端你的心跳数据 $gateway->pingData = '{"type":"ping"}'; } private function startRegister() { new Register('text://0.0.0.0:'. $this->register_port); } } ~~~ ## 3、创建事件监听文件 创建一个*app/Gatewayworker/Asr1Events.php*文件来监听处理 workman 的各种事件。 ~~~ <?php namespace App\Gatewayworker; use App\Services\Trans\DialogTransService; use GatewayWorker\Lib\Gateway; use Illuminate\Support\Facades\Log; use Workerman\Protocols\Ws; use Workerman\Connection\AsyncTcpConnection; use Workerman\Timer; class Asr1Events { use AsrTrait; static $connectionToB; static $token = ''; static $header = []; public static function onWorkerStart($businessWorker) { // echo "onWorkerStart\r\n"; } public static function onWebSocketConnect(string $client_id, array $data){ self::$header = $data; } public static function onConnect($client_id){ // 连接到来后,定时10秒关闭这个链接,需要10秒内发认证并删除定时器阻止关闭连接的执行 $auth_timer_id = Timer::add(10, function($client_id){ Gateway::closeClient($client_id); }, array($client_id), false); Gateway::updateSession($client_id, array('auth_timer_id' => $auth_timer_id)); /*客户端连接到时候触发*/ self::response($client_id,'',0,'','init'); //wss://api.aicloud.com/v10/asr/freetalk/cn_16k_common/utterance_stream?appkey=bc5d5437&access-token=3vo8NrO3TCKgvSXYQ7lKiQ self::$connectionToB = new AsyncTcpConnection('ws://api.aicloud.com'); self::$connectionToB->transport = 'ssl'; /*设置token*/ self::$token = DialogTransService::get_token_info(); } public static function onMessage($client_id, $data){ $option = self::setOption($data); usleep(10000); // 延迟 10 毫秒 self::$connectionToB->send($option); // 当收到消息时 self::$connectionToB->onMessage = function(AsyncTcpConnection $con, $result) use ($client_id) { $result_array = json_decode($result, true); if (isset($result_array['ERROR']) || isset($result_array['FATAL_ERROR'])){ $err_code = $result_array['errCode']; $err_msg = $result_array['errMessage']; self::response($client_id,'',$err_code,$err_msg,'end'); self::cloesWs($client_id); }/*错误*/ if (isset($result_array['respType']) && $result_array['respType'] == 'START'){ self::response($client_id,'',0,'','start'); }/*识别开始*/ if (isset($result_array['respType']) && $result_array['respType'] == 'RESULT'){ self::response( $client_id, $result_array['sentence']['result']['text'], 0, '', 'start' ); }/*结果*/ if (isset($result_array['respType']) && $result_array['respType'] == 'END'){ self::response($client_id,'',0,'','end'); self::cloesWs($client_id); }/*结束*/ }; self::$connectionToB->onError = function($connection, $code, $msg) use ($client_id) { self::cloesWs($client_id); }; self::$connectionToB->onClose = function($connection) use ($client_id){ self::cloesWs($client_id); }; self::$connectionToB->connect(); } public static function onClose($client_id) { self::response($client_id,'连接断开',419); } private static function setOption($data){ $data_arr = json_decode($data, true); if ( isset($data_arr['endFlag']) && $data_arr['endFlag'] == false || isset($data_arr['endFlag']) && $data_arr['endFlag'] == true ){ self::setLang(); // BINARY_TYPE_BLOB为文本 // BINARY_TYPE_ARRAYBUFFER为二进制 self::$connectionToB->websocketType = Ws::BINARY_TYPE_BLOB; if ($data_arr['endFlag'] == false){ // 认证成功,删除 10 关闭连接定 的时器 Timer::del($_SESSION['auth_timer_id']); return json_encode([ 'command' => 'START', 'config' => [ 'audioFormat' => 'pcm_s16le_16k', 'vadTail' => 3000, //结尾 'vadEnd' => 3500, //中间 'vadHead' => 3000, //开始 'vadMaxSegment' => 60 ], 'extraInfo' => '', 'recordId' => '', 'userId' => '', ],JSON_UNESCAPED_UNICODE); }else{ return json_encode([ 'command' => 'end', 'cancel' => false, ], JSON_UNESCAPED_UNICODE); } }else{ self::$connectionToB->websocketType = Ws::BINARY_TYPE_ARRAYBUFFER; return $data; } } private static function setLang(){ $lang = 'zh'; if (isset(self::$header['server']['REQUEST_URI'])){ $lang = explode('_', self::$header['server']['REQUEST_URI'])[1]; } if ($lang == 'zh'){ self::$connectionToB->_remoteURI = '/v10/asr/freetalk/cn_16k_common/utterance_stream?appkey=bc5d5437&access-token='. self::$token; }elseif($lang == 'ug'){ self::$connectionToB->_remoteURI = '/v10/asr/freetalk/ug_16k_common/utterance_stream?appkey=bc5d5437&access-token='. self::$token; }else{ self::$connectionToB->_remoteURI = '/v10/asr/freetalk/kk_16k_common/utterance_stream?appkey=bc5d5437&access-token='. self::$token; } } } ~~~ ### 命令 php artisan asr1 stop || start || start --d