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

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

parent fee528f8
...@@ -112,33 +112,36 @@ class AiTryon extends Common ...@@ -112,33 +112,36 @@ class AiTryon extends Common
]); ]);
$this->svalidate($params, ".aiadd"); $this->svalidate($params, ".aiadd");
$user = auth_user();
// 校验商品分类是否在允许试戴分类中 // 校验商品分类是否在允许试戴分类中
$goodsService = new GoodsService(); $goodsService = new GoodsService();
$is_allowed = $goodsService->isCategoryAllowed('', $params['goods_id']); $is_allowed = $goodsService->isCategoryAllowed('', $params['goods_id']);
if ($is_allowed === 0) { if ($is_allowed === 0) {
custom_log('[AI生成图片接口] 商品所属分类不允许试戴 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('商品所属分类不允许试戴'); $this->error('商品所属分类不允许试戴');
} }
//开发过程中临时代码,AI图片生成次数有限 //开发过程中临时代码,AI图片生成次数有限
// $this->success('图片生成成功', 'https://zhubaoshop.sydggxs.com/uploads/20260508/c92396f646bd41887329891647fcfcaf.png'); // $this->success('图片生成成功', 'https://zhubaoshop.sydggxs.com/uploads/20260508/c92396f646bd41887329891647fcfcaf.png');
$user = auth_user();
// 校验试戴次数 && 扣除积分 // 校验试戴次数 && 扣除积分
$userService = new User(); $userService = new User();
$res = $userService->isTry($user->id); $res = $userService->isTry($user->id);
if ($res === 0) { if ($res === 0) {
custom_log('[AI生成图片接口] 免费次数已用完 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
// 免费试戴次数用完后,扣积分,试戴一次扣10积分 // 免费试戴次数用完后,扣积分,试戴一次扣10积分
$userService = new User(); $userService = new User();
$res = $userService->deductPoints($user->id, 10); $res = $userService->deductPoints($user->id, 10);
if ($res === 0) { if ($res === 0) {
custom_log('[AI生成图片接口] 积分不足 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('免费次数已用完,积分不足,无法试戴'); $this->error('免费次数已用完,积分不足,无法试戴');
} }
} }
// 合成AI图 // 合成AI图
$ai = new Ai(); $ai = new Ai();
$res = $ai->generateImage($params, $user->id, 'b64_json'); $res = $ai->generateImage($params, $user->id, 'url');
// 我的试戴 // 我的试戴
$tryonModel = new AiTryOnModel(); $tryonModel = new AiTryOnModel();
...@@ -154,20 +157,22 @@ class AiTryon extends Common ...@@ -154,20 +157,22 @@ class AiTryon extends Common
]; ];
if ($res['code'] === 0) { if ($res['code'] === 0) {
$tryonData['ai_status'] = 2; $tryonData['ai_status'] = 2;
$tryonData['ai_err_msg'] = $res['msg']; $tryonData['ai_err_msg'] = $res['msg'];
$tryonModel->save($tryonData); $tryonModel->save($tryonData);
$this->error($res['msg']); $this->error($res['msg']);
} else { } else {
// 保存图片到本地 // 保存图片到本地
$upload = new Upload(); $aiService = new Ai();
$attachment = $upload->uploadBase64($res['data']); $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_status'] = 2;
$tryonData['ai_err_msg'] = '图片上传失败'; $tryonData['ai_err_msg'] = '图片上传失败';
$tryonModel->save($tryonData); $tryonModel->save($tryonData);
...@@ -178,9 +183,9 @@ class AiTryon extends Common ...@@ -178,9 +183,9 @@ class AiTryon extends Common
$tryonData['ai_url'] = config('shopro.api_host') . $attachment['data']; $tryonData['ai_url'] = config('shopro.api_host') . $attachment['data'];
$tryonModel->save($tryonData); $tryonModel->save($tryonData);
//试戴次数+1 // 试戴次数+1
$userService = new User(); $userService = new User();
$res = $userService->addTryTimes($user->id); $userService->addTryTimes($user->id);
$this->success('图片生成成功', config('shopro.api_host') . $attachment['data']??''); $this->success('图片生成成功', config('shopro.api_host') . $attachment['data']??'');
} }
...@@ -223,29 +228,32 @@ class AiTryon extends Common ...@@ -223,29 +228,32 @@ class AiTryon extends Common
]); ]);
$this->svalidate($params, ".aiadd"); $this->svalidate($params, ".aiadd");
$user = auth_user();
// 校验商品分类是否在允许试戴分类中 // 校验商品分类是否在允许试戴分类中
$goodsService = new GoodsService(); $goodsService = new GoodsService();
$is_allowed = $goodsService->isCategoryAllowed('', $params['goods_id']); $is_allowed = $goodsService->isCategoryAllowed('', $params['goods_id']);
if ($is_allowed === 0) { if ($is_allowed === 0) {
custom_log('[AI生成视频接口] 商品所属分类不允许试戴 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('商品所属分类不允许试戴'); $this->error('商品所属分类不允许试戴');
} }
$user = auth_user();
//开发过程中临时调试代码 //开发过程中临时调试代码
\think\Queue::push('\addons\shopro\job\AiVideoGen@save', ['taskid' => 'cgt-20260518151431-zcrgp', 'user' => $user], 'shopro-high'); // \think\Queue::push('\addons\shopro\job\AiVideoGen@save', ['taskid' => 'cgt-20260518151431-zcrgp', 'user' => $user], 'shopro-high');
$this->success('推送队列成功'); // $this->success('推送队列成功');
exit; // exit;
// $this->success('视频生成中', 13); // $this->success('视频生成中', 13);
// 校验试戴次数 && 扣除积分 // 校验试戴次数 && 扣除积分
$userService = new User(); $userService = new User();
$res = $userService->isTry($user->id); $res = $userService->isTry($user->id);
if ($res === 0) { if ($res === 0) {
custom_log('[AI生成视频接口] 免费次数已用完 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
// 免费试戴次数用完后,扣积分,试戴一次扣10积分 // 免费试戴次数用完后,扣积分,试戴一次扣10积分
$userService = new User(); $userService = new User();
$res = $userService->deductPoints($user->id, 10); $res = $userService->deductPoints($user->id, 10);
if ($res === 0) { if ($res === 0) {
custom_log('[AI生成视频接口] 积分不足 user_id:'.$user->id.' goods_id:'.$params['goods_id'], 'gen_ai');
$this->error('免费次数已用完,积分不足,无法试戴'); $this->error('免费次数已用完,积分不足,无法试戴');
} }
} }
......
...@@ -625,7 +625,7 @@ if (!function_exists('format_log_error')) { ...@@ -625,7 +625,7 @@ if (!function_exists('format_log_error')) {
$logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL; $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
\think\Log::error($logInfo); \think\Log::error($logInfo);
custom_log($logInfo, 'gen_ai_video'); custom_log($logInfo, 'gen_ai');
} }
} }
......
...@@ -4,6 +4,7 @@ namespace addons\shopro\job; ...@@ -4,6 +4,7 @@ namespace addons\shopro\job;
use addons\shopro\library\activity\getter\Db; use addons\shopro\library\activity\getter\Db;
use addons\shopro\library\HttpClient as Http; use addons\shopro\library\HttpClient as Http;
use addons\shopro\service\user\Ai;
use app\admin\model\shopro\AiTryon as AiTryOnModel; use app\admin\model\shopro\AiTryon as AiTryOnModel;
use think\exception\HttpResponseException; use think\exception\HttpResponseException;
use think\Log; use think\Log;
...@@ -33,12 +34,13 @@ class AiVideoGen extends BaseJob ...@@ -33,12 +34,13 @@ class AiVideoGen extends BaseJob
debug_echo($text); debug_echo($text);
} }
if ($this->is_log){ if ($this->is_log){
custom_log($text, 'gen_ai_video'); custom_log($text, 'gen_ai');
} }
} }
/** /**
* 保存远端视频文件到本地 * 保存远端视频文件到本地
* 暂时无用了
*/ */
private function saveVideoLoc ($videoUrl){ private function saveVideoLoc ($videoUrl){
...@@ -132,15 +134,15 @@ class AiVideoGen extends BaseJob ...@@ -132,15 +134,15 @@ class AiVideoGen extends BaseJob
$user_id = isset($user['id']) ? $user['id'] : 0; $user_id = isset($user['id']) ? $user['id'] : 0;
$this->debug_log('***************************** '.date('Y-m-d H:i:s'). '保存AI视频脚本开始 userid '.$user_id.' taskid:'.$taskid.' ***********************************'.PHP_EOL); $this->debug_log('***************************** '.date('Y-m-d H:i:s'). '保存AI视频脚本开始 userid '.$user_id.' taskid:'.$taskid.' ***********************************'.PHP_EOL);
$this->sendNotification($user_id, $taskid); // 开发过程中的临时代码 调试用
// 删除队列job // $this->sendNotification($user_id, $taskid);
$this->debug_log('[AI视频]删除Job'); // $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); // $job->delete();
exit; // exit;
if (!isset($taskid) || empty($taskid) || !isset($user_id) || empty($user_id)) { if (!isset($taskid) || empty($taskid) || !isset($user_id) || empty($user_id)) {
$this->debug_log('[AI视频]入参有空值 taskid:'.$taskid .' user_id:'.$user_id); $this->debug_log('[AI视频异步队列]入参有空值 taskid:'.$taskid .' user_id:'.$user_id);
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频]删除Job');
...@@ -149,6 +151,7 @@ class AiVideoGen extends BaseJob ...@@ -149,6 +151,7 @@ class AiVideoGen extends BaseJob
return false; return false;
} }
// 请求AI接口
$url = $this->ark_host . '/api/v3/contents/generations/tasks/' . $taskid; $url = $this->ark_host . '/api/v3/contents/generations/tasks/' . $taskid;
$params = [ $params = [
'headers' => [ 'headers' => [
...@@ -159,7 +162,7 @@ class AiVideoGen extends BaseJob ...@@ -159,7 +162,7 @@ class AiVideoGen extends BaseJob
'allow_redirects' => true 'allow_redirects' => true
]; ];
$this->debug_log('[AI视频]请求AI接口入参 user_id:'.$user_id.' AI接口url:'.$url.' params:'.json_encode($params)); $this->debug_log('[AI视频异步队列]请求AI接口入参 user_id:'.$user_id.' AI接口url:'.$url.' params:'.json_encode($params));
// 向AI接口 发送请求 // 向AI接口 发送请求
$client = new Http(); $client = new Http();
...@@ -169,7 +172,7 @@ class AiVideoGen extends BaseJob ...@@ -169,7 +172,7 @@ class AiVideoGen extends BaseJob
$content = preg_replace('/[^\x20-\x7E]/', '', $content); $content = preg_replace('/[^\x20-\x7E]/', '', $content);
$result = json_decode($content, true); $result = json_decode($content, true);
$this->debug_log('[AI视频]请求AI接口出参 response:'.json_encode($result)); $this->debug_log('[AI视频异步队列]请求AI接口出参 response:'.json_encode($result));
// AI接口 返回失败 // AI接口 返回失败
if (isset($result['error'])){ if (isset($result['error'])){
...@@ -177,7 +180,7 @@ class AiVideoGen extends BaseJob ...@@ -177,7 +180,7 @@ class AiVideoGen extends BaseJob
AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => $message]); AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => $message]);
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); $job->delete();
return false; return false;
} }
...@@ -188,58 +191,61 @@ class AiVideoGen extends BaseJob ...@@ -188,58 +191,61 @@ class AiVideoGen extends BaseJob
// 成功返回视频链接 // 成功返回视频链接
case 'succeeded': case 'succeeded':
// 保存远程视频到本地 // 保存远程视频到本地
$video_url = $this->saveVideoLoc(isset($result['content']['video_url']) ? $result['content']['video_url'] : ''); $aiService = new Ai();
$this->debug_log('[AI视频]保存本地接口返回值 video_url:'.$video_url); $video_url = $aiService->saveFileLoc(isset($result['content']['video_url']) ? $result['content']['video_url'] : '', 'gen_ai');
// $video_url = $this->saveVideoLoc(isset($result['content']['video_url']) ? $result['content']['video_url'] : '');
$this->debug_log('[AI视频异步队列]保存本地接口返回值 video_url:'.$video_url);
if ($video_url === 0){ if ($video_url === 0){
AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '视频保存到本地失败']); AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '视频保存到本地失败']);
$this->debug_log('[AI视频]保存本地视频失败 sql: '.db()->getLastSql()); $this->debug_log('[AI视频异步队列]保存本地视频失败 sql: '.db()->getLastSql());
} }
// 更新我的试戴 // 更新我的试戴
AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 1,'ai_url' => config('shopro.api_host').$video_url, 'ai_err_msg' => '视频生成成功']); AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 1,'ai_url' => config('shopro.api_host').$video_url, 'ai_err_msg' => '视频生成成功']);
$this->debug_log('[AI视频]保存本地视频成功 sql: '.db()->getLastSql()); $this->debug_log('[AI视频异步队列]保存本地视频成功 sql: '.db()->getLastSql());
// ========== 新增:发送消息通知 ========== // 发送消息通知
$this->sendNotification($user_id, $taskid); $this->sendNotification($user_id, $taskid);
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); $job->delete();
break; break;
case 'cancelled': case 'cancelled':
AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '任务已取消']); AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '任务已取消']);
$this->debug_log('[AI视频]AI生成视频任务 取消: taskId: ' . $taskid . 'userId '. $user_id ); $this->debug_log('[AI视频异步队列]AI生成视频任务 取消: taskId: ' . $taskid . 'userId '. $user_id );
$this->debug_log('[AI视频]AI生成视频任务 取消: result:'.json_encode($result)); $this->debug_log('[AI视频异步队列]AI生成视频任务 取消: result:'.json_encode($result));
$this->debug_log('[AI视频]AI生成视频任务 取消: sql:' .db()->getLastSql()); $this->debug_log('[AI视频异步队列]AI生成视频任务 取消: sql:' .db()->getLastSql());
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); $job->delete();
break; break;
case 'failed': case 'failed':
AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '视频生成失败']); AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '视频生成失败']);
$this->debug_log('[AI视频]AI生成视频任务 失败: taskId: ' . $taskid . 'userId '. $user_id ); $this->debug_log('[AI视频异步队列]AI生成视频任务 失败: taskId: ' . $taskid . 'userId '. $user_id );
$this->debug_log('[AI视频]AI生成视频任务 失败: result:'.json_encode($result)); $this->debug_log('[AI视频异步队列]AI生成视频任务 失败: result:'.json_encode($result));
$this->debug_log('[AI视频]AI生成视频任务 失败: sql:' .db()->getLastSql()); $this->debug_log('[AI视频异步队列]AI生成视频任务 失败: sql:' .db()->getLastSql());
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); $job->delete();
break; break;
case 'expired': case 'expired':
AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '任务已过期']); AiTryOnModel::where('user_id', $user_id)->where('ai_task_id', $taskid)->update(['ai_status' => 2, 'ai_err_msg' => '任务已过期']);
$this->debug_log('[AI视频]AI生成视频任务 过期: taskId: ' . $taskid . 'userId '. $user_id ); $this->debug_log('[AI视频异步队列]AI生成视频任务 过期: taskId: ' . $taskid . 'userId '. $user_id );
$this->debug_log('[AI视频]AI生成视频任务 过期: result:'.json_encode($result)); $this->debug_log('[AI视频异步队列]AI生成视频任务 过期: result:'.json_encode($result));
$this->debug_log('[AI视频]AI生成视频任务 过期: sql:' .db()->getLastSql()); $this->debug_log('[AI视频异步队列]AI生成视频任务 过期: sql:' .db()->getLastSql());
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); $job->delete();
break; break;
...@@ -255,11 +261,11 @@ class AiVideoGen extends BaseJob ...@@ -255,11 +261,11 @@ class AiVideoGen extends BaseJob
} catch (\Exception $e) { } catch (\Exception $e) {
// 队列执行失败 // 队列执行失败
$logInfo = [ $logInfo = [
" [AI视频] Exception LOG INFO BEGIN ", " [AI视频异步队列] Exception LOG INFO BEGIN ",
'[ Message ] ' . var_export('[' . $e->getCode() . ']' . $e->getMessage() . ' ' . 'AiVideoGen.save.' . $user['id'] ?? 'user_id' . $video_url??'video_url', true), '[ Message ] ' . var_export('[' . $e->getCode() . ']' . $e->getMessage() . ' ' . 'AiVideoGen.save.' . $user['id'] ?? 'user_id' . $video_url??'video_url', true),
'[ File ] ' . var_export($e->getFile() . ':' . $e->getLine(), true), '[ File ] ' . var_export($e->getFile() . ':' . $e->getLine(), true),
'[ Trace ] ' . var_export($e->getTraceAsString(), true), '[ Trace ] ' . var_export($e->getTraceAsString(), true),
"[AI视频] Exception LOG INFO ENDED ", "[AI视频异步队列] Exception LOG INFO ENDED ",
]; ];
$logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL; $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
$this->debug_log($logInfo); $this->debug_log($logInfo);
...@@ -267,7 +273,7 @@ class AiVideoGen extends BaseJob ...@@ -267,7 +273,7 @@ class AiVideoGen extends BaseJob
// $this->deleteLocalVideo($video_url); // 删除保存到本地的视频,如果已经保存了的话,暂时不处理保存到视频,获取不到video_url // $this->deleteLocalVideo($video_url); // 删除保存到本地的视频,如果已经保存了的话,暂时不处理保存到视频,获取不到video_url
// 删除队列job // 删除队列job
$this->debug_log('[AI视频]删除Job'); $this->debug_log('[AI视频异步队列]删除Job');
$job->delete(); $job->delete();
} }
} }
...@@ -281,7 +287,7 @@ class AiVideoGen extends BaseJob ...@@ -281,7 +287,7 @@ class AiVideoGen extends BaseJob
// 获取用户信息 // 获取用户信息
$user = User::find($user_id); $user = User::find($user_id);
if (!$user) { if (!$user) {
$this->debug_log('[AI视频通知]用户不存在: ' . $user_id); $this->debug_log('[AI视频异步队列][通知]用户不存在: ' . $user_id);
return false; return false;
} }
...@@ -298,14 +304,10 @@ class AiVideoGen extends BaseJob ...@@ -298,14 +304,10 @@ class AiVideoGen extends BaseJob
]) ])
); );
$this->debug_log('[AI视频]通知发送成功: user_id=' . $user_id . ' taskid=' . $taskid); $this->debug_log('[AI视频异步队列][通知]通知发送成功: user_id=' . $user_id . ' taskid=' . $taskid);
return true; return true;
}catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error_custom_name($e, '[AI视频]通知发送失败: user_id=' . $user_id . ' taskid=' . $taskid, $message, 'gen_ai_video');
} catch (\Exception $e) { } catch (\Exception $e) {
format_log_error_custom_name($e, '[AI视频]通知发送失败: user_id=' . $user_id . ' taskid=' . $taskid, 'gen_ai_video'); format_log_error_custom_name($e, '[AI视频异步队列][通知]通知发送失败: user_id=' . $user_id . ' taskid=' . $taskid, '', 'gen_ai');
} }
} }
......
...@@ -18,6 +18,70 @@ class Ai ...@@ -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 生成图片 * AI 生成图片
* @param string $param 入参 * @param string $param 入参
* @param string $userId 入参 * @param string $userId 入参
...@@ -28,7 +92,8 @@ class Ai ...@@ -28,7 +92,8 @@ class Ai
{ {
try { try {
$url = $this->ark_host . '/api/v3/images/generations'; $url = $this->ark_host . '/api/v3/images/generations';
$prompt = '严格复刻图片1 人物所有样貌特征、肢体姿势、场景背景、光影氛围一丝不变,精准匹配图片2 耳饰饰品佩戴到人物对应耳部位置,饰品贴合肌肤轮廓、尺寸比例适配、定点标准不跑偏、不悬空不变形不拉伸不重复生成;人物做原生自然轻度磨皮,柔和流畅瘦脸修容,保留真实皮肤纹理与面部细节,拒绝过度美颜、拒绝网红假脸、拒绝锥脸畸形,五官原生比例不改动,无建模感、无生硬 AI 违和感,整体色调光影统一,高清超清细节拉满,纯真人电商珠宝实拍大片质感,原图风格画质全程不变。'; // $prompt = '严格复刻图片1 人物所有样貌特征、肢体姿势、场景背景、光影氛围一丝不变,精准匹配图片2 耳饰饰品佩戴到人物对应耳部位置,饰品贴合肌肤轮廓、尺寸比例适配、定点标准不跑偏、不悬空不变形不拉伸不重复生成;人物做原生自然轻度磨皮,柔和流畅瘦脸修容,保留真实皮肤纹理与面部细节,拒绝过度美颜、拒绝网红假脸、拒绝锥脸畸形,五官原生比例不改动,无建模感、无生硬 AI 违和感,整体色调光影统一,高清超清细节拉满,纯真人电商珠宝实拍大片质感,原图风格画质全程不变。';
$prompt = '严格复刻图 1 人物样貌、姿势、背景与光影,将图 2 耳饰精准贴合佩戴于耳部,比例适配贴合不形变。人物自然轻磨皮柔和修脸,保留原生五官与皮肤细节,不假脸无 AI 违和感,色调光影统一,高清实拍珠宝电商质感。';
$params = [ $params = [
'headers' => [ 'headers' => [
'Authorization' => 'Bearer ' . $this->api_key, 'Authorization' => 'Bearer ' . $this->api_key,
...@@ -40,16 +105,15 @@ class Ai ...@@ -40,16 +105,15 @@ class Ai
"image" => [$param['person_image'], $param['jewelry_image']], "image" => [$param['person_image'], $param['jewelry_image']],
"sequential_image_generation" => "disabled", "sequential_image_generation" => "disabled",
"response_format" => $response_format, "response_format" => $response_format,
"size" => "2K", "size" => "1024×1024",
"stream" => false, "num" => 1,
"watermark" => true
], ],
'timeout' => 300, 'timeout' => 300,
'verify' => false, // 关闭 SSL 证书验证 'verify' => false, // 关闭 SSL 证书验证
'allow_redirects' => true '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(); $client = new Http();
...@@ -61,7 +125,7 @@ class Ai ...@@ -61,7 +125,7 @@ class Ai
$result = json_decode($content, true); $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 ($response_format == 'b64_json'){
if (!$result || !isset($result['data'][0]['b64_json'])) { if (!$result || !isset($result['data'][0]['b64_json'])) {
...@@ -124,7 +188,9 @@ class Ai ...@@ -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'; // $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'; $url = $this->ark_host . '/api/v3/contents/generations/tasks';
$prompt = '人物自然微动,轻微转头,微笑,眨眼,动作柔和流畅,画面稳定不闪烁、不抖动、不扭曲,真实人像质感,高清清晰,饰品完美展示,整体自然优雅,无变形、无穿模、无悬浮'; // $prompt = '人物自然微动,轻微转头,微笑,眨眼,动作柔和流畅,画面稳定不闪烁、不抖动、不扭曲,真实人像质感,高清清晰,饰品完美展示,整体自然优雅,无变形、无穿模、无悬浮';
// $prompt = '人物轻动转头,自然微笑眨眼,动作流畅柔和,画面稳定无抖动扭曲,真人高清质感,饰品完整清晰展示,整体优雅自然,无变形穿模悬浮';
$prompt = '人物微动转头微笑眨眼,动作顺滑画面稳定,高清真人质感,饰品清晰展示,无变形悬浮穿模';
$params = [ $params = [
'headers' => [ 'headers' => [
'Authorization' => 'Bearer ' . $this->api_key, 'Authorization' => 'Bearer ' . $this->api_key,
...@@ -143,7 +209,10 @@ class Ai ...@@ -143,7 +209,10 @@ class Ai
] ]
], ],
"generate_audio" => false, // 不要声音 "generate_audio" => false, // 不要声音
"safety_identifier" => md5($userId) "resolution" => "720p", // 分辨率:降档提速(原1080p改为720p)枚举值: 480p 720p 1080p
"duration" => 5,
"draft" => true,
// "safety_identifier" => md5($userId)
], ],
'timeout' => 300, 'timeout' => 300,
'verify' => false, // 关闭 SSL 证书验证 'verify' => false, // 关闭 SSL 证书验证
...@@ -151,9 +220,9 @@ class Ai ...@@ -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(); $client = new Http();
$response = $client->post($url, $params); $response = $client->post($url, $params);
...@@ -163,7 +232,7 @@ class Ai ...@@ -163,7 +232,7 @@ class Ai
$result = json_decode($content, true); $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 [ return [
'code' => 1 , 'code' => 1 ,
...@@ -172,7 +241,7 @@ class Ai ...@@ -172,7 +241,7 @@ class Ai
]; ];
} catch (\Exception $e) { } 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 [ return [
'code' => 0 , 'code' => 0 ,
'msg' => '图片生成失败' 'msg' => '图片生成失败'
......
...@@ -354,6 +354,7 @@ class Upload ...@@ -354,6 +354,7 @@ class Upload
/** /**
* AI base64文件上传 * AI base64文件上传
* 暂时用不到,废弃,原来用于保存3D试戴结果文件到本地 2026.05.19
*/ */
public function uploadBase64($base64_str = '') 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