This commit is contained in:
mkm 2023-10-12 18:20:55 +08:00
parent 5b55620e75
commit 4e3f84583f
5 changed files with 94 additions and 166 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
.env
/tests/tmp
/tests/.phpunit.result.cache
/public/tts

View File

@ -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;
}
}

View File

@ -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
View 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;
}
}

View File

@ -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,
],
];