쇼츠 클립 채널의 소재를 최신순으로 발굴하는 /feed 화면과 수집 파이프라인. - 소재 원본 탭: 웹예능 공식채널의 신규 롱폼(durationSec > 65)만 수집. 아직 아무도 안 자른 구간을 선점하는 용도라 공식계정 쇼츠는 제외한다. - 경쟁 쇼츠 탭: 예능짤 채널의 신규 쇼츠. 제목·썸네일 벤치마킹용이라 재가공 대신 원본 열기 액션을 준다. - Channel.role(MY/SOURCE/RIVAL) 컬럼 하나로 역할을 구분하고, 기존 uploads 플레이리스트 동기화를 그대로 재사용한다. 채널당 2 units라 search.list(100 units) 대비 쿼터가 거의 들지 않는다. - 3시간 주기 수집(FeedCollectionService). 소재 선점은 업로드 직후가 승부라 기존 일 1회 채널 수집으로는 늦다. - 수집함/발굴/떡상 후보 쿼리는 source 미지정 시 CHANNEL·SEARCH만 보도록 좁혀, 피드 영상이 기존 화면을 덮지 않게 격리했다. - 시드는 자동 후보 → 수동 승인. 내 채널 해시태그를 역분석해(HashtagExtractor) 공식채널 후보를 추천 목록에 쌓고, 승인 시 SOURCE/RIVAL로 등록한다. - 연속 3회 수집 실패한 시드는 자동 스킵해 쿼터 낭비를 막는다. - role이 null인 기존 채널은 부팅 시 MY로 1회 백필(ddl-auto:update 특성). UX: 기존 Editorial 디자인 시스템 유지. 골든타임(24h)·공식클립/풀에피· 떡상중·작업함 배지, 프로그램/길이/기간 필터, URL 상태 보존, 스켈레톤· 빈 상태·에러 복구 액션, 탭 키보드 이동, 이모지 대신 Lucide 아이콘. 테스트: HashtagExtractor·FeedBadges·ChannelRole 순수 로직 16건 추가(총 76건 통과). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
118 lines
5.1 KiB
YAML
118 lines
5.1 KiB
YAML
spring:
|
|
application:
|
|
name: h-lab
|
|
# Secrets are supplied via environment variables, or a git-ignored
|
|
# application-local.yml (see application-local.yml.example). No secrets here.
|
|
config:
|
|
import: optional:classpath:application-local.yml
|
|
servlet:
|
|
multipart:
|
|
max-file-size: ${UPLOAD_MAX_FILE_SIZE:200MB} # 업로드 영상(Whisper 전사용)
|
|
max-request-size: ${UPLOAD_MAX_REQUEST_SIZE:200MB}
|
|
datasource:
|
|
url: ${DB_URL:}
|
|
driverClassName: org.postgresql.Driver
|
|
username: ${DB_USERNAME:}
|
|
password: ${DB_PASSWORD:}
|
|
jpa:
|
|
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
|
hibernate:
|
|
ddl-auto: update
|
|
show-sql: false
|
|
properties:
|
|
hibernate:
|
|
format_sql: false
|
|
|
|
decorator:
|
|
datasource:
|
|
p6spy:
|
|
# 운영 기본 OFF — 모든 SQL 로깅은 순수 오버헤드. 디버깅 시 P6SPY_LOGGING=true 로 켠다.
|
|
enable-logging: ${P6SPY_LOGGING:false}
|
|
multiline: true
|
|
logging: slf4j
|
|
log-message-format: com.hlab.yanalyst.global.config.P6SpyFormatter
|
|
tracing:
|
|
include-parameter-values: true
|
|
|
|
springdoc:
|
|
swagger-ui:
|
|
path: /swagger-ui.html
|
|
tags-sorter: alpha
|
|
operations-sorter: alpha
|
|
api-docs:
|
|
path: /v3/api-docs
|
|
|
|
|
|
server:
|
|
port: 8088
|
|
|
|
# YouTube Data API 키 (YOUTUBE_API_KEY 환경변수 또는 application-local.yml 로 주입)
|
|
youtube:
|
|
api:
|
|
key: ${YOUTUBE_API_KEY:}
|
|
|
|
# Python 마이크로서비스(자막 /transcript, Whisper 전사 /transcribe). 동일 호스트면 http://localhost:8000 로 오버라이드.
|
|
python:
|
|
base-url: ${PYTHON_BASE_URL:http://h-python.tolag.shop}
|
|
|
|
# yt-dlp 원본 다운로드(로컬 ProcessBuilder 실행). 재가공 '원본 다운로드' 버튼이 사용.
|
|
ytdlp:
|
|
bin: ${YTDLP_BIN:yt-dlp} # PATH 에 있으면 그대로, 아니면 절대경로 지정
|
|
ffmpeg-location: ${FFMPEG_LOCATION:} # 비우면 PATH 사용. 필요시 ffmpeg bin 폴더 경로(예: D:\\utils\\ffmpeg\\bin)
|
|
max-height: ${YTDLP_MAX_HEIGHT:1080} # bv*[height<=N]+ba/b, mp4 머지
|
|
timeout-seconds: ${YTDLP_TIMEOUT_SECONDS:600}
|
|
download:
|
|
dir: ${DOWNLOAD_DIR:downloads} # 다운로드 캐시 폴더(작업 디렉토리 기준 상대경로 가능)
|
|
|
|
# 자가호스팅 LibreTranslate(원본 스크립트 번역 → 재가공 초안). POST /translate {q,source,target}.
|
|
translate:
|
|
base-url: ${TRANSLATE_BASE_URL:https://h-translate.tolag.shop}
|
|
|
|
# Gemini(무료 티어): 유튜브 URL → 화면 자막 추출 + 한국어 번역. AI Studio API 키 사용.
|
|
gemini:
|
|
api-key: ${GEMINI_API_KEY:}
|
|
model: ${GEMINI_MODEL:gemini-2.5-flash} # 유튜브 URL 영상 이해 지원
|
|
|
|
hlab:
|
|
# 정기 자동 수집: 등록 채널의 신규 Shorts 를 주기적으로 수집
|
|
scheduler:
|
|
channel-collection:
|
|
enabled: ${CHANNEL_COLLECTION_ENABLED:true}
|
|
cron: ${CHANNEL_COLLECTION_CRON:0 0 4 * * *} # 매일 04:00
|
|
channel-snapshot:
|
|
enabled: ${CHANNEL_SNAPSHOT_ENABLED:true}
|
|
cron: ${CHANNEL_SNAPSHOT_CRON:0 0 3 * * *} # 매일 03:00 (성장 추이 기록)
|
|
channel-discovery:
|
|
enabled: ${CHANNEL_DISCOVERY_ENABLED:true}
|
|
cron: ${CHANNEL_DISCOVERY_CRON:0 30 4 * * *} # 매일 04:30 (추천 채널 발굴)
|
|
youtube:
|
|
daily-quota: ${YOUTUBE_DAILY_QUOTA:10000} # 자동 수집이 소비할 수 있는 일일 쿼터 상한(추정)
|
|
# 추천 채널 발굴: 지역 인기 Shorts 에서 작은구독자·고배율 떡상 채널 발굴
|
|
discovery:
|
|
regions: ${DISCOVERY_REGIONS:KR}
|
|
max-subscribers: ${DISCOVERY_MAX_SUBS:100000} # 작은 채널 상한
|
|
min-ratio: ${DISCOVERY_MIN_RATIO:5.0} # 떡상 배율 하한
|
|
period-days: ${DISCOVERY_PERIOD_DAYS:14} # 최근 N일 영상 대상
|
|
top-n: ${DISCOVERY_TOP_N:30}
|
|
# 예능 특화 시드 키워드(쉼표구분). 각 키워드×지역으로 Shorts 검색해 예능 클립 소재를 우선 발굴.
|
|
# 빈 값이면 키워드 없는 기존 '지역 인기 Shorts' 발굴로 동작.
|
|
keywords: ${DISCOVERY_KEYWORDS:예능,방송,하이라이트}
|
|
# 발굴 대상 포맷 기본값: LONG_FORM(롱폼) | SHORTS. UI '지금 발굴'에서 건별 선택 가능.
|
|
format: ${DISCOVERY_FORMAT:LONG_FORM}
|
|
|
|
# 소재 발굴 피드: 소스(웹예능 공식채널) 신규 롱폼 + 경쟁(예능짤) 신규 쇼츠를 최신순으로 수집
|
|
feed:
|
|
enabled: ${FEED_ENABLED:true}
|
|
cron: ${FEED_CRON:0 15 */3 * * *} # 3시간마다 (소재 선점은 업로드 후 몇 시간이 승부)
|
|
period-days: ${FEED_PERIOD_DAYS:14} # 이보다 오래된 업로드는 수집하지 않음
|
|
seed:
|
|
max-keywords: ${FEED_SEED_MAX_KEYWORDS:8} # 시드 자동 발굴 시 사용할 상위 해시태그 수(1개당 100 units)
|
|
min-tag-count: ${FEED_SEED_MIN_TAG_COUNT:2} # 이 횟수 미만 해시태그는 프로그램명으로 보지 않음
|
|
|
|
# 텔레그램 아침 추천: 발굴 직후 상위 추천채널 다이제스트를 발송. 토큰/챗ID 없으면 자동 no-op.
|
|
notify:
|
|
telegram:
|
|
bot-token: ${TELEGRAM_BOT_TOKEN:}
|
|
chat-id: ${TELEGRAM_CHAT_ID:}
|
|
morning-digest-top-n: ${TELEGRAM_DIGEST_TOP_N:5}
|