更新
This commit is contained in:
parent
5b55620e75
commit
4e3f84583f
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
||||
/public/tts
|
@ -1,152 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app;
|
||||
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use IFlytek\Xfyun\Speech\ChatClient;
|
||||
use WebSocket\Client;
|
||||
use Workerman\Connection\AsyncTcpConnection;
|
||||
use support\Request;
|
||||
|
||||
class Pusher
|
||||
{
|
||||
private $app_id = '2eda6c2e';
|
||||
|
||||
private $api_key = '12ec1f9d113932575fc4b114a2f60ffd';
|
||||
|
||||
private $api_secret = 'MDEyMzE5YTc5YmQ5NjMwOTU1MWY4N2Y2';
|
||||
|
||||
private $chatClient;
|
||||
|
||||
public function onConnect(TcpConnection $connection)
|
||||
{
|
||||
echo "onConnect\n";
|
||||
}
|
||||
|
||||
public function onWebSocketConnect(TcpConnection $connection, $http_buffer)
|
||||
{
|
||||
echo "onWebSocketConnect\n";
|
||||
}
|
||||
|
||||
public function onMessage(TcpConnection $connection, $data)
|
||||
{
|
||||
$data=json_decode($data,true);
|
||||
if(isset($data[0])&&$data[0]['content']==''){
|
||||
return $connection->send(['header'=>['code'=>10003,'message'=>'消息不能为空']]);
|
||||
}
|
||||
if ($data != '') {
|
||||
$client = new Client($this->assembleAuthUrl('wss://spark-api.xf-yun.com/v2.1/chat'));
|
||||
// 连接到 WebSocket 服务器
|
||||
if ($client) {
|
||||
$this->chatClient=$client;
|
||||
// 发送数据到 WebSocket 服务器
|
||||
$data = $this->getBody($this->app_id, $data);
|
||||
|
||||
$client->send($data);
|
||||
// 从 WebSocket 服务器接收数据
|
||||
while (true) {
|
||||
$response = $client->receive();
|
||||
$resp = json_decode($response, true);
|
||||
$code = $resp["header"]["code"];
|
||||
// echo "从服务器接收到的数据: " . $response;
|
||||
if(0 == $code){
|
||||
$status = $resp["header"]["status"];
|
||||
if($status != 2){
|
||||
// $content = $resp['payload']['choices']['text'][0]['content'];
|
||||
$connection->send($response);
|
||||
}else{
|
||||
// $content = $resp['payload']['choices']['text'][0]['content'];
|
||||
$connection->send($response);
|
||||
|
||||
// $total_tokens = $resp['payload']['usage']['text']['total_tokens'];
|
||||
print("\n本次消耗token用量:\n");
|
||||
$client->close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($code==10004){
|
||||
return $connection->send(['header'=>['code'=>10004,'message'=>'上下文超出限制,请清空后重试']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onClose(TcpConnection $connection)
|
||||
{
|
||||
if($this->chatClient){
|
||||
$this->chatClient->close();
|
||||
}
|
||||
echo "onClose\n";
|
||||
}
|
||||
|
||||
function getBody($appid, $question)
|
||||
{
|
||||
$header = array(
|
||||
"app_id" => $appid,
|
||||
"uid" => "1"
|
||||
);
|
||||
|
||||
$parameter = array(
|
||||
"chat" => array(
|
||||
"domain" => "generalv2",
|
||||
"temperature" => 0.5,
|
||||
"max_tokens" => 8192
|
||||
)
|
||||
);
|
||||
|
||||
$payload = array(
|
||||
"message" => array(
|
||||
"text" => $question
|
||||
)
|
||||
);
|
||||
|
||||
$json_string = json_encode(array(
|
||||
"header" => $header,
|
||||
"parameter" => $parameter,
|
||||
"payload" => $payload
|
||||
));
|
||||
|
||||
return $json_string;
|
||||
}
|
||||
|
||||
function assembleAuthUrl($addr, $method = 'GET')
|
||||
{
|
||||
$apiKey = $this->api_key;
|
||||
$apiSecret = $this->api_secret;
|
||||
if ($apiKey == "" && $apiSecret == "") { // 不鉴权
|
||||
return $addr;
|
||||
}
|
||||
|
||||
$ul = parse_url($addr); // 解析地址
|
||||
if ($ul === false) { // 地址不对,也不鉴权
|
||||
return $addr;
|
||||
}
|
||||
// // $date = date(DATE_RFC1123); // 获取当前时间并格式化为RFC1123格式的字符串
|
||||
$timestamp = time();
|
||||
$rfc1123_format = gmdate("D, d M Y H:i:s \G\M\T", $timestamp);
|
||||
// $rfc1123_format = "Mon, 31 Jul 2023 08:24:03 GMT";
|
||||
|
||||
// 参与签名的字段 host, date, request-line
|
||||
$signString = array("host: " . $ul["host"], "date: " . $rfc1123_format, $method . " " . $ul["path"] . " HTTP/1.1");
|
||||
// 对签名字符串进行排序,确保顺序一致
|
||||
// ksort($signString);
|
||||
// 将签名字符串拼接成一个字符串
|
||||
$sgin = implode("\n", $signString);
|
||||
|
||||
// 对签名字符串进行HMAC-SHA256加密,得到签名结果
|
||||
$sha = hash_hmac('sha256', $sgin, $apiSecret, true);
|
||||
|
||||
$signature_sha_base64 = base64_encode($sha);
|
||||
|
||||
// 将API密钥、算法、头部信息和签名结果拼接成一个授权URL
|
||||
$authUrl = "api_key=\"$apiKey\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"$signature_sha_base64\"";
|
||||
// 对授权URL进行Base64编码,并添加到原始地址后面作为查询参数
|
||||
$authAddr = $addr . '?' . http_build_query(array(
|
||||
'host' => $ul['host'],
|
||||
'date' => $rfc1123_format,
|
||||
'authorization' => base64_encode($authUrl),
|
||||
));
|
||||
return $authAddr;
|
||||
}
|
||||
}
|
@ -41,10 +41,10 @@ class Pusher
|
||||
{
|
||||
$data=json_decode($data,true);
|
||||
|
||||
$tts_type=0;
|
||||
if(isset($data['tts'])){
|
||||
$tts_type = $data['tts'];
|
||||
}
|
||||
// $tts_type=0;
|
||||
// if(isset($data['tts'])){
|
||||
// $tts_type = $data['tts'];
|
||||
// }
|
||||
if(isset($data['data'])){
|
||||
$data = $data['data'];
|
||||
}
|
||||
@ -69,20 +69,20 @@ class Pusher
|
||||
if(0 == $code){
|
||||
$status = $resp["header"]["status"];
|
||||
if($status != 2){
|
||||
if($tts_type==1){
|
||||
$url=$this->tts($resp['payload']['choices']['text'][0]['content']);
|
||||
$resp['payload']['choices']['mp3']=$url;
|
||||
$response=json_encode($resp,true);
|
||||
// if($tts_type==1){
|
||||
// $url=$this->tts($resp['payload']['choices']['text'][0]['content']);
|
||||
// $resp['payload']['choices']['mp3']=$url;
|
||||
// $response=json_encode($resp,true);
|
||||
|
||||
}
|
||||
// }
|
||||
$connection->send($response);
|
||||
}else{
|
||||
if($tts_type==1){
|
||||
$url=$this->tts($resp['payload']['choices']['text'][0]['content']);
|
||||
$resp['payload']['choices']['mp3']=$url;
|
||||
$response=json_encode($resp,true);
|
||||
// if($tts_type==1){
|
||||
// $url=$this->tts($resp['payload']['choices']['text'][0]['content']);
|
||||
// $resp['payload']['choices']['mp3']=$url;
|
||||
// $response=json_encode($resp,true);
|
||||
|
||||
}
|
||||
// }
|
||||
$connection->send($response);
|
||||
|
||||
// $total_tokens = $resp['payload']['usage']['text']['total_tokens'];
|
||||
|
73
app/Tts.php
Normal file
73
app/Tts.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace app;
|
||||
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use IFlytek\Xfyun\Speech\ChatClient;
|
||||
use WebSocket\Client;
|
||||
use Workerman\Connection\AsyncTcpConnection;
|
||||
use support\Request;
|
||||
use Webman\Container;
|
||||
|
||||
use function DI\env;
|
||||
|
||||
class Tts
|
||||
{
|
||||
private $app_id = '2eda6c2e';
|
||||
|
||||
private $api_key = '12ec1f9d113932575fc4b114a2f60ffd';
|
||||
|
||||
private $api_secret = 'MDEyMzE5YTc5YmQ5NjMwOTU1MWY4N2Y2';
|
||||
|
||||
|
||||
private $ttsConfig = [
|
||||
'aue' => 'lame',
|
||||
'sfl' => 1,
|
||||
'vcn' => 'x4_lingxiaoyao_en'
|
||||
];
|
||||
|
||||
public function onConnect(TcpConnection $connection)
|
||||
{
|
||||
echo "onConnect\n";
|
||||
}
|
||||
|
||||
public function onWebSocketConnect(TcpConnection $connection, $http_buffer)
|
||||
{
|
||||
echo "onWebSocketConnect\n";
|
||||
}
|
||||
|
||||
public function onMessage(TcpConnection $connection, $data)
|
||||
{
|
||||
$data = json_decode($data, true);
|
||||
|
||||
// $tts_type=0;
|
||||
// if(isset($data['tts'])){
|
||||
// $tts_type = $data['tts'];
|
||||
// }
|
||||
if (isset($data['data'])) {
|
||||
$data = $data['data'];
|
||||
}
|
||||
if ($data == '') {
|
||||
return $connection->send(['header' => ['code' => 10003, 'message' => '消息不能为空']]);
|
||||
}
|
||||
if ($data != '') {
|
||||
$url = $this->tts($data);
|
||||
$resp['mp3'] = $url;
|
||||
$response = json_encode($resp, true);
|
||||
$connection->send($response);
|
||||
}
|
||||
}
|
||||
|
||||
public function onClose(TcpConnection $connection)
|
||||
{
|
||||
echo "onClose\n";
|
||||
}
|
||||
|
||||
function tts($text)
|
||||
{
|
||||
$name = time() . rand(1, 100000) . '.mp3';
|
||||
$tts = new extend\IFlytek\Xfyun\Speech\TtsClient($this->app_id, $this->api_key, $this->api_secret, $this->ttsConfig);
|
||||
file_put_contents(public_path('tts') . '/' . $name, $tts->request($text)->getBody()->getContents());
|
||||
return 'https://chat.lihaink.cn/tts/' . $name;
|
||||
}
|
||||
}
|
@ -46,4 +46,10 @@ return [
|
||||
'listen' => 'websocket://0.0.0.0:8585',
|
||||
'count' => 1,
|
||||
],
|
||||
'websocket_tts' => [
|
||||
// 这里指定进程类,就是上面定义的Pusher类
|
||||
'handler' => app\Tts::class,
|
||||
'listen' => 'websocket://0.0.0.0:8484',
|
||||
'count' => 1,
|
||||
],
|
||||
];
|
||||
|
Loading…
x
Reference in New Issue
Block a user