where('id', $audioId) ->findOrEmpty(); if ($audioInfo->isEmpty()) { throw new \Exception('任务不存在'); } $audioInfo->url = FileService::getFileUrl($audioInfo->url); $audioInfo->ws_url = $audioInfo->ws_url ?: ''; $audioInfo->text = $audioInfo->text ?: ''; self::$returnData = $audioInfo->toArray(); return true; } catch (\Exception $exception) { self::setError($exception->getMessage()); return false; } } /** * 删除音频转写记录 以及音频文件 * @param array $data * @return bool * @author L * @data 2024/6/29 16:02 */ public static function delete(array $data): bool { try { if (is_string($data['id'])) { AudioInfo::destroy(['id' => $data['id'], 'user_id' => self::$uid]); } else { AudioInfo::whereIn('id', $data['id'])->where('user_id', self::$uid)->select()->delete(); } return true; } catch (\Exception $exception) { self::setError($exception->getMessage()); return false; } } /** * 创建任务 * @param array $params * @return bool * @throws \Exception * @author L * @data 2024/6/29 10:46 */ public static function task(array $params): bool { $unit = TokenLogService::checkToken(self::$uid, 'meeting'); try { $request = [ 'language' => $params['language'], 'task_type' => $params['task_type'], 'url' => $params['url'], 'speaker' => $params['speaker'], 'translation' => $params['translation'], ]; if ($params['task_type'] == 2) { $request['tips'] = 'start'; } $response = \app\common\service\ToolsService::Asr()->text($request); if (!isset($response['data']['task_id']) || !isset($response['data']['duration'])) { self::setError('转写失败'); return false; } $audioInfo = AudioInfo::create([ 'task_id' => $response['data']['task_id'], 'url' => FileService::setFileUrl($params['url']), 'status' => 0, 'user_id' => self::$uid, 'task_type' => $params['task_type'], 'language' => $params['language'], 'speaker' => $params['speaker'], 'translation' => $params['translation'], 'name' => $params['name'] ]); if ($audioInfo->task_type == 1) { //离线 $audioInfo->status = 3; $audioInfo->task_id = $response['data']['task_id']; $audioInfo->save(); $unit = TokenLogService::checkToken(self::$uid, 'meeting'); //时长 $duration = $response['data']['duration'] ?? 60; //折算分钟 $minutes = ((int)($duration / 60)) + ($duration % 60 > 0 ? 1 : 0); $points = ceil($minutes * $unit); //token扣除 User::userTokensChange(self::$uid, $points); $extra = ['音视频时长' => $minutes, '算力单价' => $unit, '实际消耗算力' => $points]; //记录日志 AccountLogLogic::recordUserTokensLog(true, self::$uid, AccountLogEnum::TOKENS_DEC_MEETING, $points, $audioInfo->task_id, $extra); } else { //实时 $audioInfo->status = 1; //录音中 $audioInfo->ws_url = $response['data']['ws_url']; $audioInfo->save(); } self::$returnData = $audioInfo->toArray(); return true; } catch (\think\exception\HttpResponseException $exception) { throw $exception; } catch (\Throwable $exception) { self::setError($exception->getMessage()); return false; } } /** * 创建任务 * @param array $params * @return bool * @throws \Exception * @author L * @data 2024/6/29 10:46 */ public static function batch(array $data): bool { $unit = TokenLogService::checkToken(self::$uid, 'meeting'); try { if (count($data) > 10) { self::setError("批量最多支持10个文件"); return false; } foreach ($data as $params) { $request = [ 'language' => $params['language'], 'task_type' => 1, 'url' => $params['url'], 'speaker' => $params['speaker'], 'translation' => $params['translation'], ]; $audioInfo = AudioInfo::create([ 'url' => FileService::setFileUrl($params['url']), 'status' => 0, 'user_id' => self::$uid, 'task_type' => 1, 'language' => $params['language'], 'speaker' => $params['speaker'], 'translation' => $params['translation'], 'name' => $params['name'] ]); $response = \app\common\service\ToolsService::Asr()->text($request); if (!isset($response['data']['task_id']) || !isset($response['data']['duration'])) { $audioInfo->status = 5; $audioInfo->remark = '转写失败'; $audioInfo->save(); continue; } $audioInfo->status = 3; $audioInfo->task_id = $response['data']['task_id']; $audioInfo->save(); //时长 $duration = $response['data']['duration'] ?? 60; //折算分钟 $minutes = ((int)($duration / 60)) + ($duration % 60 > 0 ? 1 : 0); $points = ceil($minutes * $unit); //token扣除 User::userTokensChange(self::$uid, $points); $extra = ['音视频时长' => $minutes, '算力单价' => $unit, '实际消耗算力' => $points]; //记录日志 AccountLogLogic::recordUserTokensLog(true, self::$uid, AccountLogEnum::TOKENS_DEC_MEETING, $points, $audioInfo->task_id, $extra); } self::$returnData = []; return true; } catch (\think\exception\HttpResponseException $exception) { throw $exception; } catch (\Throwable $exception) { self::setError($exception->getMessage()); return false; } } /** * 获取任务状态 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function status(string $taskId): bool { $audioInfo = AudioInfo::where('task_id', $taskId)->findOrEmpty(); if ($audioInfo->isEmpty()) { self::setError("任务不存在"); return false; } $request = [ 'task_id' => $taskId ]; $response = \app\common\service\ToolsService::Asr()->status($request); if ($response['code'] != 10000) { self::setError("获取任务状态失败"); return false; } self::updateAudioInfo($response['data']); self::$returnData = $response['data']; return true; } /** * 重试 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function retry(int $audioId): bool { $audioInfo = AudioInfo::where('id', $audioId)->findOrEmpty(); if ($audioInfo->isEmpty()) { self::setError("任务不存在"); return false; } if (!in_array($audioInfo->status, [0, 5])) { //待处理 转写失败 self::setError("当前状态无法重试"); return false; } if ($audioInfo->task_type != 1) { self::setError("当前任务类型无法重试"); return false; } $request = [ 'language' => $audioInfo->language, 'task_type' => 1, 'url' => $audioInfo->url, 'speaker' => $audioInfo->speaker, 'translation' => $audioInfo->translation, ]; $response = \app\common\service\ToolsService::Asr()->text($request); if (!isset($response['data']['task_id']) || !isset($response['data']['duration'])) { self::setError('转写失败'); return false; } $audioInfo->status = 3; $audioInfo->task_id = $response['data']['task_id']; $audioInfo->save(); self::$returnData = $response['data']; return true; } /** * 富文本 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function text(array $data): bool { $audioInfo = AudioInfo::where('id', $data['id'])->findOrEmpty(); if ($audioInfo->isEmpty()) { self::setError("任务不存在"); return false; } $audioInfo->text = $data['text']; $audioInfo->save(); self::$returnData = $audioInfo->toArray(); return true; } /** * 暂停 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function pause(int $audioId): bool { $audioInfo = AudioInfo::where('id', $audioId)->findOrEmpty(); if ($audioInfo->isEmpty()) { self::setError("任务不存在"); return false; } $audioInfo->status = 2; $audioInfo->save(); self::$returnData = $audioInfo->toArray(); return true; } /** * 继续录音 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function continue(int $audioId): bool { $audioInfo = AudioInfo::where('id', $audioId)->findOrEmpty(); if ($audioInfo->isEmpty()) { self::setError("任务不存在"); return false; } $audioInfo->status = 1; $audioInfo->save(); self::$returnData = $audioInfo->toArray(); return true; } /** * 停止录音 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function stop(int $audioId, string $url): bool { $audioInfo = AudioInfo::where('id', $audioId)->findOrEmpty(); if ($audioInfo->isEmpty()) { self::setError("任务不存在"); return false; } $audioInfo->url = $url; $request = [ 'language' => $audioInfo->language, 'task_type' => $audioInfo->task_type, 'url' => $audioInfo->url, 'speaker' => $audioInfo->speaker, 'translation' => $audioInfo->translation, 'tips' => 'stop' ]; $response = \app\common\service\ToolsService::Asr()->text($request); if (!isset($response['data']['task_id']) || !isset($response['data']['duration'])) { $audioInfo->status = 5; $audioInfo->remark = '转写失败'; $audioInfo->save(); self::setError('转写失败'); return false; } $audioInfo->status = 3; //转写中 $audioInfo->task_id = $response['data']['task_id']; $audioInfo->save(); $unit = TokenLogService::checkToken(self::$uid, 'meeting'); //时长 $duration = $response['data']['duration'] ?? 60; //折算分钟 $minutes = ((int)($duration / 60)) + ($duration % 60 > 0 ? 1 : 0); $points = ceil($minutes * $unit); $extra = ['音视频时长' => $minutes, '算力单价' => $unit, '实际消耗算力' => $points]; //记录日志 AccountLogLogic::recordUserTokensLog(true, self::$uid, AccountLogEnum::TOKENS_DEC_MEETING, $points, $audioInfo->task_id, $extra); self::$returnData = $audioInfo->toArray(); return true; } /** * 更新音频信息 * @param array $data * @return bool * @author L * @data 2024/6/29 16:18 */ public static function updateAudioInfo(array $data): bool { $audioInfo = AudioInfo::where('task_id', $data['TaskId'])->findOrEmpty(); if ($audioInfo->isEmpty()) { return false; } $audioInfo->response = $data; $audioInfo->remark = $data['TaskStatus']; if ($data['TaskStatus'] == "COMPLETED") { $audioInfo->status = 4; } if ($data['TaskStatus'] == "FAILED") { $audioInfo->status = 5; } $audioInfo->save(); if ($audioInfo->status === 5) { //查询是否已返还 if (UserTokensLog::where('user_id', $audioInfo->user_id)->where('change_type', AccountLogEnum::TOKENS_DEC_MEETING)->where('action', 1)->where('task_id', $audioInfo->task_id)->count() == 0) { $points = UserTokensLog::where('user_id', $audioInfo->user_id)->where('change_type', AccountLogEnum::TOKENS_DEC_MEETING)->where('task_id', $audioInfo->task_id)->value('change_amount') ?? 0; AccountLogLogic::recordUserTokensLog(false, $audioInfo->user_id, AccountLogEnum::TOKENS_DEC_MEETING, $points, $audioInfo->task_id); } } return true; } }