diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 2a76cb5d1..b3fc0f9ea 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -11,6 +11,7 @@ use Carbon\Carbon; use App\Models\File; use App\Models\User; use App\Module\Base; +use App\Module\Extranet; use App\Module\TimeRange; use App\Models\FileContent; use App\Models\AbstractModel; @@ -1476,6 +1477,50 @@ class DialogController extends AbstractController return Base::retSuccess("success"); } + /** + * @api {get} api/dialog/msg/voice2text 29. 语音消息转文字 + * + * @apiDescription 将语音消息转文字,需要token身份 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName msg__voice2text + * + * @apiParam {Number} msg_id 消息ID + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function msg__voice2text() + { + User::auth(); + // + $msg_id = intval(Request::input("msg_id")); + $msg = WebSocketDialogMsg::whereId($msg_id)->first(); + if (empty($msg)) { + return Base::retError("消息不存在或已被删除"); + } + if ($msg->type !== 'record') { + return Base::retError("仅支持语音消息"); + } + if ($msg['msg']['text']) { + return Base::retSuccess("success", $msg); + } + WebSocketDialog::checkDialog($msg->dialog_id); + // + $msgData = Base::json2array($msg->getRawOriginal('msg')); + $res = Extranet::openAItranscriptions(public_path($msgData['path'])); + if (Base::isError($res)) { + return $res; + } + // + $msg->updateInstance([ + 'msg' => array_merge($msgData, ['text' => $res['data']]), + ]); + $msg->save(); + return Base::retSuccess("success", $msg); + } + /** * @api {get} api/dialog/msg/mark 30. 消息标记操作 * diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index bd4581a40..f65a0829d 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -40,7 +40,7 @@ class SystemController extends AbstractController * @apiParam {String} type * - get: 获取(默认) * - all: 获取所有(需要管理员权限) - * - save: 保存设置(参数:['reg', 'reg_identity', 'reg_invite', 'temp_account_alias', 'login_code', 'password_policy', 'project_invite', 'chat_information', 'anon_message', 'e2e_message', 'auto_archived', 'archived_day', 'task_visible', 'task_default_time', 'all_group_mute', 'all_group_autoin', 'user_private_chat_mute', 'user_group_chat_mute', 'image_compress', 'image_save_local', 'start_home']) + * - save: 保存设置(参数:['reg', 'reg_identity', 'reg_invite', 'temp_account_alias', 'login_code', 'password_policy', 'project_invite', 'chat_information', 'anon_message', 'voice2text', 'e2e_message', 'auto_archived', 'archived_day', 'task_visible', 'task_default_time', 'all_group_mute', 'all_group_autoin', 'user_private_chat_mute', 'user_group_chat_mute', 'image_compress', 'image_save_local', 'start_home']) * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) @@ -66,6 +66,7 @@ class SystemController extends AbstractController 'project_invite', 'chat_information', 'anon_message', + 'voice2text', 'e2e_message', 'auto_archived', 'archived_day', @@ -93,6 +94,9 @@ class SystemController extends AbstractController return Base::retError('自动归档时间不可大于100天!'); } } + if ($all['voice2text'] == 'open' && empty(Base::settingFind('aibotSetting', 'openai_key'))) { + return Base::retError('开启语音转文字功能需要在应用中开启 ChatGPT AI 机器人。'); + } $setting = Base::setting('system', Base::newTrim($all)); } else { $setting = Base::setting('system'); @@ -113,6 +117,7 @@ class SystemController extends AbstractController $setting['project_invite'] = $setting['project_invite'] ?: 'open'; $setting['chat_information'] = $setting['chat_information'] ?: 'optional'; $setting['anon_message'] = $setting['anon_message'] ?: 'open'; + $setting['voice2text'] = $setting['voice2text'] ?: 'close'; $setting['e2e_message'] = $setting['e2e_message'] ?: 'close'; $setting['auto_archived'] = $setting['auto_archived'] ?: 'close'; $setting['archived_day'] = floatval($setting['archived_day']) ?: 7; diff --git a/app/Module/Extranet.php b/app/Module/Extranet.php index eb0ea021a..9556ef7cf 100644 --- a/app/Module/Extranet.php +++ b/app/Module/Extranet.php @@ -12,6 +12,49 @@ use Illuminate\Support\Facades\Config; */ class Extranet { + /** + * 通过 openAI 语音转文字 + * @param string $filePath + * @return array + */ + public static function openAItranscriptions($filePath) + { + if (!file_exists($filePath)) { + return Base::retError("语音文件不存在"); + } + $systemSetting = Base::setting('system'); + $aibotSetting = Base::setting('aibotSetting'); + if ($systemSetting['voice2text'] !== 'open' || empty($aibotSetting['openai_key'])) { + return Base::retError("语音转文字功能未开启"); + } + // + $extra = [ + 'Content-Type' => 'multipart/form-data', + 'Authorization' => 'Bearer ' . $aibotSetting['openai_key'], + ]; + if ($aibotSetting['openai_agency']) { + $extra['CURLOPT_PROXY'] = $aibotSetting['openai_agency']; + if (str_contains($aibotSetting['openai_agency'], 'socks')) { + $extra['CURLOPT_PROXYTYPE'] = CURLPROXY_SOCKS5; + } else { + $extra['CURLOPT_PROXYTYPE'] = CURLPROXY_HTTP; + } + } + $res = Ihttp::ihttp_request('https://api.openai.com/v1/audio/transcriptions', [ + 'file' => new \CURLFile($filePath), + 'model' => 'whisper-1' + ], $extra, 15); + if (Base::isError($res)) { + return Base::retError("语音转文字失败", $res); + } + $resData = Base::json2array($res['data']); + if (empty($resData['text'])) { + return Base::retError("语音转文字失败", $resData); + } + // + return Base::retSuccess("success", $resData['text']); + } + /** * 获取IP地址经纬度 * @param string $ip diff --git a/app/Module/Ihttp.php b/app/Module/Ihttp.php index 587f35a53..158e60798 100755 --- a/app/Module/Ihttp.php +++ b/app/Module/Ihttp.php @@ -35,8 +35,12 @@ class Ihttp if($post) { if (is_array($post)) { $filepost = false; - foreach ($post as $name => $value) { - if (is_string($value) && substr($value, 0, 1) == '@') { + foreach ($post as $value) { + if (is_string($value) && str_starts_with($value, '@')) { + $filepost = true; + break; + } + if ($value instanceof \CURLFile) { $filepost = true; break; } diff --git a/language/original-api.txt b/language/original-api.txt index 01c3bf717..af194c6a5 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -497,3 +497,10 @@ Api接口文档 请选择举报类型 请填写举报原因 + + +开启语音转文字功能需要在应用中开启 ChatGPT AI 机器人。 +语音转文字功能未开启 +语音文件不存在 +语音转文字失败 +仅支持语音消息 diff --git a/language/original-web.txt b/language/original-web.txt index 93661f768..0324622f9 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -1594,3 +1594,9 @@ License Key 举报原因 举报图 举报投诉 + +转文字 +语音转文字 +长按语音消息可转换成文字。 +需要在应用中开启 ChatGPT AI 机器人 +关闭语音转文字功能。 diff --git a/resources/assets/js/pages/manage/components/DialogView.vue b/resources/assets/js/pages/manage/components/DialogView.vue index 884edd58f..363a7069d 100644 --- a/resources/assets/js/pages/manage/components/DialogView.vue +++ b/resources/assets/js/pages/manage/components/DialogView.vue @@ -52,6 +52,9 @@