Sfoglia il codice sorgente

片段分镜的画面新增画风提示词,并增加总开关控制是否添加

lh 10 ore fa
parent
commit
180796d849

+ 147 - 0
app/Libs/ActShowContent.php

@@ -0,0 +1,147 @@
+<?php
+
+
+namespace App\Libs;
+
+
+use Illuminate\Support\Facades\DB;
+
+
+/**
+ * act_show_content 处理:把动漫画风提示词插入每个「画面:[…]」块
+ *
+ * 规则:
+ * 1. 取 mp_animes.art_style_type,查 mp_art_styles(is_deleted=0)的 prompt;
+ * 2. prompt 非空时,插入到每个「画面:」后第一个闭合 ] 之前,用中文逗号分隔;
+ * 3. 找不到闭合 ] 的块、已包含该画风提示词的块跳过。
+ *
+ * 受 config('anime.act_show_art_style_enabled') 总开关控制,默认关闭;
+ * 只处理 act_show_content 字段,不修改 act_content。
+ */
+class ActShowContent
+{
+    /** 画风提示词缓存(anime_id => prompt),同一次请求内避免重复查库 */
+    private static $stylePromptCache = [];
+
+    /**
+     * 把画风提示词插入 act_show_content 中每个「画面:[…]」块
+     *
+     * @param string $content act_show_content 内容
+     * @param int    $animeId 所属动漫ID
+     * @return string 处理后的内容(开关关闭、无画风提示词时原样返回)
+     */
+    public static function insertArtStylePrompt($content, $animeId)
+    {
+        if (!config('anime.act_show_art_style_enabled', false)) {
+            return $content;
+        }
+
+        if (!is_string($content) || $content === '' || strpos($content, '画面:') === false) {
+            return $content;
+        }
+
+        $prompt = self::getArtStylePrompt($animeId);
+        if ($prompt === '') {
+            return $content;
+        }
+
+        $huamianLen     = strlen('画面:');
+        $insertPositions = [];
+        $skipped        = 0;
+        $offset         = 0;
+
+        while (($pos = strpos($content, '画面:', $offset)) !== false) {
+            $searchStart = $pos + $huamianLen;
+            $closePos    = strpos($content, ']', $searchStart);
+
+            if ($closePos === false) {
+                // 该「画面:」块找不到闭合 ],跳过
+                $skipped++;
+                break;
+            }
+
+            // 闭合 ] 之前已经出现下一个「画面:」,说明当前块没有闭合 ],跳过当前块
+            $nextPos = strpos($content, '画面:', $searchStart);
+            if ($nextPos !== false && $nextPos < $closePos) {
+                $skipped++;
+                $offset = $nextPos;
+                continue;
+            }
+
+            $inner = substr($content, $searchStart, $closePos - $searchStart);
+
+            // 画面块内没有 [,] 或已经跨到其它字段行,说明不是标准的「画面:[…]」,跳过
+            if (strpos($inner, '[') === false
+                || preg_match('/(^|\n)\s*(运镜|配音台词|背景音效|出场角色|场景|出场道具|【(?:镜头|分镜))/u', $inner)) {
+                $skipped++;
+                $offset = $closePos + 1;
+                continue;
+            }
+
+            if (strpos($inner, $prompt) !== false) {
+                // 已包含画风提示词,避免重复插入
+                $skipped++;
+            } else {
+                $insertPositions[] = [
+                    'pos'       => $closePos,
+                    'needComma' => !preg_match('/[,,、]\s*$/u', $inner),
+                ];
+            }
+
+            $offset = $closePos + 1;
+        }
+
+        if ($insertPositions) {
+            // 从后往前插入,避免前面的插入影响后面的位置
+            foreach (array_reverse($insertPositions) as $item) {
+                $insertText = ($item['needComma'] ? ',' : '') . $prompt;
+                $content    = substr($content, 0, $item['pos']) . $insertText . substr($content, $item['pos']);
+            }
+
+            dLog('anime')->debug('act_show_content 插入画风提示词', [
+                'anime_id' => (int)$animeId,
+                'inserted' => count($insertPositions),
+                'skipped'  => $skipped,
+            ]);
+        } elseif ($skipped > 0) {
+            dLog('anime')->warning('act_show_content 未找到可插入的「画面:[…]」块', [
+                'anime_id' => (int)$animeId,
+                'skipped'  => $skipped,
+            ]);
+        }
+
+        return $content;
+    }
+
+    /**
+     * 按动漫ID取画风提示词(mp_animes.art_style_type -> mp_art_styles.prompt)
+     *
+     * @param int $animeId
+     * @return string 取不到时返回空字符串
+     */
+    private static function getArtStylePrompt($animeId)
+    {
+        $animeId = (int)$animeId;
+        if ($animeId <= 0) {
+            return '';
+        }
+
+        if (!array_key_exists($animeId, self::$stylePromptCache)) {
+            $prompt       = '';
+            $anime        = DB::table('mp_animes')->where('id', $animeId)->first(['art_style_type']);
+            $artStyleType = $anime ? trim((string)$anime->art_style_type) : '';
+
+            if ($artStyleType !== '') {
+                $styleRow = DB::table('mp_art_styles')
+                    ->where('art_style', $artStyleType)
+                    ->where('is_deleted', 0)
+                    ->first(['prompt']);
+                $prompt = $styleRow ? trim((string)$styleRow->prompt) : '';
+            }
+
+            self::$stylePromptCache[$animeId] = $prompt;
+        }
+
+        return self::$stylePromptCache[$animeId];
+    }
+}

+ 5 - 0
app/Services/Anime/AnimeService.php

@@ -6,6 +6,7 @@ use App\Consts\BaseConst;
 use App\Consts\ErrorConst;
 use App\Exceptions\ApiException;
 use App\Facade\Site;
+use App\Libs\ActShowContent;
 use App\Libs\Utils;
 use App\Models\MpGeneratePicTask;
 use App\Models\MpTaskCenter;
@@ -12544,6 +12545,10 @@ class AnimeService
                     },
                     $processed_content
                 );
+
+                // 按动漫画风给 act_show_content 的「画面:[…]」插入画风提示词
+                // 总开关 config('anime.act_show_art_style_enabled') 默认关闭,只处理 act_show_content
+                $processed_content = ActShowContent::insertArtStylePrompt($processed_content, getProp($episode, 'anime_id'));
                 
                 // 更新数据库
                 $boolen = DB::table('mp_episode_segments')

+ 5 - 0
app/Services/DeepSeek/DeepSeekService.php

@@ -5,6 +5,7 @@ namespace App\Services\DeepSeek;
 use App\Consts\ErrorConst;
 use App\Consts\BaseConst;
 use App\Facade\Site;
+use App\Libs\ActShowContent;
 use App\Libs\JsonSafeRepair;
 use App\Libs\Utils;
 use GuzzleHttp\Client;
@@ -14284,6 +14285,10 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
                     },
                     $processed_content
                 );
+
+                // 按动漫画风给 act_show_content 的「画面:[…]」插入画风提示词
+                // 总开关 config('anime.act_show_art_style_enabled') 默认关闭,只处理 act_show_content
+                $processed_content = ActShowContent::insertArtStylePrompt($processed_content, $target_anime_id);
                 
                 $segment['act_show_content'] = $processed_content;
             }

+ 21 - 0
config/anime.php

@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * 动漫生成相关配置
+ */
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | act_show_content 插入画风提示词开关
+    |--------------------------------------------------------------------------
+    | 开启后,confirmActs、regenerateSegmentScript 生成 act_show_content 时,
+    | 会按动漫的 art_style_type 取 mp_art_styles.prompt,
+    | 插入到每个「画面:[…]」的第一个闭合 ] 之前。
+    | 只影响 act_show_content 字段,不修改 act_content。
+    |
+    | 默认关闭;线上开启方式:.env 中配置 ACT_SHOW_ART_STYLE_ENABLED=true
+    */
+    'act_show_art_style_enabled' => (bool)env('ACT_SHOW_ART_STYLE_ENABLED', false),
+
+];