fix: 인트로 텍스트 20자 제한 및 비디오 캐싱 문제 해결

- 인트로(썸네일) 텍스트 제한을 10자에서 20자로 증가
- 비디오 URL에 updated_at 타임스탬프 추가하여 캐싱 문제 해결
- 재편집 후 영상이 이전 버전으로 보이는 문제 수정

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kihong.kim
2026-01-04 22:10:23 +09:00
parent be3ed688a1
commit ad14c4ea8c
3 changed files with 12 additions and 8 deletions

View File

@@ -88,7 +88,7 @@ class RenderRequest(BaseModel):
subtitle_style: Optional[SubtitleStyle] = None subtitle_style: Optional[SubtitleStyle] = None
keep_original_audio: bool = False keep_original_audio: bool = False
# Intro text overlay (shown at beginning of video for YouTube Shorts thumbnail) # Intro text overlay (shown at beginning of video for YouTube Shorts thumbnail)
intro_text: Optional[str] = None # Max 10 characters recommended intro_text: Optional[str] = None # Max 20 characters recommended
intro_duration: float = 0.7 # Duration of frozen frame with intro text (seconds) intro_duration: float = 0.7 # Duration of frozen frame with intro text (seconds)
intro_font_size: int = 100 # Font size intro_font_size: int = 100 # Font size

View File

@@ -3,6 +3,9 @@ import { Download, FileText, Film } from 'lucide-react';
import { jobsApi } from '../api/client'; import { jobsApi } from '../api/client';
export default function VideoPreview({ videoUrl, jobId }) { export default function VideoPreview({ videoUrl, jobId }) {
// Generate cache-busting timestamp
const cacheBuster = `?t=${Date.now()}`;
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<h3 className="font-medium flex items-center gap-2"> <h3 className="font-medium flex items-center gap-2">
@@ -17,6 +20,7 @@ export default function VideoPreview({ videoUrl, jobId }) {
controls controls
className="w-full h-full object-contain" className="w-full h-full object-contain"
poster="" poster=""
key={videoUrl}
> >
브라우저가 비디오를 지원하지 않습니다. 브라우저가 비디오를 지원하지 않습니다.
</video> </video>

View File

@@ -498,8 +498,8 @@ export default function HomePage() {
try { try {
const res = await thumbnailApi.generateCatchphrase(currentJob.job_id, 'homeshopping'); const res = await thumbnailApi.generateCatchphrase(currentJob.job_id, 'homeshopping');
if (res.data.catchphrase) { if (res.data.catchphrase) {
// 최대 10자 제한 // 최대 20자 제한
const text = res.data.catchphrase.slice(0, 10); const text = res.data.catchphrase.slice(0, 20);
setIntroText(text); setIntroText(text);
} }
} catch (err) { } catch (err) {
@@ -575,7 +575,7 @@ export default function HomePage() {
완성된 영상 완성된 영상
</h3> </h3>
<VideoPreview <VideoPreview
videoUrl={jobsApi.downloadOutput(currentJob.job_id)} videoUrl={`${jobsApi.downloadOutput(currentJob.job_id)}?t=${new Date(currentJob.updated_at).getTime()}`}
jobId={currentJob.job_id} jobId={currentJob.job_id}
/> />
</div> </div>
@@ -905,13 +905,13 @@ export default function HomePage() {
<input <input
type="text" type="text"
value={introText} value={introText}
onChange={(e) => setIntroText(e.target.value.slice(0, 10))} onChange={(e) => setIntroText(e.target.value.slice(0, 20))}
placeholder="최대 10자 입력..." placeholder="최대 20자 입력..."
maxLength={10} maxLength={20}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white text-lg focus:outline-none focus:border-pink-500" className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white text-lg focus:outline-none focus:border-pink-500"
/> />
<span className="absolute right-3 top-1/2 -translate-y-1/2 text-xs text-gray-500"> <span className="absolute right-3 top-1/2 -translate-y-1/2 text-xs text-gray-500">
{introText.length}/10 {introText.length}/20
</span> </span>
</div> </div>