If user changed the URL while a probe was in flight, the late response
for the old URL would still set lastProbedUrl and enable the start
button, breaking the "확인 전 가져오기 차단" UI invariant.
Drop the response (and the catch path, and the post-confirm path) when
the current input no longer matches the probed URL.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Review P2: probe 성공 후 사용자가 URL 입력값을 다른 URL 로 바꿔도 "확인"
버튼이 여전히 활성화 상태였습니다. 그래서 A 로 probe → B 로 수정 → 확인을
누르면 B 가 probe 없이 바로 다운로드 시작됐습니다.
수정:
- `lastProbedUrl` 로 마지막으로 probe 통과한 URL 기록.
- ytUrl 의 input 이벤트에서 현재 값이 lastProbedUrl 과 다르면
ytStartBtn 을 disable 로 되돌리고 ytProbeBtn 을 다시 활성화.
- ytStartBtn 클릭 핸들러에도 가드 추가: 클릭 시점에 URL ≠ lastProbedUrl
이면 안내 메시지와 함께 차단 (race condition 대비).
이제 "확인 누르기 전 가져오기 못 누르게" 요구사항이 어느 순서로 입력이
들어와도 만족됩니다.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
세 가지 사용자 보고 처리:
1) 다운로드 바가 멈춰 있다가 한번에 50% 로 점프
- 원인: yt-dlp 는 파이썬 스크립트라 stdout 이 pipe 로 연결되면
block-buffered 가 되어 진행률 라인들이 4KB 버퍼에 모였다가 종료 직전에
쏟아짐. node 의 stdout 'data' 핸들러가 그 전엔 아무 것도 못 봄.
- 수정: spawn 의 env 에 PYTHONUNBUFFERED=1 추가. 라인 단위로 즉시 flush.
2) 변환을 20배 빠르게
- 원인: minterpolate(mci) 는 motion estimation 자체가 무거워 mci 기본값
이어도 영상 길이의 수 배 시간이 든다 (blend 도 5~10배가 한계).
- 수정: 다운로드 후 60fps 변환과 trim 재인코딩 양쪽에서 minterpolate 를
`fps=60` (단순 프레임 복제) 으로 교체. preset 도 `veryfast` → `ultrafast`.
실측상 영상 길이의 1/3 ~ 1배 시간 — mci 대비 수십 배 빠름.
- 시각적 부드러움은 30fps 와 동일하지만 컨테이너/타이밍은 60fps cfr 로 유지.
사용자가 알려준 "timing 만 60fps 로 바뀌고 실제 부드러움은 그대로" 경로.
3) "확인" 전 "가져오기" 재클릭 막기
- probe 클릭 시 ytProbeBtn 도 disabled.
- probe 실패 / 5분 경고 취소 / start 실패 시만 재활성화.
- 정상 흐름은 probe 성공 → 확인 클릭 → 다운로드 → redirect 라 재활성화
필요 없음. ytStartBtn 도 클릭 직후 disabled 로 중복 클릭 방지.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Review P1: 진행률 폴링이 304 응답을 받으면 r.json() 이 reject 되는데
.catch() 가 없어 setTimeout 도 안 걸리고 폴링이 영구 중단됐습니다.
이게 "60fps 변환 확인 중" 에서 바가 멈춰 보이던 진짜 원인이었어요.
세 곳을 다 고침:
1) src/routes/op.ts `/op/job/:id`
- `Cache-Control: no-store, no-cache, must-revalidate` + `Pragma: no-cache`
- 브라우저가 conditional GET 으로 304 를 받지 않게 한다.
2) public/editor.js fetch
- `{ cache: 'no-store' }` 옵션. 서버 헤더 + 클라 옵션 둘 다.
3) public/editor.js pollJob
- `.catch()` 추가. 일시적 네트워크/파싱 오류여도 2 초 백오프로
폴링을 재개한다. 변환이 오래 걸려도 바가 계속 갱신됨을 보장.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
비디오의 src 가 HTML 인라인이라 loadedmetadata 가 스크립트 실행보다
먼저 끝나는 경우, 늦게 붙은 리스너가 영원히 못 받아 duration=0 으로
멈춰있던 문제 수정. readyState 즉시 검사 + durationchange 도 같이
구독하도록 변경.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
영상편집기에 lossless-cut 류 트림 타임라인 추가. 숫자 입력만 있던 기존 UI 를
시각적 재생바 + 좌/우 드래그 핸들 + 플레이헤드로 교체.
- 좌/우 파란 핸들을 끌어 in/out 점 설정 (pointer events 기반, 터치 지원)
- 흰색 플레이헤드가 영상 재생 위치 따라감
- 타임라인 빈 공간 클릭 → 그 지점으로 시킹
- "[ 시작점" / "끝점 ]" 버튼으로 현재 시점 마크
- "선택 재생" 으로 선택구간만 미리보기, "초기화" 로 전체 선택 복원
- 기존 숫자 입력은 보조 입력으로 유지하고 상태와 양방향 동기화
저장 페이로드는 그대로 (startSec/endSec). 서버측 ffmpeg 트림 로직 변경 없음.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>