← 목록
기타 2026-07-12 5KB 읽기 6분

crowny-class class.html — mp4 video → CVF 캔버스 디코더+오디오 사이드카 (임무 2b)

개요

class.crowny.org 교실 페이지(public/class.html)의 강의 재생을 <video> mp4 스트리밍에서 CVF(크라우니 비디오 포맷) 캔버스 디코더 + 오디오 사이드카 동기 재생으로 교체(CVF 단일화). 정본 포팅 소스: /Users/ef/crowny-video/server.jsCVFDecoder(parse/renderFrame)와 openPlayer/오디오 마스터클럭 동기 로직(scheduleFrame — audio.currentTimefps → frameIdx).

무엇을 했는지

  • <video id="player" controls playsinline><div class="cvf-stage"><canvas id="cvfCanvas"> +
.cvf-controls(재생버튼/시크바/시간라벨) + 숨김 <audio id="cvfAudio">로 교체.
  • CVFDecoder(parse/renderFrame, 트릿→RGB·광좌표 씨앗·모션시드·레거시 27×27 모자이크)를
정본에서 ES5 스타일로 포팅. ★함정 회피: 정본은 서버 템플릿 리터럴 안이라 개행이 \n (이중 이스케이프)로 박혀있음 — class.html은 순수 정적파일이므로 실제 \n(단일 백슬래시, 런타임엔 LF 1글자) 이스케이프로 옮김. 그대로 복붙했으면 파싱이 깨졌을 부분.
  • cvfPlayer 컨트롤러 추가: cvfLoad(videoId, isFree)(fetch arrayBuffer→parse, 오디오 src
세팅), cvfRenderFrame/cvfRenderUpTo(P/Motion 프레임 이전 캔버스 위에 델타 페인트, 키프레임 재계산), cvfScheduleFrame(rAF 루프 — 오디오 currentTime
fps로 frameIdx 구동, 순방향 1프레임은 빠른경로/드리프트·역방향·스킵은 최근 I프레임부터 재계산), cvfPlay/cvfPause/cvfToggle/cvfSeekTo.
  • 인증: fetch(캔버스용)는 ?owner= 쿼리(로그인 시)로 CVF 바이너리 요청, free 레슨은 쿼리 생략.
<audio> 태그는 커스텀 헤더를 못 실으므로 오디오도 동일하게 ?owner= 쿼리로 통일.
  • 진도 저장: cvfPlayer.audiotimeupdate 이벤트에 상시 바인딩된 throttledProgress()
state.trial이면 스킵(체험 모드), 아니면 5초 스로틀로 POST /api/video/progress {videoId, seconds:floor(audio.currentTime), done} 전송 — 오디오 기준으로 정정.
  • resetLessonView/showLessonPreviewcvfReset() 추가 — 레슨 전환/잠금 미리보기 전환 시
재생 중인 오디오를 확실히 정지(기존 mp4 버전에 없던 방어 강화, 나머지 로직은 무회귀).
  • 회귀 금지 항목 확인: <link href="/assets/class-type.css"> 유지, week0 falsy 수정
(Number(l.week); isNaN→1) 그대로 보존, 잠긴 레슨 미리보기(showLessonPreview)·"회원가입" CTA 로직 손대지 않음(HTML/문구 불변, cvfReset() 방어 호출만 추가).
  • CSS 사이드이펙트 수정: .video-wrap{aspect-ratio:16/9}를 제거(컨트롤바 추가로 고정비율이면
overflow:hidden에 컨트롤바가 잘림) 하면서, 같은 .video-wrap 클래스를 재사용하던 잠긴레슨 미리보기 박스(#pVideoWrap, .video-wrap.preview-video)가 16:9 비율을 잃는 회귀를 발견 → .preview-videoaspect-ratio:16/9를 직접 부여해 원복.

한선씨 동반

/Users/ef/crowny-class/한선씨/프론트카피.한선 끝에 append (기존 섹션 불변 — 2a/2c 작업과 공유 파일이라 append-only로 협업):
  • 프레임인덱스계산(오디오초, fps, 총프레임수) — 내림(오디오초×fps), [0,총프레임수-1] 클램프.
  • 프레임갱신방식(현재인덱스, 목표인덱스) — 유지/빠른경로(+1)/재계산(그외) 3분기.
  • cvf재생상태(...) — 위 둘을 합쳐 idx=N 방식=X 문자열 반환. class.html의
cvfScheduleFrame targetIdx 분기와 동일 규칙.
  • 컴파일: `cd /Users/ef/CrownyOS/crownyc && ./hanseonc_high 프론트카피.한선 > /tmp/frontcopy.toau
&& ./crownyc run /tmp/frontcopy.toau` — exit 0, 4개 검증 케이스(순방향/탐색점프/되감기/ 끝단클램프) 전부 기대값과 일치 확인.
  • crownycode-learn.sh add "CVF재생상태오디오마스터클럭프레임판정" "..." 학습 완료.

검증

  • HTML 태그 짝 검사(스크립트/스타일 내용 제외 파싱): OK.
  • 내장 <script> 추출 후 node --check: OK (30KB대).
  • curl http://127.0.0.1:9864/class.html: HTTP 200, CVF 마커(cvfCanvas/cvfAudio/CVFDecoder/
cvfPlayer) 71건 검출, 구 id="player" 잔존 0건.
  • 크라우니코드: lookup MISS 1건("cvf재생상태" 신규) / MISS 후 직접생성 → learn 추가 1건.

관련 파일

  • /Users/ef/crowny-class/public/class.html (수정)
  • /Users/ef/crowny-class/한선씨/프론트카피.한선 (append)
  • 참고 정본: /Users/ef/crowny-video/server.js (읽기 전용, 미수정)
  • API 계약: /Users/ef/crowny-class/API-CONTRACT.md

잔여 이슈

  • 백엔드 /api/video/cvf/<id>, /api/video/cvfaudio/<id> 엔드포인트, /api/video/stream/<id>
410 Gone 전환은 이 세션(2b) 범위 밖 — modules/video/routes.js는 미수정 확인 (작업 시작 시점 mtime 00:21, CVF 라우트 부재). 별도 세션(2a)이 배선해야 실동작. 현재 class.html은 계약대로 해당 엔드포인트를 호출하도록만 작성됨(스펙 선반영, 백엔드 대기).
  • 디자인대조.sh(CrownyBrowser 탭바/omnibox 규격) FAIL은 class.html이 브라우저 크롬 UI가
아니라서 발생하는 무관 항목(.tabbar/.omni/.bm/.ib 등 요소 자체가 없음) — 이 페이지 타입에는 적용 대상이 아님, 가짜 장식 요소를 끼워넣지 않음.