Commit 94fa5ad7 authored by 刘小敏's avatar 刘小敏

3D试戴 提速 日志记录优化

parent fee528f8
......@@ -112,33 +112,36 @@ class AiTryon extends Common
]);
$this->svalidate($params, ".aiadd");
$user = auth_user();
// 校验商品分类是否在允许试戴分类中
$goodsService = new GoodsService();
$is_allowed = $goodsService->isCategoryAllowed('', $params['goods_id']);
if ($is_allowed === 0) {
custom_log('[AI生成图片接口] 商品所属分类不允许试戴 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('商品所属分类不允许试戴');
}
//开发过程中临时代码,AI图片生成次数有限
// $this->success('图片生成成功', 'https://zhubaoshop.sydggxs.com/uploads/20260508/c92396f646bd41887329891647fcfcaf.png');
$user = auth_user();
// 校验试戴次数 && 扣除积分
$userService = new User();
$res = $userService->isTry($user->id);
if ($res === 0) {
custom_log('[AI生成图片接口] 免费次数已用完 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
// 免费试戴次数用完后,扣积分,试戴一次扣10积分
$userService = new User();
$res = $userService->deductPoints($user->id, 10);
if ($res === 0) {
custom_log('[AI生成图片接口] 积分不足 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('免费次数已用完,积分不足,无法试戴');
}
}
// 合成AI图
$ai = new Ai();
$res = $ai->generateImage($params, $user->id, 'b64_json');
$res = $ai->generateImage($params, $user->id, 'url');
// 我的试戴
$tryonModel = new AiTryOnModel();
......@@ -154,20 +157,22 @@ class AiTryon extends Common
];
if ($res['code'] === 0) {
$tryonData['ai_status'] = 2;
$tryonData['ai_err_msg'] = $res['msg'];
$tryonModel->save($tryonData);
$this->error($res['msg']);
} else {
// 保存图片到本地
$upload = new Upload();
$attachment = $upload->uploadBase64($res['data']);
$aiService = new Ai();
$attachment = $aiService->saveFileLoc(isset($res['data']) ? $res['data'] : '', 'gen_ai');
// $upload = new Upload();
// $attachment = $upload->uploadBase64($res['data']);
// 记录入参日志
custom_log('用户ID:'. $user->id .' AI生成图片 保存到本地接口接口出参:'.json_encode($attachment), 'gen_ai_img_api');
custom_log('用户ID:'. $user->id .' AI生成图片 保存到本地接口接口出参:'.json_encode($attachment), 'gen_ai');
if($attachment['code'] == 0){
if($attachment == 0){
$tryonData['ai_status'] = 2;
$tryonData['ai_err_msg'] = '图片上传失败';
$tryonModel->save($tryonData);
......@@ -178,9 +183,9 @@ class AiTryon extends Common
$tryonData['ai_url'] = config('shopro.api_host') . $attachment['data'];
$tryonModel->save($tryonData);
//试戴次数+1
// 试戴次数+1
$userService = new User();
$res = $userService->addTryTimes($user->id);
$userService->addTryTimes($user->id);
$this->success('图片生成成功', config('shopro.api_host') . $attachment['data']??'');
}
......@@ -223,29 +228,32 @@ class AiTryon extends Common
]);
$this->svalidate($params, ".aiadd");
$user = auth_user();
// 校验商品分类是否在允许试戴分类中
$goodsService = new GoodsService();
$is_allowed = $goodsService->isCategoryAllowed('', $params['goods_id']);
if ($is_allowed === 0) {
custom_log('[AI生成视频接口] 商品所属分类不允许试戴 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('商品所属分类不允许试戴');
}
$user = auth_user();
//开发过程中临时调试代码
\think\Queue::push('\addons\shopro\job\AiVideoGen@save', ['taskid' => 'cgt-20260518151431-zcrgp', 'user' => $user], 'shopro-high');
$this->success('推送队列成功');
exit;
// \think\Queue::push('\addons\shopro\job\AiVideoGen@save', ['taskid' => 'cgt-20260518151431-zcrgp', 'user' => $user], 'shopro-high');
// $this->success('推送队列成功');
// exit;
// $this->success('视频生成中', 13);
// 校验试戴次数 && 扣除积分
$userService = new User();
$res = $userService->isTry($user->id);
if ($res === 0) {
custom_log('[AI生成视频接口] 免费次数已用完 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
// 免费试戴次数用完后,扣积分,试戴一次扣10积分
$userService = new User();
$res = $userService->deductPoints($user->id, 10);
if ($res === 0) {
custom_log('[AI生成视频接口] 积分不足 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('免费次数已用完,积分不足,无法试戴');
}
}
......
......@@ -625,7 +625,7 @@ if (!function_exists('format_log_error')) {
$logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
\think\Log::error($logInfo);
custom_log($logInfo, 'gen_ai_video');
custom_log($logInfo, 'gen_ai');
}
}
......
This diff is collapsed.
......@@ -18,6 +18,70 @@ class Ai
}
/**
* 保存远端文件到本地
* 主要用于3D试戴 2026.05.19
*/
public function saveFileLoc ($file_url, $log_name = 'gen_ai'){
if (empty($file_url)) {
return 0;
}
try {
custom_log('fileUrl: '.$file_url, $log_name);
// 1 生成存储目录(fastadmin标准uploads目录)
$upload_dir = '/uploads/ai_video/' . date('Ymd') . '/';
$dir = $this->public_dir . $upload_dir;
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
// 2 生成唯一文件名
$filename = md5(time() . uniqid()) . '.mp4';
$full_path = $this->public_dir . $upload_dir . $filename;
// 3 加载视频地址
$ch = curl_init($file_url);
$fp = fopen($full_path, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
// 4 写入文件
curl_exec($ch);
$error = curl_error($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 获取HTTP状态码
curl_close($ch);
fclose($fp);
// 5 严格判断:网络错误 / HTTP状态码异常 / 文件为空
if ($error || $http_code >= 400 || filesize($full_path) === 0) {
// 下载失败,删除产生的空文件
if (file_exists($full_path)) {
unlink($full_path);
}
custom_log('文件下载失败:' . $error . "HTTP状态码:{$http_code},文件为空", $log_name);
return 0; // 统一失败返回值
}
if (!file_exists($full_path)) {
return 0;
}
return $upload_dir . $filename;
} catch (\Exception $e){
format_log_error_custom_name($e, '文件下载失败', '', $log_name);
// custom_log('文件下载失败:' . $e->getMessage(), $log_name);
return 0;
}
}
/**
* AI 生成图片
* @param string $param 入参
* @param string $userId 入参
......@@ -28,7 +92,8 @@ class Ai
{
try {
$url = $this->ark_host . '/api/v3/images/generations';
$prompt = '严格复刻图片1 人物所有样貌特征、肢体姿势、场景背景、光影氛围一丝不变,精准匹配图片2 耳饰饰品佩戴到人物对应耳部位置,饰品贴合肌肤轮廓、尺寸比例适配、定点标准不跑偏、不悬空不变形不拉伸不重复生成;人物做原生自然轻度磨皮,柔和流畅瘦脸修容,保留真实皮肤纹理与面部细节,拒绝过度美颜、拒绝网红假脸、拒绝锥脸畸形,五官原生比例不改动,无建模感、无生硬 AI 违和感,整体色调光影统一,高清超清细节拉满,纯真人电商珠宝实拍大片质感,原图风格画质全程不变。';
// $prompt = '严格复刻图片1 人物所有样貌特征、肢体姿势、场景背景、光影氛围一丝不变,精准匹配图片2 耳饰饰品佩戴到人物对应耳部位置,饰品贴合肌肤轮廓、尺寸比例适配、定点标准不跑偏、不悬空不变形不拉伸不重复生成;人物做原生自然轻度磨皮,柔和流畅瘦脸修容,保留真实皮肤纹理与面部细节,拒绝过度美颜、拒绝网红假脸、拒绝锥脸畸形,五官原生比例不改动,无建模感、无生硬 AI 违和感,整体色调光影统一,高清超清细节拉满,纯真人电商珠宝实拍大片质感,原图风格画质全程不变。';
$prompt = '严格复刻图 1 人物样貌、姿势、背景与光影,将图 2 耳饰精准贴合佩戴于耳部,比例适配贴合不形变。人物自然轻磨皮柔和修脸,保留原生五官与皮肤细节,不假脸无 AI 违和感,色调光影统一,高清实拍珠宝电商质感。';
$params = [
'headers' => [
'Authorization' => 'Bearer ' . $this->api_key,
......@@ -40,16 +105,15 @@ class Ai
"image" => [$param['person_image'], $param['jewelry_image']],
"sequential_image_generation" => "disabled",
"response_format" => $response_format,
"size" => "2K",
"stream" => false,
"watermark" => true
"size" => "1024×1024",
"num" => 1,
],
'timeout' => 300,
'verify' => false, // 关闭 SSL 证书验证
'allow_redirects' => true
];
// 记录入参日志
custom_log('[AI生成图片接口]用户ID:'. $userId . ' response_format'. $response_format . ' AI生成图片接口入参:'.json_encode($params), 'gen_ai_img_api');
custom_log('[AI生成图片接口]用户ID:'. $userId . ' response_format'. $response_format . ' AI生成图片接口入参:'.json_encode($params), 'gen_ai');
// 发送请求
$client = new Http();
......@@ -61,7 +125,7 @@ class Ai
$result = json_decode($content, true);
// 记录出参日志
custom_log('[AI生成图片接口]用户ID:'. $userId . ' response_format'. $response_format .' AI生成图片接口出参:'.json_encode($result), 'gen_ai_img_api');
custom_log('[AI生成图片接口]用户ID:'. $userId . ' response_format'. $response_format .' AI生成图片接口出参:'.json_encode($result), 'gen_ai');
if ($response_format == 'b64_json'){
if (!$result || !isset($result['data'][0]['b64_json'])) {
......@@ -124,7 +188,9 @@ class Ai
// $resGenImg['data'] = 'https://ark-acg-cn-beijing.tos-cn-beijing.volces.com/doubao-seedream-5-0/02177752801269334e1fb186d00f6ff5c484dce264092c4da58e2_0.jpeg?X-Tos-Algorithm=TOS4-HMAC-SHA256&X-Tos-Credential=AKLTYWJkZTExNjA1ZDUyNDc3YzhjNTM5OGIyNjBhNDcyOTQ%2F20260430%2Fcn-beijing%2Ftos%2Frequest&X-Tos-Date=20260430T054730Z&X-Tos-Expires=86400&X-Tos-Signature=2d109489c534c8bd9e2f9f1820edff8956916da5ee5a477022f6ab8d3024af19&X-Tos-SignedHeaders=host';
$url = $this->ark_host . '/api/v3/contents/generations/tasks';
$prompt = '人物自然微动,轻微转头,微笑,眨眼,动作柔和流畅,画面稳定不闪烁、不抖动、不扭曲,真实人像质感,高清清晰,饰品完美展示,整体自然优雅,无变形、无穿模、无悬浮';
// $prompt = '人物自然微动,轻微转头,微笑,眨眼,动作柔和流畅,画面稳定不闪烁、不抖动、不扭曲,真实人像质感,高清清晰,饰品完美展示,整体自然优雅,无变形、无穿模、无悬浮';
// $prompt = '人物轻动转头,自然微笑眨眼,动作流畅柔和,画面稳定无抖动扭曲,真人高清质感,饰品完整清晰展示,整体优雅自然,无变形穿模悬浮';
$prompt = '人物微动转头微笑眨眼,动作顺滑画面稳定,高清真人质感,饰品清晰展示,无变形悬浮穿模';
$params = [
'headers' => [
'Authorization' => 'Bearer ' . $this->api_key,
......@@ -143,7 +209,10 @@ class Ai
]
],
"generate_audio" => false, // 不要声音
"safety_identifier" => md5($userId)
"resolution" => "720p", // 分辨率:降档提速(原1080p改为720p)枚举值: 480p 720p 1080p
"duration" => 5,
"draft" => true,
// "safety_identifier" => md5($userId)
],
'timeout' => 300,
'verify' => false, // 关闭 SSL 证书验证
......@@ -151,9 +220,9 @@ class Ai
];
// 记录入参日志
custom_log('用户ID:'. $userId .' AI生成视频接口入参:'.json_encode($params), 'gen_ai_video_api');
custom_log('用户ID:'. $userId .' AI生成视频接口入参:'.json_encode($params), 'gen_ai');
// 发送请求
// AI接口 发送请求
$client = new Http();
$response = $client->post($url, $params);
......@@ -163,7 +232,7 @@ class Ai
$result = json_decode($content, true);
// 记录出参日志
custom_log('用户ID:'. $userId .' AI生成视频接口返回:'.json_encode($result), 'gen_ai_video_api');
custom_log('用户ID:'. $userId .' AI生成视频接口返回:'.json_encode($result), 'gen_ai');
return [
'code' => 1 ,
......@@ -172,7 +241,7 @@ class Ai
];
} catch (\Exception $e) {
format_log_error_custom_name($e, '[AI生成视频接口异常]','用户ID:'. $userId . $e->getMessage(), 'gen_ai_video_api');
format_log_error_custom_name($e, '[AI生成视频接口异常]','用户ID:'. $userId . $e->getMessage(), 'gen_ai');
return [
'code' => 0 ,
'msg' => '图片生成失败'
......
......@@ -354,6 +354,7 @@ class Upload
/**
* AI base64文件上传
* 暂时用不到,废弃,原来用于保存3D试戴结果文件到本地 2026.05.19
*/
public function uploadBase64($base64_str = '')
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment