Files
zyt/server/app/common/service/TrtcCloudRecordingService.php
T
2026-03-24 16:32:56 +08:00

168 lines
6.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\common\service;
use think\facade\Log;
/**
* 腾讯云 TRTC 云端录制(CreateCloudRecording / DeleteCloudRecording
* 依赖:composer require tencentcloud/trtc
*/
class TrtcCloudRecordingService
{
public static function sdkAvailable(): bool
{
return class_exists(\TencentCloud\Trtc\V20190722\TrtcClient::class);
}
/**
* @return array{ok:bool,task_id?:string,message?:string}
*/
public static function startMixRecording(
int $sdkAppId,
string $roomId,
string $botUserId,
string $botUserSig
): array {
if (!self::sdkAvailable()) {
return ['ok' => 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_keyCAM 密钥)'];
}
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);
}
}