Commit Graph

14 Commits

Author SHA1 Message Date
Claude (owner)
0faf7af42a feat(playlist): show thumbnails in import preview
플레이리스트 가져오기 미리보기 목록에 각 항목 썸네일을 표시한다.
YouTube video id 로 mqdefault 썸네일 URL 을 만들고, id 가 없으면
yt-dlp 가 준 thumbnail 필드로 폴백. 깨진 이미지는 빈 박스 처리.

- youtube.ts: PlaylistEntry 에 thumbnailUrl 추가 + flat-playlist 파싱에서 채움
- playlist.js: probe 매핑에 thumbnailUrl 반영, 각 행에 img 렌더(lazy + onerror)
- styles.css: 행 그리드에 썸네일 칼럼(96px 16:9) 추가

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-01 22:52:05 +09:00
Claude (owner)
0e39836c1f feat(folders): allow videos in top-level folders too
1단계 폴더에도 영상을 직접 추가할 수 있게 한다 (하위 폴더와 혼합 가능).
플레이리스트 추가는 기존대로 2단계 폴더 한정.

- op.ts: editor/upload/youtube start 의 parentId===null 차단 제거
  (playlist probe/start/new 차단은 유지)
- op/folder.ejs: 1단계에서 "하위 폴더 추가"+"영상 추가" 동시 노출,
  서브폴더 그리드와 영상 그리드를 함께 표시
- folder.ejs(public): 1단계에서 하위 폴더 + 영상 함께 표시
- README: 폴더 구조/버튼 설명 갱신

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-01 22:12:37 +09:00
Claude (owner)
6eac31401a docs(readme): fix two remaining mismatches with implementation
리뷰어 P2 잔여 2건 반영:
- URL 규칙의 1단계 폴더 설명을 "서브폴더 + 영상 혼합" → "하위 폴더만
  표시" 로 정정. 같은 문서 안 폴더 화면 스펙(73-75)과 일관되게 맞춤.
- 관리자 페이지 우클릭 메뉴에 적혀 있던 "영상-허용 토글" 제거. 실제
  dashboard.js 컨텍스트 메뉴는 이름 변경 / 삭제만 존재하고 DB 에도
  폴더별 영상 허용 필드가 없음.

코드 변경 없음. `npm run build` 통과.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:51:51 +09:00
Claude (owner)
90e227d857 docs(readme): align with actual implementation
리뷰어 P2 지적 3건 반영:
- 데이터 위치: `data/videos/<videoId>/` 라는 잘못된 경로를 실제 구조
  `data/folders/<topName>[/<subName>]/<videoId>/` 로 교정. `data/jobs`,
  `data/tmp` 도 추가. "폴더 이름 바꿔도 파일 이동 없음" 문장은 실제로는
  rename 동작이 일어나므로 삭제.
- 공개 폴더 화면 설명: 1단계가 "서브폴더 + 영상 혼합" 이라고 적혀
  있었지만, views/folder.ejs 구현은 1단계=하위폴더만 / 2단계=영상만 으로
  분리됨. 두 단계별 렌더링을 정확히 기술.
- 관리자 폴더: "영상 카드 드래그 정렬" 항목은 plain admin folder 뷰에
  없으므로 제거. 드래그 정렬은 플레이리스트 임포트 화면 한정임을 명시.
- 랜덤 ID 형식: "8자 base32" → 실제 public/playlist.js 의 24자 hex
  (crypto.randomUUID 압축) 로 정정. 시퀀셜 zero-pad 동작도 보강 설명.

코드 변경 없음. `npm run build` 통과.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:50:05 +09:00
Claude (owner)
5693e1c6b0 refactor: dedupe encoder retry + collectFolderSegments + 3-probe → 1
simplify skill 결과 정리:
- editor.ts: HW→libx264 잡 폴백 패턴을 encodeWithFallback() 한 곳으로
  모으고 upscale/trim 양쪽에서 호출. 진행률 무전송 변형은 runner 인자로 분기.
- editor.ts: upscaleOriginalTo60Fps 가 fps/해상도/길이를 위해 spawnSync
  ffprobe 를 3번 돌리던 것을 probeVideoMeta() 한 번 호출로 통합. 핫패스에서
  이벤트 루프 블로킹을 줄임. 이제 미사용이 된 probeVideoResolution/
  probeVideoDuration 은 제거.
- routes/helpers.ts: op.ts/public.ts 양쪽에 동일하게 있던
  collectFolderSegments 를 공용 모듈로 추출.
- youtube.ts: probeYoutube/probeYoutubePlaylist 의 stderr 누적을
  runFfmpeg 와 동일하게 마지막 2KB 만 유지하도록 캡.

README.md 도 5/31 STEP 1~5 (중첩 폴더 + 영상 ID 편집 + 플레이리스트
임포트 + 짧은 공유 URL) 과 5/16 묶음(부드러운 진행바 + 60fps/FHD 캡 +
HW 인코더 자동 감지) 까지 반영해 전반 갱신.

`npm run build` 통과.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:44:29 +09:00
25a809546e fix(setup): tolerate yt-dlp execve ENOENT on slim docker bases
문제: alpine/distroless 처럼 glibc 가 없는 도커 베이스 이미지에서는 PyInstaller
로 빌드된 yt-dlp_linux 의 동적 링커가 없어 execve 가 ENOENT 를 반환. 이전에는
npm run setup 이 통째로 실패해서 Docker 빌드를 차단했음.

수정:
- 다운로드는 됐지만 --version 검증이 실패하면 throw 하지 않고 안내만 출력 후
  계속 진행. 못 쓰는 바이너리는 unlink 해서 혼동 방지.
- SKIP_YT_DLP=1 환경변수로 다운로드 자체를 건너뛸 수 있게 추가.
- 도커/PATH 설치 가이드를 warn 으로 같이 노출 (apt/apk/pip 명령).
- README 외부 의존 섹션에도 slim base / SKIP_YT_DLP 안내 추가.

src/youtube.ts 의 PATH fallback 은 그대로라 시스템에 yt-dlp 가 설치돼 있으면
런타임에 자동으로 그것을 사용합니다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 19:00:43 +09:00
aae58f645a fix: harden UPLOAD_MAX_BYTES parsing; sync docs with 1 GiB default
리뷰어 지적사항 반영:
- "abc" 같은 오타도 Infinity 로 풀리던 문제 수정. 잘못된 값은 기본 1 GiB 로
  fallback 하고 경고 로그를 남김. 무제한은 "0" 또는 "Infinity" 만 명시적으로 인정.
- .env.example / README 의 "비우면 무제한" 표현을 코드 동작과 일치시켜
  "비우면 기본 1 GiB" 로 정정.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 18:10:27 +09:00
a14963e237 feat: cap upload size at 1 GiB by default (UPLOAD_MAX_BYTES override)
기본 업로드 한도를 1 GiB (1073741824 바이트) 로 설정. .env 의 UPLOAD_MAX_BYTES 로
바꿀 수 있고, 0 이나 Infinity 로 두면 무제한.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 18:06:21 +09:00
8de8bb982a chore: drop Docker scaffolding (Dockerfile/compose/.dockerignore)
도커는 사용자가 따로 만들어 쓸 예정이라 레포에서 제거합니다. README/.env.example
의 Docker 관련 안내도 같이 정리. .env 기반 PORT/HOST 설정은 직접 실행용으로 유지.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 17:57:45 +09:00
e4e697d287 feat: Docker support + .env-driven PORT/HOST config
직접 실행과 Docker compose 가 같은 .env 한 파일로 PORT/HOST/SESSION_SECRET 등을
공유합니다. 컨테이너는 node:22-bookworm-slim 기반에 ffmpeg + 번들된 yt-dlp 포함,
data 볼륨 마운트로 영속화합니다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 17:39:23 +09:00
cb9406d88e feat: npm run setup (yt-dlp + deps + build); lift upload size limit
scripts/setup.mjs runs `npm install`, downloads the platform-specific
yt-dlp binary from GitHub releases to ./bin/yt-dlp (which src/youtube.ts
already prefers), checks for ffmpeg and prints install hints, then runs
`tsc`. One command replaces three for fresh checkouts.

While verifying setup, hit `MulterError: File too large` (LIMIT_FILE_SIZE)
on a 10 GB mkv upload, and ETXTBSY on freshly downloaded yt-dlp.

- ETXTBSY: the redirect path in downloadFile opened a writestream to the
  destination before following the redirect, so the (unused) outer stream
  still held the file open when the post-download spawnSync ran. Split
  redirect-following from file writing so only the final 200 response
  opens the destination file.
- LIMIT_FILE_SIZE: removed the hard-coded 4 GB cap. Upload limit now
  defaults to Infinity and is configurable via UPLOAD_MAX_BYTES.
  Wrapped multer's middleware so its errors (LIMIT_FILE_SIZE etc.) come
  back as a clean 413 JSON instead of a stack trace from the global
  error handler.
- Also disabled Node's default 5 minute requestTimeout so 10 GB uploads
  over slow links don't get cut mid-stream. Configurable via
  HTTP_REQUEST_TIMEOUT_MS.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 17:13:47 +09:00
0db04cf5cd feat: implement video site per README spec
- Express + EJS + express-session stack (auth/navbar ported from minecraft_launcher)
- Public: main folder list, folder video grid, internal popup player (/player/:videoId)
- Admin (/op): login, folder CRUD with right-click context menu + add-folder modal
- Admin folder: video grid with right-click edit/rename/delete, "영상 추가" -> editor
- Video editor: drag-drop upload, file picker, YouTube URL probe (ETA + 5분 경고),
  background yt-dlp download with progress polling, navbar title edit, trim controls,
  save runs ffmpeg trim (original preserved)
- Filesystem storage under data/folders/<name>/<videoId>/{meta.json, original.<ext>, edited.<ext>}

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 16:42:00 +09:00
8d13d155de docs: expand README with project spec 2026-05-15 15:45:14 +09:00
claude
b6a27c8128 docs: add README with project title 2026-05-15 15:23:24 +09:00