From 211d81009102778221b95e954d5cc92928df6ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Tue, 28 Jul 2026 13:35:02 +0800 Subject: [PATCH] 1 --- short_drama.db | Bin 462848 -> 462848 bytes shortdrama/model/domain/shot.go | 4 ++-- shortdrama/service/episode_service.go | 31 +++++++++++++------------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/short_drama.db b/short_drama.db index e9e79d82c90f14e3835b3a334632fd36a601e522..9e2193a6a30ecfe891cdbd9cdc0a8c35daefc676 100644 GIT binary patch delta 1995 zcmd5-T})e596#sWb4v@iLzpooT-w-|DaMDtf2LKGw>Y~*SfT8(RixcKA_O&_SXzHBf>61Da;Cg{8 z$z|@X27vp~Y_0~-aL<<&mQ-8D%wam`NcCR6&;)m-xL@a)+6hA}QUf5=Ta13c(Fi|m zO+LDGr`@RtvLc9fw@a1;c`NTxcwXd1w~d!=qQ@$%@23*^8EjijznFXHbnf^kS3gT! zOGmGbzqyz`adkRAclyHI%U{fq(fLekEeRBPqL=cNa6k5M^m&#Ht%3J zCl|i0Pj2~R#?T$7JA973;*xc)h!P6Lr0~Nt_~?7TrXXD7e|qQ zgZVUybRF0SbUw8*gB0D~q$l=*Mgd%<;O%-SLu^Kap>XhE_^BIUmlUUL7bS`JY)ng8 zKbgpf)xMu`J5xb{=6OXV-@nJ0)RFCM4VHGenDSz^o-uFAsQgv;WAnkOg=5762{YbUKegH|7{ zR$5Pz%UQgYwbP?bUCv_MbtZ#YR-Xg<9Hp;^sp8HR%+xqKlxok+!dd_-FKN^nR;hcp zspy_E8a8xKSzn`xP@3-FOC6p5PnGZsG>whb#bNQ1hpFSw?u0TK_zBnB){vy8U&a0g z^_4f7LKDw z;pFoLYX<1`heE@l;L4Sn1dF1TWG}h$4H~W+GsTV;Vb+4R1hbZ{W$gbQbreke4{)AE zYz1fr727~F;bu`o&6p_;)@?_wbg<_2vHuqe5WN3}1Zq#U#zwSFiWYjkv1p-^)&$Rn zAeHskHX##Vq2F%uUrBt8mdVH@K1*Kdr1^7u0XR*@9cW04vF@AZ(JH-8Np@>_bcf{_ MjXyg<1g+)G)c^nh delta 3366 zcmcIn3v5%@8TR$P*CDY3uaeUSw&ShXkv6N+Lcbfu$nQb(hVwADx*SMtyS|^jA%nE(5GAIb;6%` zRG&>3u@7FQ5=qYoU;dClzuZn`dD_0(LAQVMU`2b+=Mn9n{&7Y7#;^Yzsjwaf7)jPD zD={XPtfQty(d-sFC7v;;(+x^} zDx*%b7UH>Qc-&s-0tQ)-8UHN%{Bz(3t`Z_18q zhq2SgjZEUp)&DS8w~yV((Bla=t~bLZZ*$}6^Fgue4VUBPX3VeniVj0d~>;h4a% z2alfedz)}eC!X#{F@0nbnq$crlzEF>hI*ILQuOr~WE9#cp=D@xoZO05Um@erXYq6l zxO|Xal8OXe$HFgg`ZA3BCp!eV^}T+dFL26= zT5ggrBnKu3xXvNmV1^%e#tMhPn!xE%Tx-MicHC_H|4^Ed(JN3I5wRH+xye|RMp1F- z%d5ca-CICC{xrLaN4Lor7rI-H zTCS2x^v~Pm^Jt9#%fOP!`~2QX|8x_0EqL-Q-#37pF5;#du7M3WrvgJgey^sTzSn$k60jAf?H8ygMRsm@rd^QRZGUFvz zCiQx8^CUpz$1M;XO;+~GJ1m$D_O`TrQ(ij zOuE7DYIoBBA$AeDnt>*g>^daE6Zt%AcUkfE= z*ERp71y6V&`FO`Pr~&jK)_C7Vfq1jaKRE#B@J;80EU0q_Po5AocMb>6&jeDs&A4Td zAE*^9wKno&=OL+iaGB5N_l|JAQ+Tk0vo%9tJd}0Ee<=nvcCPDkV6u*HtoD0d`11c= zA(lz#7m=e6vZm<{=)ZlOii-<*$5fD0e9#E~Q7R3L7HR)ZuGt=}ZR3Wff@m1G3~=L6 z27I6$XRilM`H(*ZJ{=R-(F)^u@Ejg+;npeK5vm76JzPy~zl+&s)R%<%mn)EI}xv9~5LJqoh( z1D3#4cd%U`h5NfeMy^Y!g|GnIC(z!{prF7k9&w<5O_K`r_D5tw0;~;MMxly7q4d*J zd|bst!3z~7u44cweM|rw&&N>lURq1bc7z@8pKcbA4vujwi))9%fh*MLYlDE0hpWUn z94ZtSAl{$~LG{CydWb;I-WoL90=D!1$#KApCcdH*^pMX%^BJCPRQcB8eg(1~pE@5Fa07R)3OXy#AiHy^$#4j}Xztw$|s;>smr>3bqsz4Sd+ zHYfgrG~U8k_XtlG;^CvlA|?No1;!(CgE~cCVLVc?v$CSJQYc`i%90YOXXW`uld)WG5I$4n`9-;9x%m~wvWFwb zWQTK2OsZB<##AX7bUKHMJWkeCT7NwspFJkzEODvPR8VXx{0>Oz>H7Z&`O*Ai$jlRv zLvRzrcz^YXm@-9PU@XrsD=w`lK4kK^=W@iyQ{*MZAzE_SQ&3r!D@@4^Dmd{;iYfBq zgSmyq?A(eX@QVD{o`p-mjwv@((YPyTxUP2GgoGm>8w_t+#8Ct}J|`xZ6Dsy^yCw1{ zmdcdep{?W?C7mTwk!+Sa6q5#Tx-HPQLE8mQiR`mfTFh(E&4jiO+Gc1Q(2ZGY6a6#j z=CBWDDQf50Iq~uiGfgcKlW&R0x1`$;gigV6k!YD?zA~r2Tbai%WW9>fep{Kv<|#N| zIsg2wT?>>q%$FVx&>GT}srq!SHe+!E^X6GgHr*wbw@}t2Ap`59v(&qziPJ~J1`0uR zK}1tw=qfZXQ#DGRTB8x5Um{V- yR{A2TVjhbA3-qppDr8MA@lPp~77-DP-cF|Fk>O1`osPZl7t0dr%=B5a#PM%D6Bhme diff --git a/shortdrama/model/domain/shot.go b/shortdrama/model/domain/shot.go index ddff7cb..7c419f2 100644 --- a/shortdrama/model/domain/shot.go +++ b/shortdrama/model/domain/shot.go @@ -53,10 +53,10 @@ func writeShotFields(b *strings.Builder, s Shot) { fmt.Fprintf(b, "事件:%s\n", s.Event) } if s.Dialogue != "" { - fmt.Fprintf(b, "台词:%s\n", s.Dialogue) + fmt.Fprintf(b, "台词:%s(角色开口说)\n", s.Dialogue) } if s.Narration != "" { - fmt.Fprintf(b, "画外音:%s\n", s.Narration) + fmt.Fprintf(b, "画外音:%s(角色不开口,仅播放旁白配音)\n", s.Narration) } if s.AmbientSound != "" { fmt.Fprintf(b, "环境音:%s\n", s.AmbientSound) diff --git a/shortdrama/service/episode_service.go b/shortdrama/service/episode_service.go index 0a899db..ba19f57 100644 --- a/shortdrama/service/episode_service.go +++ b/shortdrama/service/episode_service.go @@ -247,9 +247,6 @@ func (s *episodeService) GenerateScript(ctx context.Context, dramaId int64, epis fastCharPerSecond := g.Cfg().MustGet(ctx, "speech.fastCharPerSecond", 6).Int() slowCharPerSecond := g.Cfg().MustGet(ctx, "speech.slowCharPerSecond", 3).Int() - // 在发送给AI前,截断超出朗读预算的剧情描述,避免AI生成时长不足的镜头 - description = truncateDescriptionForDuration(description, int(d.EpisodeDuration), charPerSecond) - systemPrompt := PromptService.GetScriptGenerationPrompt(ctx) userInput := s.buildScriptGenUserInput(ctx, d, episodeTitle, description, genCtx, refTemplate, videoModel) @@ -750,24 +747,26 @@ func createPendingTasks(ctx context.Context, dramaId, epId int64, script string, // ============ 直接为各分段创建生成任务(script 按模型配置的 API 请求体格式构建)============ segDurs := calcSegDurs(d.EpisodeDuration, modelCfg) - segStartTimes := make([]int, len(segDurs)) - for i := 1; i < len(segDurs); i++ { - segStartTimes[i] = segStartTimes[i-1] + segDurs[i-1] - } + // 按镜头数量均分到各分段(避免时间窗口切分导致的空段或信息不全) + totalShots := len(allShots) + numSegs := len(segDurs) + base := totalShots / numSegs + extra := totalShots % numSegs + shotIdx := 0 for segIdx, segDur := range segDurs { - segEndTime := segStartTimes[segIdx] + segDur - var segShots []domain.Shot - for _, sh := range allShots { - shStart := parseMMSSToSeconds(sh.StartTime) - if shStart < segStartTimes[segIdx] || shStart >= segEndTime { - continue - } - segShots = append(segShots, sh) + count := base + if segIdx < extra { + count++ + } + end := shotIdx + count + if end > totalShots { + end = totalShots } taskGroups = append(taskGroups, _taskGroup{ - promptText: domain.ShotsToPromptText(segShots), + promptText: domain.ShotsToPromptText(allShots[shotIdx:end]), dur: segDur, }) + shotIdx = end } } else { // 纯文本脚本:按 calcSegDurs 拆段 + splitScriptForSegment 切分(保留原逻辑)