Files
bini-shorts-maker/backend/app/routers/fonts.py
kihong.kim c3795138da Initial commit: YouTube Shorts maker application
Features:
- Video download from TikTok/Douyin using yt-dlp
- Audio transcription with OpenAI Whisper
- GPT-4 translation (direct/summarize/rewrite modes)
- Subtitle generation with ASS format
- Video trimming with frame-accurate preview
- BGM integration with volume control
- Intro text overlay support
- Thumbnail generation with text overlay

Tech stack:
- Backend: FastAPI, Python 3.11+
- Frontend: React, Vite, TailwindCSS
- Video processing: FFmpeg
- AI: OpenAI Whisper, GPT-4

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 21:38:34 +09:00

164 lines
4.9 KiB
Python

"""
Fonts Router - Korean font management for subtitles.
Provides font listing and recommendations for YouTube Shorts subtitles.
"""
from fastapi import APIRouter, HTTPException
from app.models.schemas import FontInfo, KOREAN_FONTS, FONT_RECOMMENDATIONS
router = APIRouter()
@router.get("/")
async def list_fonts():
"""
List all available Korean fonts for subtitles.
Returns font information including:
- id: System font name to use in subtitle_style.font_name
- name: Display name in Korean
- style: Font style description
- recommended_for: Content types this font works well with
- download_url: Where to download the font
- license: Font license information
"""
fonts = []
for font_id, font_info in KOREAN_FONTS.items():
fonts.append({
"id": font_info.id,
"name": font_info.name,
"style": font_info.style,
"recommended_for": font_info.recommended_for,
"download_url": font_info.download_url,
"license": font_info.license,
})
return {
"fonts": fonts,
"total": len(fonts),
"default": "NanumGothic",
"usage": "Set subtitle_style.font_name to the font id",
}
@router.get("/recommend/{content_type}")
async def recommend_fonts(content_type: str):
"""
Get font recommendations for a specific content type.
Available content types:
- tutorial: 튜토리얼, 강의
- gaming: 게임, 리액션
- cooking: 요리, 먹방
- comedy: 코미디, 유머
- travel: 여행, 브이로그
- news: 뉴스, 정보
- asmr: ASMR, 릴렉스
- fitness: 운동, 피트니스
- tech: 기술, IT
- lifestyle: 라이프스타일, 일상
"""
content_type_lower = content_type.lower()
if content_type_lower not in FONT_RECOMMENDATIONS:
available_types = list(FONT_RECOMMENDATIONS.keys())
raise HTTPException(
status_code=404,
detail=f"Unknown content type. Available: {', '.join(available_types)}"
)
recommended_ids = FONT_RECOMMENDATIONS[content_type_lower]
recommendations = []
for font_id in recommended_ids:
if font_id in KOREAN_FONTS:
font = KOREAN_FONTS[font_id]
recommendations.append({
"id": font.id,
"name": font.name,
"style": font.style,
"download_url": font.download_url,
})
return {
"content_type": content_type_lower,
"recommendations": recommendations,
"primary": recommended_ids[0] if recommended_ids else "NanumGothic",
}
@router.get("/categories")
async def list_font_categories():
"""
List fonts grouped by style category.
"""
categories = {
"clean": {
"name": "깔끔/모던",
"description": "정보성 콘텐츠, 튜토리얼에 적합",
"fonts": ["Pretendard", "SpoqaHanSansNeo", "NanumGothic"],
},
"friendly": {
"name": "친근/둥글",
"description": "일상, 라이프스타일 콘텐츠에 적합",
"fonts": ["GmarketSans", "NanumSquareRound", "Cafe24SsurroundAir"],
},
"handwriting": {
"name": "손글씨/캐주얼",
"description": "먹방, 요리, 유머 콘텐츠에 적합",
"fonts": ["BMDoHyeon", "BMJua", "DoHyeon"],
},
"impact": {
"name": "강조/임팩트",
"description": "게임, 하이라이트, 리액션에 적합",
"fonts": ["Cafe24Ssurround", "BlackHanSans"],
},
}
# Add font details to each category
for category_id, category_info in categories.items():
font_details = []
for font_id in category_info["fonts"]:
if font_id in KOREAN_FONTS:
font = KOREAN_FONTS[font_id]
font_details.append({
"id": font.id,
"name": font.name,
})
category_info["font_details"] = font_details
return {
"categories": categories,
}
@router.get("/{font_id}")
async def get_font(font_id: str):
"""
Get detailed information about a specific font.
"""
if font_id not in KOREAN_FONTS:
available_fonts = list(KOREAN_FONTS.keys())
raise HTTPException(
status_code=404,
detail=f"Font not found. Available fonts: {', '.join(available_fonts)}"
)
font = KOREAN_FONTS[font_id]
return {
"id": font.id,
"name": font.name,
"style": font.style,
"recommended_for": font.recommended_for,
"download_url": font.download_url,
"license": font.license,
"usage_example": {
"subtitle_style": {
"font_name": font.id,
"font_size": 36,
"position": "center",
}
},
}