AnimeService.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. namespace App\Services\Anime;
  3. use App\Consts\ErrorConst;
  4. use App\Facade\Site;
  5. use App\Libs\Utils;
  6. use App\Services\AIGeneration\AIImageGenerationService;
  7. use GuzzleHttp\Client;
  8. use Illuminate\Support\Facades\DB;
  9. use Illuminate\Support\Facades\Log;
  10. use Illuminate\Support\Facades\Redis;
  11. use OSS\Core\OssException;
  12. use OSS\OssClient;
  13. class AnimeService
  14. {
  15. protected $aiImageGenerationService;
  16. public function __construct(AIImageGenerationService $aiImageGenerationService) {
  17. $this->aiImageGenerationService = $aiImageGenerationService;
  18. }
  19. public function uploadImg($data) {
  20. }
  21. public function batchSetRoleImg($data) {
  22. $anime_id = getProp($data, 'anime_id');
  23. if (!$anime_id) Utils::throwError('1002:请选择对话');
  24. $roles = getProp($data, 'roles');
  25. foreach ($roles as &$role) {
  26. $role_name = getProp($role, 'role');
  27. $description = getProp($role, 'description');
  28. // 参考图地址
  29. $ref_img_url = getProp($role, 'ref_img_url');
  30. // 此处调用AIImageGenerationService的生成图片任务接口: createImageGenerationTask(注意使用默认参数,prompt使用角色描述),并返回任务id
  31. try {
  32. $params = [
  33. 'prompt' => $description,
  34. 'ref_img_urls' => !empty($ref_img_url) ? $ref_img_url : []
  35. ];
  36. $task = $this->aiImageGenerationService->createImageGenerationTask($params);
  37. $task_id = $task->id;
  38. if (!$task_id) {
  39. Utils::throwError("20003: 角色({$role_name})生成图片失败");
  40. }
  41. $role['task_id'] = $task_id;
  42. $role['task_status'] = 'processing';
  43. } catch (\Exception $e) {
  44. Utils::throwError("20003:" . $e->getMessage());
  45. }
  46. }
  47. // 保存角色信息
  48. $boolen = DB::table('mp_animes')->where('id', $anime_id)->update([
  49. 'roles' => json_encode($roles, 256),
  50. 'generate_status' => '执行中',
  51. 'updated_at' => date('Y-m-d H:i:s')
  52. ]);
  53. if (!$boolen) {
  54. Utils::throwError('20003:保存角色信息失败');
  55. }
  56. return $boolen;
  57. }
  58. public function batchSetSceneImg($data) {
  59. $anime_id = getProp($data, 'anime_id');
  60. if (!$anime_id) Utils::throwError('1002:请选择对话');
  61. $scenes = getProp($data, 'scenes');
  62. foreach ($scenes as &$scene) {
  63. $scene_name = getProp($scene, 'scene');
  64. $description = getProp($scene, 'description');
  65. // 参考图地址
  66. $ref_img_url = getProp($scene, 'url');
  67. // 此处调用AIImageGenerationService的生成图片任务接口: createImageGenerationTask(注意使用默认参数,prompt使用角色描述),并返回任务id
  68. try {
  69. $params = [
  70. 'prompt' => $description,
  71. 'ref_img_urls' => !empty($ref_img_url) ? $ref_img_url : []
  72. ];
  73. $task = $this->aiImageGenerationService->createImageGenerationTask($params);
  74. $task_id = $task->id;
  75. if (!$task_id) {
  76. Utils::throwError("20003: 角色({$scene_name})生成图片失败");
  77. }
  78. $scene['task_id'] = $task_id;
  79. $scene['task_status'] = 'processing';
  80. } catch (\Exception $e) {
  81. Utils::throwError("20003:" . $e->getMessage());
  82. }
  83. }
  84. // 保存角色信息
  85. $boolen = DB::table('mp_animes')->where('id', $anime_id)->update([
  86. 'scenes' => json_encode($scenes, 256),
  87. 'generate_status' => '执行中',
  88. 'updated_at' => date('Y-m-d H:i:s')
  89. ]);
  90. if (!$boolen) {
  91. Utils::throwError('20003:保存角色信息失败');
  92. }
  93. return $boolen;
  94. }
  95. public function editAnime($data) {
  96. $script_arr =getProp($data, 'script', []);
  97. if (!$script_arr) Utils::throwError('20003:剧本内容不能为空');
  98. $start_episode_sequence = getProp($data, 'start_episode_sequence', 1);
  99. $anime_id = getProp($data, 'anime_id');
  100. try {
  101. DB::beginTransaction();
  102. $table_data = [
  103. 'intro' => isset($script_arr['intro']) ? $script_arr['intro'] : '',
  104. 'highlights' => isset($script_arr['highlights']) ? $script_arr['highlights'] : '',
  105. 'role_relationship' => isset($script_arr['role_relationship']) ? $script_arr['role_relationship'] : '',
  106. 'core_contradiction' => isset($script_arr['core_contradiction']) ? $script_arr['core_contradiction'] : '',
  107. 'roles' => isset($script_arr['roles']) ? json_encode($script_arr['roles'], 256) : '',
  108. 'art_style' => isset($script_arr['art_style']) ? $script_arr['art_style'] : '',
  109. 'scenes' => isset($script_arr['scenes']) ? json_encode($script_arr['scenes'], 256) : '',
  110. 'status' => 3,
  111. 'start_episode_sequence' => $start_episode_sequence,
  112. 'end_episode_sequence' => $start_episode_sequence + count($script_arr['episodes']) - 1,
  113. 'episode_num' => count($script_arr['episodes']),
  114. 'updated_at' => date('Y-m-d H:i:s')
  115. ];
  116. // 保存剧本内容
  117. if (!empty($anime_id)) {
  118. $boolen = DB::table('mp_animes')->where('id', $anime_id)->update($table_data);
  119. if (!$boolen) {
  120. dLog('deepseek')->info('对话保存失败', $table_data);
  121. Utils::throwError('20003:对话保存失败');
  122. }
  123. }else {
  124. $table['created_at'] = $table_data['updated_at'];
  125. $anime_id = DB::table('mp_animes')->insertGetId($table_data);
  126. if (!$anime_id) {
  127. dLog('deepseek')->info('对话保存失败', $table_data);
  128. Utils::throwError('20003:对话保存失败');
  129. }
  130. }
  131. // 保存分集内容
  132. // 删除历史分集内容
  133. $boolen1 = DB::table('mp_anime_episodes')->where('anime_id', $anime_id)->delete();
  134. $episodes = [];
  135. $sequence = 1;
  136. foreach ($script_arr['episodes'] as $episode) {
  137. $segment_number = 1;
  138. foreach($episode['segments'] as $segment) {
  139. $episodes[] = [
  140. 'anime_id' => $anime_id,
  141. 'episode_number' => $episode['episode_number'],
  142. 'title' => $episode['title'],
  143. // 'content' => $episode['content'],
  144. 'content' => '',
  145. 'segment_number' => $segment_number,
  146. 'segment_content' => $segment['segment_content'],
  147. 'sequence' => $sequence,
  148. 'created_at' => date('Y-m-d H:i:s'),
  149. 'updated_at' => date('Y-m-d H:i:s')
  150. ];
  151. $sequence++;
  152. $segment_number++;
  153. }
  154. }
  155. $boolen2 = DB::table('mp_anime_episodes')->insert($episodes);
  156. if (!$boolen2) {
  157. dLog('deepseek')->info('分集内容保存失败', $episodes);
  158. Utils::throwError('20003:分集内容保存失败');
  159. }
  160. } catch (\Exception $e) {
  161. DB::rollBack();
  162. Utils::throwError('20003:'.$e->getMessage());
  163. }
  164. DB::commit();
  165. return true;
  166. }
  167. public function animeDetail($data) {
  168. $anime_id = getProp($data, 'anime_id');
  169. $anime = DB::table('mp_animes')->where('id', $anime_id)->where('is_deleted', 0)
  170. ->selectRaw('id as anime_id, anime_name, intro, highlights, roles, role_relationship, core_contradiction, art_style, scenes, status, start_episode_sequence, end_episode_sequence, episode_num, remark, generate_status, created_at')->first();
  171. if (!$anime) Utils::throwError('20003:该剧本不存在!');
  172. $anime = (array)$anime;
  173. $anime['roles'] = json_decode($anime['roles']);
  174. $anime['scenes'] = json_decode($anime['scenes']);
  175. // 获取分集信息
  176. $episodes = DB::table('mp_anime_episodes')->where('anime_id', $anime_id)->orderBy('episode_number')
  177. ->select('id', 'episode_number', 'title', 'content', 'segment_number', 'segment_content')
  178. ->orderBy('episode_number')->orderBy('segment_number')->get()->map(function ($value) {
  179. return (array)$value;
  180. })->toArray();
  181. $return_episodes = [];
  182. foreach($episodes as $episode) {
  183. $episode_number = getProp($episode, 'episode_number');
  184. if (isset($return_episodes[$episode_number])) {
  185. $return_episodes[$episode_number]['segments'][] = [
  186. 'segment_number' => getProp($episode, 'segment_number'),
  187. 'segment_content' => getProp($episode, 'segment_content')
  188. ];
  189. }else {
  190. $return_episodes[$episode_number] = [
  191. 'episode_number' => $episode_number,
  192. 'title' => getProp($episode, 'title'),
  193. 'segments' => [
  194. [
  195. 'segment_number' => getProp($episode, 'segment_number'),
  196. 'segment_content' => getProp($episode, 'segment_content')
  197. ]
  198. ]
  199. ];
  200. }
  201. }
  202. $anime['episodes'] = array_values($return_episodes);
  203. return $anime;
  204. }
  205. }