|
|
@@ -653,6 +653,23 @@ class AnimeController extends BaseController
|
|
|
if (!$episode) Utils::throwError('20003:分集不存在');
|
|
|
$episodeNumber = $episode->episode_number;
|
|
|
$ratio = !empty($episode->ratio) ? $episode->ratio : '9:16';
|
|
|
+ $generate_audio = getProp($data, 'generate_audio', 0);
|
|
|
+
|
|
|
+ // 处理视频模型(在循环外统一处理)
|
|
|
+ $model = getProp($data, 'model');
|
|
|
+ if (!$model) {
|
|
|
+ // 用户没有输入,从episode表获取
|
|
|
+ $model = getProp($episode, 'video_model');
|
|
|
+ if (!$model) {
|
|
|
+ // episode表也没有,使用默认值
|
|
|
+ $model = 'doubao-seedance-1-5-pro-251215';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 验证模型是否在可用模型表中
|
|
|
+ if (!DB::table('mp_video_models')->where('model', $model)->where('is_enabled', 1)->exists()) {
|
|
|
+ $model = 'doubao-seedance-1-5-pro-251215';
|
|
|
+ }
|
|
|
+
|
|
|
// 获取所有分镜信息
|
|
|
$segments = DB::table('mp_episode_segments')
|
|
|
->where('anime_id', $animeId)
|
|
|
@@ -680,34 +697,66 @@ class AnimeController extends BaseController
|
|
|
$segmentContent = $segment->segment_content ?: '';
|
|
|
$tailFrame = $segment->tail_frame ?: '';
|
|
|
|
|
|
+ // 判断 $segmentContent 是否有台词内容,如果有则确保使用中文左右双引号
|
|
|
+ $hasDialogue = false;
|
|
|
+ if (preg_match('/(?:台词内容|台词|对白|对话)[::]\s*([^\n]+)/u', $segmentContent, $dialogueMatch)) {
|
|
|
+ $dialogue = trim($dialogueMatch[1]);
|
|
|
+
|
|
|
+ // 如果台词不为空且不是"无"
|
|
|
+ if (!empty($dialogue) && $dialogue !== '无') {
|
|
|
+ // 过滤掉所有符号(引号、标点、空格等),只保留文字内容来判断是否有实际台词
|
|
|
+ $dialogueFiltered = preg_replace('/[""\'\',。!?、;:…—\-\s\p{P}\p{S}]/u', '', $dialogue);
|
|
|
+ if (!empty($dialogueFiltered) && $dialogueFiltered !== '无') {
|
|
|
+ $hasDialogue = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ $dialogue = preg_replace('/^["”]/u', '“', $dialogue); // 替换句首英文双引号或中文右双引号
|
|
|
+ $dialogue = preg_replace('/["“]$/u', '”', $dialogue); // 替换句尾英文双引号或中文左双引号
|
|
|
+ // 句首或句尾没有中文双引号,则分别添加中文左右双引号
|
|
|
+ if (!preg_match('/^[“]/', $dialogue)) {
|
|
|
+ $dialogue = '“' . $dialogue;
|
|
|
+ }
|
|
|
+ if (!preg_match('/[”]$/', $dialogue)) {
|
|
|
+ $dialogue .= '”';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将修改后的台词替换回 $segmentContent
|
|
|
+ $originalDialogue = $dialogueMatch[1];
|
|
|
+ $segmentContent = str_replace($originalDialogue, $dialogue, $segmentContent);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查 $segmentContent 中是否已有尾帧描述
|
|
|
+ $contentHasTailFrame = preg_match('/(?:尾帧描述|尾帧)[::]\s*([^\n]+)/u', $segmentContent, $contentTailFrameMatch);
|
|
|
+
|
|
|
+ // 确定最终使用的尾帧描述(优先级:segmentContent自带 > 分镜表字段)
|
|
|
+ $finalTailFrame = '';
|
|
|
+ if ($contentHasTailFrame) {
|
|
|
+ // segmentContent 中有尾帧描述,使用它
|
|
|
+ $finalTailFrame = trim($contentTailFrameMatch[1]);
|
|
|
+ } else {
|
|
|
+ // segmentContent 中没有,使用分镜表中的尾帧描述
|
|
|
+ $finalTailFrame = $tailFrame;
|
|
|
+ }
|
|
|
+
|
|
|
// 构建完整的提示词
|
|
|
$fullPrompt = $segmentContent;
|
|
|
- if ($tailFrame) {
|
|
|
- $fullPrompt .= "\n尾帧描述:$tailFrame";
|
|
|
+ if ($finalTailFrame && !$contentHasTailFrame) {
|
|
|
+ // 只有当 segmentContent 中没有尾帧描述时才追加
|
|
|
+ $fullPrompt .= "\n尾帧描述:$finalTailFrame";
|
|
|
}
|
|
|
|
|
|
+ // 去除多余的换行符(将连续多个换行符替换为单个换行符)
|
|
|
+ $fullPrompt = preg_replace('/\n{2,}/', "\n", $fullPrompt);
|
|
|
+ $fullPrompt = trim($fullPrompt);
|
|
|
+
|
|
|
+ // 当前是否启用音效同出(没台词强制关闭音效同出,节省资源收费)
|
|
|
+ $current_generate_audio = $hasDialogue ? $generate_audio : 0;
|
|
|
+
|
|
|
// 智能选择视频时长
|
|
|
// $videoDuration = $this->AnimeService->calculateOptimalVideoDuration($segmentContent, $tailFrame);
|
|
|
$videoDuration = -1;
|
|
|
|
|
|
- // 处理视频模型(在循环外统一处理,避免重复)
|
|
|
- if (!isset($model)) {
|
|
|
- $model = getProp($data, 'model');
|
|
|
- if (!$model) {
|
|
|
- // 用户没有输入,从episode表获取
|
|
|
- $episode = DB::table('mp_anime_episodes')->where('id', $episodeId)->first();
|
|
|
- $model = getProp($episode, 'video_model');
|
|
|
- if (!$model) {
|
|
|
- // episode表也没有,使用默认值
|
|
|
- $model = 'doubao-seedance-1-5-pro-251215';
|
|
|
- }
|
|
|
- }
|
|
|
- // 验证模型是否在可用模型表中
|
|
|
- if (!DB::table('mp_video_models')->where('model', $model)->where('is_enabled', 1)->exists()) {
|
|
|
- $model = 'doubao-seedance-1-5-pro-251215';
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
// 构建视频生成参数
|
|
|
$videoParams = [
|
|
|
'model' => $model,
|
|
|
@@ -717,7 +766,7 @@ class AnimeController extends BaseController
|
|
|
'video_resolution' => '720P',
|
|
|
'seed' => -1,
|
|
|
'ratio' => $ratio,
|
|
|
- 'generate_audio' => false,
|
|
|
+ 'generate_audio' => (int)$current_generate_audio === 0 ? false : true,
|
|
|
'draft' => false,
|
|
|
'watermark' => false,
|
|
|
'camera_fixed' => false,
|
|
|
@@ -842,12 +891,10 @@ class AnimeController extends BaseController
|
|
|
}
|
|
|
|
|
|
// 保存模型到episode表
|
|
|
- if (isset($model)) {
|
|
|
- DB::table('mp_anime_episodes')->where('id', $episodeId)->update([
|
|
|
- 'video_model' => $model,
|
|
|
- 'updated_at' => date('Y-m-d H:i:s')
|
|
|
- ]);
|
|
|
- }
|
|
|
+ DB::table('mp_anime_episodes')->where('id', $episodeId)->update([
|
|
|
+ 'video_model' => $model,
|
|
|
+ 'updated_at' => date('Y-m-d H:i:s')
|
|
|
+ ]);
|
|
|
|
|
|
// 记录开始时间(包含创建任务的时间)
|
|
|
$startTime = time();
|