|
|
@@ -44,11 +44,84 @@ class AnimeService
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 构建统一的分镜数据结构(episodeInfo格式)
|
|
|
+ * @param array $segments 分镜数据数组
|
|
|
+ * @return array 返回包含acts和total_duration的数组
|
|
|
+ */
|
|
|
+ public function buildEpisodeSegmentsStructure($segments) {
|
|
|
+ $acts = [];
|
|
|
+ $totalDuration = 0; // 初始化总时长
|
|
|
+
|
|
|
+ foreach($segments as $segment) {
|
|
|
+ // 计算分镜时长,优先级:video_duration > audio_duration > 默认5秒
|
|
|
+ $videoDuration = getProp($segment, 'video_duration');
|
|
|
+ $audioDuration = getProp($segment, 'audio_duration');
|
|
|
+
|
|
|
+ if (!empty($videoDuration) && is_numeric($videoDuration)) {
|
|
|
+ $totalDuration += floatval($videoDuration);
|
|
|
+ } elseif (!empty($audioDuration) && is_numeric($audioDuration)) {
|
|
|
+ $totalDuration += floatval($audioDuration);
|
|
|
+ } else {
|
|
|
+ $totalDuration += 5; // 默认5秒
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建分镜信息
|
|
|
+ $segmentInfo = [
|
|
|
+ 'segment_id' => getProp($segment, 'segment_id'),
|
|
|
+ 'segment_number' => getProp($segment, 'segment_number'),
|
|
|
+ 'segment_content' => getProp($segment, 'segment_content'),
|
|
|
+ 'description' => getProp($segment, 'description'),
|
|
|
+ 'composition' => getProp($segment, 'composition'),
|
|
|
+ 'camera_movement' => getProp($segment, 'camera_movement'),
|
|
|
+ 'voice_actor' => getProp($segment, 'voice_actor'),
|
|
|
+ 'dialogue' => getProp($segment, 'dialogue'),
|
|
|
+ 'frame_type' => getProp($segment, 'frame_type'),
|
|
|
+ 'scene' => getProp($segment, 'scene'),
|
|
|
+ 'characters' => getProp($segment, 'characters'),
|
|
|
+ 'tail_frame' => getProp($segment, 'tail_frame'),
|
|
|
+ 'emotion' => getProp($segment, 'emotion'),
|
|
|
+ 'emotion_type' => getProp($segment, 'emotion_type'),
|
|
|
+ 'gender' => getProp($segment, 'gender'),
|
|
|
+ 'speed_ratio' => getProp($segment, 'speed_ratio'),
|
|
|
+ 'loudness_ratio' => getProp($segment, 'loudness_ratio'),
|
|
|
+ 'emotion_scale' => getProp($segment, 'emotion_scale'),
|
|
|
+ 'pitch' => getProp($segment, 'pitch'),
|
|
|
+ 'voice_name' => getProp($segment, 'voice_name'),
|
|
|
+ 'voice_type' => getProp($segment, 'voice_type'),
|
|
|
+ 'voice_audio_url' => getProp($segment, 'voice_audio_url'),
|
|
|
+ 'img_url' => getProp($segment, 'img_url'),
|
|
|
+ 'audio_url' => getProp($segment, 'audio_url'),
|
|
|
+ 'audio_duration' => getProp($segment, 'audio_duration', 0),
|
|
|
+ 'video_url' => getProp($segment, 'video_url'),
|
|
|
+ 'video_duration' => getProp($segment, 'video_duration', 0),
|
|
|
+ 'last_frame_url' => getProp($segment, 'last_frame_url'),
|
|
|
+ 'current_type' => getProp($segment, 'current_type'),
|
|
|
+ ];
|
|
|
+
|
|
|
+ $actNumber = getProp($segment, 'act_number');
|
|
|
+ if (isset($acts[$actNumber])) {
|
|
|
+ $acts[$actNumber]['segments'][] = $segmentInfo;
|
|
|
+ } else {
|
|
|
+ $acts[$actNumber] = [
|
|
|
+ 'act_number' => $actNumber,
|
|
|
+ 'act_title' => getProp($segment, 'act_title'),
|
|
|
+ 'segments' => [$segmentInfo]
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'acts' => array_values($acts),
|
|
|
+ 'total_duration' => intval(round($totalDuration))
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 验证画面比例是否有效
|
|
|
* @param string $ratio 画面比例
|
|
|
* @return bool
|
|
|
*/
|
|
|
- private function validateRatio($ratio) {
|
|
|
+ public function validateRatio($ratio) {
|
|
|
return isset(BaseConst::IMAGE_RATIOS[$ratio]);
|
|
|
}
|
|
|
|
|
|
@@ -379,96 +452,10 @@ class AnimeService
|
|
|
return (array)$value;
|
|
|
})->toArray();
|
|
|
|
|
|
- $acts = [];
|
|
|
- $totalDuration = 0; // 初始化总时长
|
|
|
-
|
|
|
- foreach($segments as $segment) {
|
|
|
- // 计算分镜时长,优先级:video_duration > audio_duration > 默认5秒
|
|
|
- $videoDuration = getProp($segment, 'video_duration');
|
|
|
- $audioDuration = getProp($segment, 'audio_duration');
|
|
|
-
|
|
|
- if (!empty($videoDuration) && is_numeric($videoDuration)) {
|
|
|
- $totalDuration += floatval($videoDuration);
|
|
|
- } elseif (!empty($audioDuration) && is_numeric($audioDuration)) {
|
|
|
- $totalDuration += floatval($audioDuration);
|
|
|
- } else {
|
|
|
- $totalDuration += 5; // 默认5秒
|
|
|
- }
|
|
|
-
|
|
|
- if (isset($acts[getProp($segment, 'act_number')])) {
|
|
|
- $acts[getProp($segment, 'act_number')]['segments'][] = [
|
|
|
- 'segment_id' => getProp($segment, 'segment_id'),
|
|
|
- 'segment_number' => getProp($segment, 'segment_number'),
|
|
|
- 'segment_content' => getProp($segment, 'segment_content'),
|
|
|
- 'description' => getProp($segment, 'description'),
|
|
|
- 'composition' => getProp($segment, 'composition'),
|
|
|
- 'camera_movement' => getProp($segment, 'camera_movement'),
|
|
|
- 'voice_actor' => getProp($segment, 'voice_actor'),
|
|
|
- 'dialogue' => getProp($segment, 'dialogue'),
|
|
|
- 'frame_type' => getProp($segment, 'frame_type'),
|
|
|
- 'scene' => getProp($segment, 'scene'),
|
|
|
- 'characters' => getProp($segment, 'characters'),
|
|
|
- 'tail_frame' => getProp($segment, 'tail_frame'),
|
|
|
- 'emotion' => getProp($segment, 'emotion'),
|
|
|
- 'emotion_type' => getProp($segment, 'emotion_type'),
|
|
|
- 'gender' => getProp($segment, 'gender'),
|
|
|
- 'speed_ratio' => getProp($segment, 'speed_ratio'),
|
|
|
- 'loudness_ratio' => getProp($segment, 'loudness_ratio'),
|
|
|
- 'emotion_scale' => getProp($segment, 'emotion_scale'),
|
|
|
- 'pitch' => getProp($segment, 'pitch'),
|
|
|
- 'voice_name' => getProp($segment, 'voice_name'),
|
|
|
- 'voice_type' => getProp($segment, 'voice_type'),
|
|
|
- 'voice_audio_url' => getProp($segment, 'voice_audio_url'),
|
|
|
- 'img_url' => getProp($segment, 'img_url'),
|
|
|
- 'audio_url' => getProp($segment, 'audio_url'),
|
|
|
- 'audio_duration' => getProp($segment, 'audio_duration', 0),
|
|
|
- 'video_url' => getProp($segment, 'video_url'),
|
|
|
- 'video_duration' => getProp($segment, 'video_duration', 0),
|
|
|
- 'last_frame_url' => getProp($segment, 'last_frame_url'),
|
|
|
- 'current_type' => getProp($segment, 'current_type'),
|
|
|
- ];
|
|
|
- }else {
|
|
|
- $acts[getProp($segment, 'act_number')]= [
|
|
|
- 'act_number' => getProp($segment, 'act_number'),
|
|
|
- 'act_title' => getProp($segment, 'act_title'),
|
|
|
- 'segments' => [
|
|
|
- [
|
|
|
- 'segment_id' => getProp($segment, 'segment_id'),
|
|
|
- 'segment_number' => getProp($segment, 'segment_number'),
|
|
|
- 'segment_content' => getProp($segment, 'segment_content'),
|
|
|
- 'description' => getProp($segment, 'description'),
|
|
|
- 'composition' => getProp($segment, 'composition'),
|
|
|
- 'camera_movement' => getProp($segment, 'camera_movement'),
|
|
|
- 'voice_actor' => getProp($segment, 'voice_actor'),
|
|
|
- 'dialogue' => getProp($segment, 'dialogue'),
|
|
|
- 'frame_type' => getProp($segment, 'frame_type'),
|
|
|
- 'scene' => getProp($segment, 'scene'),
|
|
|
- 'characters' => getProp($segment, 'characters'),
|
|
|
- 'tail_frame' => getProp($segment, 'tail_frame'),
|
|
|
- 'emotion' => getProp($segment, 'emotion'),
|
|
|
- 'emotion_type' => getProp($segment, 'emotion_type'),
|
|
|
- 'gender' => getProp($segment, 'gender'),
|
|
|
- 'speed_ratio' => getProp($segment, 'speed_ratio'),
|
|
|
- 'loudness_ratio' => getProp($segment, 'loudness_ratio'),
|
|
|
- 'emotion_scale' => getProp($segment, 'emotion_scale'),
|
|
|
- 'pitch' => getProp($segment, 'pitch'),
|
|
|
- 'voice_name' => getProp($segment, 'voice_name'),
|
|
|
- 'voice_type' => getProp($segment, 'voice_type'),
|
|
|
- 'voice_audio_url' => getProp($segment, 'voice_audio_url'),
|
|
|
- 'img_url' => getProp($segment, 'img_url'),
|
|
|
- 'audio_url' => getProp($segment, 'audio_url'),
|
|
|
- 'audio_duration' => getProp($segment, 'audio_duration', 0),
|
|
|
- 'video_url' => getProp($segment, 'video_url'),
|
|
|
- 'video_duration' => getProp($segment, 'video_duration', 0),
|
|
|
- 'last_frame_url' => getProp($segment, 'last_frame_url'),
|
|
|
- 'current_type' => getProp($segment, 'current_type'),
|
|
|
- ]
|
|
|
- ]
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
- $episode['acts'] = array_values($acts);
|
|
|
- $episode['total_duration'] = intval(round($totalDuration)); // 取整后的总时长
|
|
|
+ // 使用公共方法构建分镜结构
|
|
|
+ $segmentsStructure = $this->buildEpisodeSegmentsStructure($segments);
|
|
|
+ $episode['acts'] = $segmentsStructure['acts'];
|
|
|
+ $episode['total_duration'] = $segmentsStructure['total_duration'];
|
|
|
|
|
|
return $episode;
|
|
|
}
|
|
|
@@ -611,67 +598,9 @@ class AnimeService
|
|
|
];
|
|
|
|
|
|
// 复用已有的分镜数据,按 act 分组(避免重复查询数据库)
|
|
|
- $acts = [];
|
|
|
- $totalDuration = 0; // 初始化总时长
|
|
|
-
|
|
|
- foreach($segments_for_insert as $segment) {
|
|
|
- // 计算分镜时长,优先级:video_duration > audio_duration > 默认5秒
|
|
|
- $videoDuration = getProp($segment, 'video_duration');
|
|
|
- $audioDuration = getProp($segment, 'audio_duration');
|
|
|
-
|
|
|
- if (!empty($videoDuration) && is_numeric($videoDuration)) {
|
|
|
- $totalDuration += floatval($videoDuration);
|
|
|
- } elseif (!empty($audioDuration) && is_numeric($audioDuration)) {
|
|
|
- $totalDuration += floatval($audioDuration);
|
|
|
- } else {
|
|
|
- $totalDuration += 5; // 默认5秒
|
|
|
- }
|
|
|
-
|
|
|
- $act_number = getProp($segment, 'act_number');
|
|
|
- $segment_info = [
|
|
|
- 'segment_id' => getProp($segment, 'segment_id'),
|
|
|
- 'segment_number' => getProp($segment, 'segment_number'),
|
|
|
- 'segment_content' => getProp($segment, 'segment_content'),
|
|
|
- 'description' => getProp($segment, 'description'),
|
|
|
- 'composition' => getProp($segment, 'composition'),
|
|
|
- 'camera_movement' => getProp($segment, 'camera_movement'),
|
|
|
- 'voice_actor' => getProp($segment, 'voice_actor'),
|
|
|
- 'dialogue' => getProp($segment, 'dialogue'),
|
|
|
- 'frame_type' => getProp($segment, 'frame_type'),
|
|
|
- 'scene' => getProp($segment, 'scene'),
|
|
|
- 'characters' => getProp($segment, 'characters'),
|
|
|
- 'tail_frame' => getProp($segment, 'tail_frame'),
|
|
|
- 'emotion' => getProp($segment, 'emotion'),
|
|
|
- 'emotion_type' => getProp($segment, 'emotion_type'),
|
|
|
- 'gender' => getProp($segment, 'gender'),
|
|
|
- 'speed_ratio' => getProp($segment, 'speed_ratio'),
|
|
|
- 'loudness_ratio' => getProp($segment, 'loudness_ratio'),
|
|
|
- 'emotion_scale' => getProp($segment, 'emotion_scale'),
|
|
|
- 'pitch' => getProp($segment, 'pitch'),
|
|
|
- 'voice_name' => getProp($segment, 'voice_name'),
|
|
|
- 'voice_type' => getProp($segment, 'voice_type'),
|
|
|
- 'voice_audio_url' => getProp($segment, 'voice_audio_url'),
|
|
|
- 'img_url' => getProp($segment, 'img_url'),
|
|
|
- 'audio_url' => getProp($segment, 'audio_url'),
|
|
|
- 'audio_duration' => getProp($segment, 'audio_duration', 0),
|
|
|
- 'video_url' => getProp($segment, 'video_url'),
|
|
|
- 'video_duration' => getProp($segment, 'video_duration', 0),
|
|
|
- 'last_frame_url' => getProp($segment, 'last_frame_url'),
|
|
|
- 'current_type' => getProp($segment, 'current_type'),
|
|
|
- ];
|
|
|
-
|
|
|
- if (isset($acts[$act_number])) {
|
|
|
- $acts[$act_number]['segments'][] = $segment_info;
|
|
|
- } else {
|
|
|
- $acts[$act_number] = [
|
|
|
- 'act_number' => $act_number,
|
|
|
- 'act_title' => getProp($segment, 'act_title'),
|
|
|
- 'segments' => [$segment_info]
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
- $result['acts'] = array_values($acts);
|
|
|
- $result['total_duration'] = intval(round($totalDuration)); // 取整后的总时长
|
|
|
+ $segmentsStructure = $this->buildEpisodeSegmentsStructure($segments_for_insert);
|
|
|
+ $result['acts'] = $segmentsStructure['acts'];
|
|
|
+ $result['total_duration'] = $segmentsStructure['total_duration'];
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
@@ -701,96 +630,10 @@ class AnimeService
|
|
|
return (array)$value;
|
|
|
})->toArray();
|
|
|
|
|
|
- $acts = [];
|
|
|
- $totalDuration = 0; // 初始化总时长
|
|
|
-
|
|
|
- foreach($segments as $segment) {
|
|
|
- // 计算分镜时长,优先级:video_duration > audio_duration > 默认5秒
|
|
|
- $videoDuration = getProp($segment, 'video_duration');
|
|
|
- $audioDuration = getProp($segment, 'audio_duration');
|
|
|
-
|
|
|
- if (!empty($videoDuration) && is_numeric($videoDuration)) {
|
|
|
- $totalDuration += floatval($videoDuration);
|
|
|
- } elseif (!empty($audioDuration) && is_numeric($audioDuration)) {
|
|
|
- $totalDuration += floatval($audioDuration);
|
|
|
- } else {
|
|
|
- $totalDuration += 5; // 默认5秒
|
|
|
- }
|
|
|
-
|
|
|
- if (isset($acts[getProp($segment, 'act_number')])) {
|
|
|
- $acts[getProp($segment, 'act_number')]['segments'][] = [
|
|
|
- 'segment_id' => getProp($segment, 'segment_id'),
|
|
|
- 'segment_number' => getProp($segment, 'segment_number'),
|
|
|
- 'segment_content' => getProp($segment, 'segment_content'),
|
|
|
- 'description' => getProp($segment, 'description'),
|
|
|
- 'composition' => getProp($segment, 'composition'),
|
|
|
- 'camera_movement' => getProp($segment, 'camera_movement'),
|
|
|
- 'voice_actor' => getProp($segment, 'voice_actor'),
|
|
|
- 'dialogue' => getProp($segment, 'dialogue'),
|
|
|
- 'frame_type' => getProp($segment, 'frame_type'),
|
|
|
- 'scene' => getProp($segment, 'scene'),
|
|
|
- 'characters' => getProp($segment, 'characters'),
|
|
|
- 'tail_frame' => getProp($segment, 'tail_frame'),
|
|
|
- 'emotion' => getProp($segment, 'emotion'),
|
|
|
- 'emotion_type' => getProp($segment, 'emotion_type'),
|
|
|
- 'gender' => getProp($segment, 'gender'),
|
|
|
- 'speed_ratio' => getProp($segment, 'speed_ratio'),
|
|
|
- 'loudness_ratio' => getProp($segment, 'loudness_ratio'),
|
|
|
- 'emotion_scale' => getProp($segment, 'emotion_scale'),
|
|
|
- 'pitch' => getProp($segment, 'pitch'),
|
|
|
- 'voice_name' => getProp($segment, 'voice_name'),
|
|
|
- 'voice_type' => getProp($segment, 'voice_type'),
|
|
|
- 'voice_audio_url' => getProp($segment, 'voice_audio_url'),
|
|
|
- 'img_url' => getProp($segment, 'img_url'),
|
|
|
- 'audio_url' => getProp($segment, 'audio_url'),
|
|
|
- 'audio_duration' => getProp($segment, 'audio_duration', 0),
|
|
|
- 'video_url' => getProp($segment, 'video_url'),
|
|
|
- 'video_duration' => getProp($segment, 'video_duration', 0),
|
|
|
- 'last_frame_url' => getProp($segment, 'last_frame_url'),
|
|
|
- 'current_type' => getProp($segment, 'current_type'),
|
|
|
- ];
|
|
|
- }else {
|
|
|
- $acts[getProp($segment, 'act_number')]= [
|
|
|
- 'act_number' => getProp($segment, 'act_number'),
|
|
|
- 'act_title' => getProp($segment, 'act_title'),
|
|
|
- 'segments' => [
|
|
|
- [
|
|
|
- 'segment_id' => getProp($segment, 'segment_id'),
|
|
|
- 'segment_number' => getProp($segment, 'segment_number'),
|
|
|
- 'segment_content' => getProp($segment, 'segment_content'),
|
|
|
- 'description' => getProp($segment, 'description'),
|
|
|
- 'composition' => getProp($segment, 'composition'),
|
|
|
- 'camera_movement' => getProp($segment, 'camera_movement'),
|
|
|
- 'voice_actor' => getProp($segment, 'voice_actor'),
|
|
|
- 'dialogue' => getProp($segment, 'dialogue'),
|
|
|
- 'frame_type' => getProp($segment, 'frame_type'),
|
|
|
- 'scene' => getProp($segment, 'scene'),
|
|
|
- 'characters' => getProp($segment, 'characters'),
|
|
|
- 'tail_frame' => getProp($segment, 'tail_frame'),
|
|
|
- 'emotion' => getProp($segment, 'emotion'),
|
|
|
- 'emotion_type' => getProp($segment, 'emotion_type'),
|
|
|
- 'gender' => getProp($segment, 'gender'),
|
|
|
- 'speed_ratio' => getProp($segment, 'speed_ratio'),
|
|
|
- 'loudness_ratio' => getProp($segment, 'loudness_ratio'),
|
|
|
- 'emotion_scale' => getProp($segment, 'emotion_scale'),
|
|
|
- 'pitch' => getProp($segment, 'pitch'),
|
|
|
- 'voice_name' => getProp($segment, 'voice_name'),
|
|
|
- 'voice_type' => getProp($segment, 'voice_type'),
|
|
|
- 'voice_audio_url' => getProp($segment, 'voice_audio_url'),
|
|
|
- 'img_url' => getProp($segment, 'img_url'),
|
|
|
- 'audio_url' => getProp($segment, 'audio_url'),
|
|
|
- 'audio_duration' => getProp($segment, 'audio_duration', 0),
|
|
|
- 'video_url' => getProp($segment, 'video_url'),
|
|
|
- 'video_duration' => getProp($segment, 'video_duration', 0),
|
|
|
- 'last_frame_url' => getProp($segment, 'last_frame_url'),
|
|
|
- 'current_type' => getProp($segment, 'current_type'),
|
|
|
- ]
|
|
|
- ]
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
- $episode['acts'] = array_values($acts);
|
|
|
- $episode['total_duration'] = intval(round($totalDuration)); // 取整后的总时长
|
|
|
+ // 使用公共方法构建分镜结构
|
|
|
+ $segmentsStructure = $this->buildEpisodeSegmentsStructure($segments);
|
|
|
+ $episode['acts'] = $segmentsStructure['acts'];
|
|
|
+ $episode['total_duration'] = $segmentsStructure['total_duration'];
|
|
|
}
|
|
|
|
|
|
return $episodes;
|
|
|
@@ -837,9 +680,14 @@ class AnimeService
|
|
|
}
|
|
|
$segment = DB::table("mp_episode_segments")->where('segment_id', $segment_id)->first();
|
|
|
if (!$segment) Utils::throwError('20003:该分镜不存在!');
|
|
|
- $ref_img_url = getProp($segment, 'img_url');
|
|
|
- if (empty($ref_img_url)) {
|
|
|
- $prompt = getProp($segment, 'segment_content');
|
|
|
+ // $ref_img_url = getProp($segment, 'img_url');
|
|
|
+ $ref_img_url = '';
|
|
|
+ if (empty($prompt)) {
|
|
|
+ if (empty($ref_img_url)) {
|
|
|
+ $prompt = getProp($segment, 'segment_content');
|
|
|
+ }else {
|
|
|
+ $prompt = '请根据图片生成';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
$anime_id = getProp($segment, 'anime_id');
|