false, 'message' => '未安装 tencentcloud/trtc,请在 server 目录执行 composer update']; } $secretId = trim((string)config('trtc.api_secret_id', '')); $secretKey = trim((string)config('trtc.api_secret_key', '')); if ($secretId === '' || $secretKey === '') { return ['ok' => false, 'message' => '未配置 trtc.api_secret_id / trtc.api_secret_key(CAM 密钥)']; } if ($sdkAppId <= 0) { return ['ok' => false, 'message' => 'SdkAppId 无效']; } if (self::trtcUserSigSecretKey() === '') { return ['ok' => false, 'message' => '未配置 TRTC UserSig 密钥(project.trtc.secretKey)']; } $roomIdType = ctype_digit($roomId) ? 1 : 0; $region = (string)config('trtc.recording_api_region', 'ap-guangzhou'); try { $cred = new \TencentCloud\Common\Credential($secretId, $secretKey); $httpProfile = new \TencentCloud\Common\Profile\HttpProfile(); $httpProfile->setEndpoint('trtc.tencentcloudapi.com'); $clientProfile = new \TencentCloud\Common\Profile\ClientProfile(); $clientProfile->setHttpProfile($httpProfile); $client = new \TencentCloud\Trtc\V20190722\TrtcClient($cred, $region, $clientProfile); $req = new \TencentCloud\Trtc\V20190722\Models\CreateCloudRecordingRequest(); $req->SdkAppId = $sdkAppId; $req->RoomId = (string)$roomId; $req->RoomIdType = $roomIdType; $req->UserId = $botUserId; $req->UserSig = $botUserSig; $recordParams = new \TencentCloud\Trtc\V20190722\Models\RecordParams(); $recordParams->RecordMode = 2; $recordParams->StreamType = 0; $recordParams->MaxIdleTime = 300; $req->RecordParams = $recordParams; $tencentVod = new \TencentCloud\Trtc\V20190722\Models\TencentVod(); $tencentVod->ExpireTime = 0; $cloudVod = new \TencentCloud\Trtc\V20190722\Models\CloudVod(); $cloudVod->TencentVod = $tencentVod; $storage = new \TencentCloud\Trtc\V20190722\Models\StorageParams(); $storage->CloudVod = $cloudVod; $req->StorageParams = $storage; $videoParams = new \TencentCloud\Trtc\V20190722\Models\VideoParams(); $videoParams->Width = 720; $videoParams->Height = 1280; $videoParams->Fps = 15; $videoParams->BitRate = 1000000; $videoParams->Gop = 2; $mixTc = new \TencentCloud\Trtc\V20190722\Models\MixTranscodeParams(); $mixTc->VideoParams = $videoParams; $req->MixTranscodeParams = $mixTc; $mixLayout = new \TencentCloud\Trtc\V20190722\Models\MixLayoutParams(); $mixLayout->MixLayoutMode = 3; $req->MixLayoutParams = $mixLayout; $resp = $client->CreateCloudRecording($req); $taskId = $resp->TaskId ?? ''; if ($taskId === '') { return ['ok' => false, 'message' => 'CreateCloudRecording 未返回 TaskId']; } return ['ok' => true, 'task_id' => $taskId]; } catch (\Throwable $e) { Log::error('CreateCloudRecording failed: ' . $e->getMessage()); return ['ok' => false, 'message' => $e->getMessage()]; } } /** * @return array{ok:bool,message?:string} */ public static function stopRecording(int $sdkAppId, string $taskId): array { if ($taskId === '') { return ['ok' => true]; } if (!self::sdkAvailable()) { return ['ok' => false, 'message' => '未安装 tencentcloud/trtc']; } $secretId = trim((string)config('trtc.api_secret_id', '')); $secretKey = trim((string)config('trtc.api_secret_key', '')); if ($secretId === '' || $secretKey === '') { return ['ok' => false, 'message' => '未配置云 API 密钥']; } $region = (string)config('trtc.recording_api_region', 'ap-guangzhou'); try { $cred = new \TencentCloud\Common\Credential($secretId, $secretKey); $httpProfile = new \TencentCloud\Common\Profile\HttpProfile(); $httpProfile->setEndpoint('trtc.tencentcloudapi.com'); $clientProfile = new \TencentCloud\Common\Profile\ClientProfile(); $clientProfile->setHttpProfile($httpProfile); $client = new \TencentCloud\Trtc\V20190722\TrtcClient($cred, $region, $clientProfile); $req = new \TencentCloud\Trtc\V20190722\Models\DeleteCloudRecordingRequest(); $req->SdkAppId = $sdkAppId; $req->TaskId = $taskId; $client->DeleteCloudRecording($req); return ['ok' => true]; } catch (\Throwable $e) { Log::warning('DeleteCloudRecording: ' . $e->getMessage()); return ['ok' => false, 'message' => $e->getMessage()]; } } public static function trtcSdkAppId(): int { $p = config('project.trtc'); return (int)(is_array($p) ? ($p['sdkAppId'] ?? 0) : 0) ?: (int)config('trtc.sdkAppId', 0); } public static function trtcUserSigSecretKey(): string { $p = config('project.trtc'); $fromProject = is_array($p) ? (string)($p['secretKey'] ?? '') : ''; return $fromProject !== '' ? $fromProject : (string)config('trtc.secretKey', ''); } public static function makeBotUserSig(string $botUserId): string { $sdkAppId = self::trtcSdkAppId(); $key = self::trtcUserSigSecretKey(); $api = new TLSSigAPIv2($sdkAppId, $key); $expire = (int)(config('project.trtc.expireTime') ?? config('trtc.expireTime', 86400)); return $api->genUserSig($botUserId, $expire > 0 ? $expire : 86400); } }