更新
This commit is contained in:
@@ -14,6 +14,7 @@ use app\model\User;
|
||||
use app\model\UserDailyStat;
|
||||
use app\service\AdminScopeService;
|
||||
use app\service\ComfyUIService;
|
||||
use app\service\CosyVoiceService;
|
||||
use app\service\DepartmentService;
|
||||
use app\service\DifyService;
|
||||
use app\service\OpenAIService;
|
||||
@@ -666,11 +667,87 @@ class Admin extends BaseApi
|
||||
AdminScopeService::requireAny($this->authUser(), ['btn:settings:save', 'can_manage_settings']);
|
||||
$input = $this->request->put();
|
||||
foreach ($input as $key => $value) {
|
||||
if ($key === 'voice_persona') {
|
||||
if (!is_array($value)) {
|
||||
return $this->error('AI 客服人物配置格式无效', 422);
|
||||
}
|
||||
$value = CosyVoiceService::normalizePersona($value);
|
||||
}
|
||||
SettingsService::set($key, $value);
|
||||
}
|
||||
CosyVoiceService::clearFailure();
|
||||
return $this->success(null, '设置已更新');
|
||||
}
|
||||
|
||||
public function uploadVoiceReference()
|
||||
{
|
||||
AdminScopeService::requireAny($this->authUser(), ['btn:settings:save', 'can_manage_settings']);
|
||||
$file = $this->request->file('file');
|
||||
if (!$file) {
|
||||
return $this->error('请选择 WAV 参考音频', 422);
|
||||
}
|
||||
|
||||
$originalName = basename((string) $file->getOriginalName());
|
||||
$extension = strtolower($file->extension() ?: pathinfo($originalName, PATHINFO_EXTENSION));
|
||||
if ($extension !== 'wav') {
|
||||
return $this->error('音色样本只支持 WAV 文件', 422);
|
||||
}
|
||||
if ((int) $file->getSize() > 15 * 1024 * 1024) {
|
||||
return $this->error('音色样本不能超过 15MB', 422);
|
||||
}
|
||||
|
||||
$header = @file_get_contents($file->getPathname(), false, null, 0, 12);
|
||||
if (!is_string($header) || strlen($header) < 12 || substr($header, 0, 4) !== 'RIFF' || substr($header, 8, 4) !== 'WAVE') {
|
||||
return $this->error('文件不是有效的 WAV 音频', 422);
|
||||
}
|
||||
|
||||
$targetDir = root_path() . 'storage' . DIRECTORY_SEPARATOR . 'cosyvoice';
|
||||
if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true) && !is_dir($targetDir)) {
|
||||
return $this->error('无法创建音色样本目录', 500);
|
||||
}
|
||||
|
||||
$storedName = 'voice-' . date('Ymd-His') . '-' . bin2hex(random_bytes(4)) . '.wav';
|
||||
$moved = $file->move($targetDir, $storedName);
|
||||
if (!$moved) {
|
||||
return $this->error('音色样本保存失败', 500);
|
||||
}
|
||||
|
||||
$path = $targetDir . DIRECTORY_SEPARATOR . $storedName;
|
||||
$persona = CosyVoiceService::getPersona();
|
||||
$persona['prompt_wav'] = $path;
|
||||
$persona['prompt_wav_name'] = $originalName;
|
||||
$persona = CosyVoiceService::normalizePersona($persona, $persona);
|
||||
SettingsService::set('voice_persona', $persona);
|
||||
CosyVoiceService::clearFailure($persona);
|
||||
|
||||
return $this->success([
|
||||
'name' => $persona['prompt_wav_name'],
|
||||
'path' => $persona['prompt_wav'],
|
||||
], '音色样本上传成功');
|
||||
}
|
||||
|
||||
public function previewVoicePersona()
|
||||
{
|
||||
AdminScopeService::requireAny($this->authUser(), ['btn:settings:save', 'can_manage_settings']);
|
||||
$text = trim((string) ($this->request->post('text') ?: '您好,我是您的 AI 客服,很高兴为您服务。'));
|
||||
$text = mb_substr($text, 0, 160);
|
||||
|
||||
try {
|
||||
CosyVoiceService::clearFailure();
|
||||
$speech = CosyVoiceService::speech($text);
|
||||
} catch (\Throwable $error) {
|
||||
return $this->error($error->getMessage(), 502);
|
||||
}
|
||||
|
||||
return response($speech['audio'], 200, [
|
||||
'Content-Type' => $speech['content_type'],
|
||||
'Content-Length' => (string) strlen($speech['audio']),
|
||||
'Cache-Control' => 'no-store',
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
'X-TTS-Provider' => 'cosyvoice',
|
||||
]);
|
||||
}
|
||||
|
||||
public function models()
|
||||
{
|
||||
AdminScopeService::requireAny($this->authUser(), ['menu:models', 'can_manage_models']);
|
||||
@@ -872,6 +949,9 @@ class Admin extends BaseApi
|
||||
'inpaint_seed_node',
|
||||
'inpaint_image_node',
|
||||
'inpaint_mask_node',
|
||||
'tts_model',
|
||||
'tts_voice',
|
||||
'tts_instructions',
|
||||
] as $key) {
|
||||
if (!array_key_exists($key, $raw)) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user