crowny-class 강의 재생 mp4 복구 (CVF → <video> 하이브리드)
개요
CVF 1080p가 실측상 실용불가(원본보다 큰 팽창·134배·인코딩 9~10시간)로 판정되어, 사장님 규칙 "안되면 MP4"에 따라 class.crowny.org 강의 재생을 mp4
<video> 태그로 복구했다. CVF 파이프라인(encode-upload.sh·handleCvf·handleCvfAudio)은 삭제하지 않고 아카이브/관리자용으로 유지(하이브리드).
무엇을 했는지
/Users/ef/crowny-class/public/class.html의 강의 재생부를 CVF 캔버스 디코더+오디오 사이드카에서
<video id="player" controls playsinline preload="metadata"> 단일 재생경로로 되돌렸다.
CSS: .cvf-stage/.cvf-controls/.cvf-play-btn/.cvf-seek/.cvf-time 전부 제거 → .video-wrap video{width:100%;aspect-ratio:16/9;...} 2줄로 축소.
HTML: canvas+오디오 태그 블록(9줄) → <video id="player"> 1줄.
JS: CVFDecoder IIFE(트릿→RGB 파서, ~210줄) + cvfPlayer 컨트롤러(재생/시크/스케줄, ~160줄) 전량 삭제. 대신:
videoStreamUrl(videoId) — owner()가 있으면(로그인·유료) ?owner= 쿼리 동봉, 무로그인 체험은 미동봉(free 레슨만 서버가 통과).
loadVideo(videoId) — player.src = videoStreamUrl(videoId); player.load();
resetVideo() — pause+src 제거+load().
진도추적: player.addEventListener('timeupdate', ...) / ('ended', ...) → throttledProgress(force)가 로그인시 POST /api/video/progress {videoId, seconds:floor(player.currentTime), done}. 체험(무로그인)은 state.trial이면 스킵(회귀 없음).
파일 라인 수 948 → 587 (CVF 코드 361줄 순삭제).회귀 유지 확인
- 55분 작업 타이머(startTick/renderTimer) 그대로.
- 무로그인 잠긴 레슨 미리보기(showLessonPreview, 목표 전문+가이드 40자 절단+영상 잠금 플레이스홀더) + 회원가입 CTA 그대로.
- week 0 오리엔테이션 그룹(
w === 0 ? '오리엔테이션 — 무료 3강 포함') 그대로.
<link rel="stylesheet" href="/assets/class-type.css"> 그대로.
- 무료 3클립 무로그인 재생:
loadLessonTrial에서 loadVideo(lesson.videoId) 호출 — owner 없어도 videoStreamUrl이 쿼리 생략, free 영상이라 서버 페이월 통과.
페이월 불변식 재확인
/api/video/stream/<id>는 API-CONTRACT.md 기준 student 권한(owner 쿼리/헤더) 필요 — meta.free!==true면 인증 필요. mp4 실파일은
데이터/영상/파일/<id>.mp4로 PUBLIC 서빙 루트 밖에 있어 정적서빙 직접도달 불가, 스트림 라우트 경유만 가능 — CVF와 동일 게이트 유지.
검증
- 태그 짝 검사(div/video/html/head/body/script/style) — 전부 OK (video 1open/1close, 리포트상 mismatch는 JS 주석 안의 "<video>" 문자열 오탐).
node --check로 임베드 script 블록 추출 후 문법 검사 — OK.
curl -s -o /dev/null -w "%{http_code}" localhost:9864/class.html → 200, 응답 본문에 id="player" 확인. 서버 재기동 안 함(라이브 static 파일 즉시 반영).
관련 파일
/Users/ef/crowny-class/public/class.html (수정)
/Users/ef/crowny-class/API-CONTRACT.md (참조, 미수정)
- 백업:
/tmp/class.html.bak (패치 전 원본)
- 패치 스크립트(스크래치패드, 일회성):
patch_class_html.py + 한선씨 동반 patch_class_html.한선(줄범위치환 핵심로직, 컴파일+검증 PASS) — /private/tmp/claude-501/-Users-ef/f9b12166-e530-4008-96c1-e83df68283e2/scratchpad/
잔여 이슈
- CVF 파이프라인 자체(encode-upload.sh, server.js handleCvf/handleCvfAudio)는 이번 작업에서 손대지 않음 — 아카이브/관리자용으로 그대로 살아있음, 필요시 별도 점검.
- mp4 스트리밍은 API-CONTRACT.md상 HTTP Range 206 지원이 전제(서버측, video 모듈 소유) — 이번 작업은 프론트 재생 경로만 다뤘고 서버 stream 라우트 자체는 미수정(이미 구현되어 있다는 계약 전제).