14 Commits
Author SHA1 Message Date
ncakanghanandClaude Opus 5 4be0235d2f 지문을 오디오 우선으로 — 네트워크 소스에서 읽는 양을 크게 줄인다
CI / windows-x64 (push) Canceled after 0s
CI / windows-arm64-cross (push) Canceled after 0s
CI / windows-arm64-native (push) Canceled after 0s
CI / macos (push) Canceled after 0s
26,000편(26TB, SMB) 라이브러리에서 지문 생성이 하루에 10%밖에 진행되지 않았다.
원인은 구조다: 프레임 지문을 만들려고 **파일을 처음부터 끝까지 읽는다**(실측 96.8%).
동시 실행을 2→8로 올려도 차이가 없었다 — 대역 병목이라 읽는 양을 줄이는 것 말고는 방법이 없다.

오디오 지문은 `-vn`으로 영상 청크를 건너뛰어 파일의 일부만 읽는다(컨테이너별 실측):
  mp4 0.4% · mov 0.4% · ts 0.3% · mkv 1.6%   ← 전체 패스 96.8%

그래서 3단계로 나눴다.
- ① 오디오 지문을 전 파일에 먼저 (sig_state=3). 26TB가 아니라 100~400GB를 읽는다.
- ② 저장된 지문으로 후보 쌍을 뽑아 걸린 파일을 표시 (sig_state=4). 파일을 읽지 않는다.
- ③ 프레임은 우선순위대로 — 오디오 짝 있음(4) → 소리 없음(0) → 짝 없음(3).
     중복일 가능성이 높은 것부터 처리하므로 결과가 며칠이 아니라 몇 분 뒤부터 나온다.

후보 판정은 탐지와 같은 함수(candidates_from_tokens)를 쓴다 — 규칙이 갈라지면
"지문 단계에서는 후보였는데 탐지에서는 아니다"는 설명 불가능한 상태가 생긴다.

측정으로 정한 것들:
- 오디오만으로는 그룹이 **0개**다(시각 확인이 프레임을 요구한다). ②③이 없으면 무의미하다.
- 오디오는 배속·피치 변화에 무너진다. 216개 토큰 중 공통:
    워터마크 216 · 레터박스 216 · 재인코딩 211 · 중간자르기 22/59
    1.25배속 3 · 피치+6% 8 · atempo1.05 40/205
  배속 사본은 프레임 경로가 뒤에서 채운다(그쪽에 배속 후보 로직이 있다).
  근거를 tests/audio_speed_evidence.rs에 고정했다.
- 절감 크기는 중복률에 비례한다. 픽스처는 10편 중 8편이 파생 사본이라 20%만 줄지만,
  실제 라이브러리에서 짝이 5%면 26TB가 1.4TB가 된다. 그 비율은 ②가 로그로 알려준다.

함께 고친 것 — 편집 백업이 영구히 쌓이던 문제
- 자르기·반전은 원본을 .archive_trash/edits에 남기는데 지우는 코드가 없었다.
  되돌리기는 최근 배치만 보므로 그 창을 벗어난 백업은 되돌릴 수도 없이 자리만 차지했다.
  미디어 드라이브에 쌓이므로 영상 라이브러리에서는 수십 GB가 된다.
- 창(20배치)을 벗어난 것만 지운다. 앱 시작 시·편집할 때마다·사이드바 버튼으로 돈다.
- 백업이 사라진 배치는 되돌리기 후보에서 뺀다 — Ctrl+Z가 조용히 실패하면 이유를 알 수 없다.
- 사이드바 정리 영역에 「편집 백업 N개 · N MB」로 용량을 노출한다.

빌드: profile.dev에서 의존성 디버그 정보를 뺐다(PDB 200여 개가 시간·디스크를 크게 먹는다).
자체 크레이트는 line-tables-only — 패닉 위치는 그대로 안다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:04:23 +09:00
ncakanghanandClaude Opus 5 8aa74c1a8d 영상 중복 탐지 완성 + 간단 편집(회전·자르기) + 동시 재생 + 별점·태그 세트
CI / windows-x64 (push) Canceled after 0s
CI / windows-arm64-cross (push) Canceled after 0s
CI / windows-arm64-native (push) Canceled after 0s
CI / macos (push) Canceled after 0s
중복 탐지
- 이미지 근접쌍 밴드 색인 + 스트리밍 클러스터, 후보 검증(타일 다수결·크롭 해시)
- 색 지문으로 색만 다른 오탐 제거, 회전·반전본 탐지(8변형 질의, 선택 옵션)
- 오디오 지문(chromaprint)을 같은 디코드 패스에서 뽑아 레터박스 사본을 잡는다.
  배경음만 같은 남남은 시각 확인 패스(트림 축 프레임 거리)로 걸러낸다 — 실측 9 vs 29.
- 비교 재생(CompareView): 여러 사본을 offset 정렬해 나란히 재생
- 지문 생성 속도 조절(느림·보통·빠름) — 재시작 없이 반영

간단 편집 (원본을 직접 고침, Ctrl+Z로 되돌림)
- 회전·반전: JPEG은 EXIF 방향 태그 2바이트만, MP4는 회전 행렬만 — 화질 손실 0.
  방향값 전이표는 군의 성질(90도x4=제자리)로 검산하고, 실제 화소를 transpose=1과
  비교해 "시계 방향"이 정말 시계인지 확인한다.
- 자르기: 화면 좌표 기준(회전 메타가 붙어 있어도 어긋나지 않는다)
- 구간 자르기: 스트림 복사라 무손실. 필름스트립 타임라인 + 손잡이 끌기 + 구간 미리보기.
- 되돌릴 수 없는 편집(자르기·반전)은 원본을 .archive_trash/edits로 옮겨 보관
- 편집이 수정시각을 바꾸지 않는다 — 기본 정렬이 촬영일이라 항목이 튀면 다시 찾아야 한다

동시 재생
- 고른 영상을 최대 9개 격자에 놓고 함께 재생. 소리는 한 칸만.
- 실시간 변환이 필요한 코덱은 2개까지만 — 그 이상은 ffmpeg가 기계를 멈춘다

그 외
- 별점(스냅샷 flags 남는 비트에 얹어 항목당 바이트 증가 0)
- 태그: 검색 없이 클릭으로 붙이기, 세트+단축키, 이름 수정 시 붙은 항목에 전파
- 파일 로깅(tracing-appender) — 릴리스는 콘솔이 없어 stdout만으로는 원인을 못 찾았다
- ARM64 크로스 컴파일 스크립트(관리자 권한 없이 VS 카탈로그에서 조립)
- DB 마이그레이션 v7~v10

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:18:24 +09:00
강 한andClaude Opus 4.8 67d2ddc59e 편의 기능(정렬·종류필터·전체선택/단축키·정보 오버레이) + 스냅샷 범위 안전화
Snapshot 접근자 범위 안전화(핵심 버그):
- id/width/height/kind/hasThumb/thumbFailed가 count 밖 i에서 DataView RangeError를
  던져 Solid 반응성 그래프 전체가 무너지던 문제 수정. 스냅샷이 줄어들 때(필터/검색/
  폴더 전환) For가 초과 셀을 제거하기 전에 셀 접근자가 옛 인덱스로 재실행되며 발생.
  범위 밖이면 0/false 반환. (증상: 필터/검색이 한 번은 되고 이후 먹통)

기능:
- 정렬: 촬영일/이름/크기/수정일 × 오름·내림 (툴바 드롭다운+방향 토글).
  backend snap_tail로 ORDER BY 구성, 4개 스냅샷 커맨드에 sort/kind 파라미터 추가.
- 종류 필터: 전체/사진/영상 툴바 토글 (backend kind 필터).
- 전체 선택(Ctrl+A)/선택 반전(Ctrl+Shift+A), ? 키 단축키 도움말 오버레이.
- 썸네일 정보 오버레이(ⓘ 토글): 가시 셀에 파일명·크기 지연 로드 표시.

검증(사진120+영상25): 종류필터 120/25/145/120 반복 정상, 정렬 순서 변경, Ctrl+A
145개 선택, ? 오버레이, ⓘ로 파일명 표시 확인.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 00:34:52 +09:00
강 한andClaude Fable 5 2072f9f27e 재생바 총길이 안정화 — ffprobe 메타 우선 + 없으면 즉석 ffprobe
증상: 영상 재생 시 재생바가 실시간으로 늘어나며 요동침. 총 재생시간이
고정되지 않음.
원인: durationSec가 직접 모드에서 <video>.duration을 우선 사용했는데, 스트림/
일부 컨테이너(리먹스 fMP4 등)에선 재생 중 요소 duration이 계속 커져 재생바가
current/duration 비율로 요동쳤다. 또 메타(duration_ms)가 아직 추출 안 된 영상은
playback_info가 null을 반환해 요소 duration에 의존.

수정:
- VideoPlayer.durationSec: ffprobe 메타 총길이를 항상 우선, 없을 때만 요소 duration
  폴백. (고정 총길이라 재생바 안정)
- playback_info: 영상인데 duration_ms가 null이면 즉석 ffprobe로 채우고 DB에 캐시
  (SMB 등 메타 미추출 상태에서도 정확한 총길이/코덱 보장, 다음 재생부터 재프로브 없음).

검증(VP9 20s): playback_info durationMs=20000, 재생 중 표시 0:00→ 진행하며 총길이는
0:20 고정, 진행바 0%→4%→8% 단조 증가(요동 없음).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 23:17:28 +09:00
강 한andClaude Fable 5 ffa737be98 재실행 시 백지+응답없음(SMB 소스) 수정 — 시작 시 워처/썸네일백필을 메인 스레드에서 분리
증상: SMB(네트워크) 소스 + 자료 많음 상태에서 재실행하면 창이 백지 + "응답 없음".
원인: setup()가 메인 스레드에서 watcher.refresh()를 동기 호출 → 각 로컬 소스에
debouncer.watch(경로, Recursive)를 등록하는데, 재실행 직후 SMB 공유가 느리거나
재연결 중이면 watch()가 블로킹 → 메인 스레드(이벤트 루프)가 멈춰 창이 안 그려짐.
(처음 열 땐 소스가 없어 no-op이라 정상이었고, 소스 추가는 워커 스레드에서 refresh해
안 멈췄음 — 재실행 때만 메인 스레드에서 SMB를 건드려 멈춤.)

수정: 워처 매니저는 즉시 등록하되 refresh(watch 등록)는 백그라운드 스레드로,
시작 썸네일 백필(enqueue_pending)도 백그라운드로 이동. setup()가 SMB를 동기로
건드리지 않으므로 창이 즉시 렌더되고 응답 유지.

검증(로컬): 소스 있는 상태 재실행 → 창 ~0.7초에 렌더(사이드바+그리드 30셀),
새 파일 추가 시 워처가 3초 내 감지해 재스캔(31셀). 회귀 없음.
(실제 SMB 블로킹은 로컬 재현 불가 — 메인 스레드에서 SMB를 건드리는 유일한 지점을 제거.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 22:05:33 +09:00
강 한andClaude Fable 5 938b3b840e 첫 소스 매핑 체감 속도 개선 — 열거 직후 그리드 표시(메타 대기 안 함)
증상: 파일(특히 영상)이 많으면 첫 소스 추가 시 오래 걸림. 원인은
library-changed(그리드 표시)가 스캔+이미지메타+영상메타를 모두 마친 뒤에야
발생 → 영상마다 ffprobe 프로세스를 띄우는 영상 메타가 끝날 때까지 그리드가 빈 채로.

수정: run_scan_pipeline에 on_refresh 콜백 추가.
- 열거(파일 DB 삽입) 직후 썸네일 생성 시작 + library-changed 발생 → 그리드 즉시 표시
- 이미지 메타(헤더, 빠름) 후 재배치
- 영상 메타(ffprobe, 느림)는 백그라운드 진행, 완료 후 최종 재배치
watcher 재스캔도 동일 적용.

검증(영상 250개): 그리드가 300ms에 표시(메타 250 대기 중), 썸네일은 백그라운드로
채워지고 영상 메타 완료(~6.6s) 후 종횡비 재배치. 기존엔 ~6.6s 내내 빈 화면이었음.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 21:37:45 +09:00
강 한andClaude Fable 5 e95772e79b 시작 시 메타 백필 + 백그라운드 처리 진행 표시(상태바)
- 메타 백필: 이전 스캔이 중단돼 meta_state=0으로 남은 파일을 시작 시
  (전체 재스캔 없이) 저우선순위로 이어서 분석. 썸네일 백필(enqueue_pending)과 짝.
- pending_counts 커맨드 + 상태바 표시: "썸네일 생성 중 N / 메타 분석 중 M".
  thumbs-ready·library-changed·시작 시 트리거하고, 남은 작업이 있으면 2초 폴링,
  0이 되면 자동으로 숨김.

검증: 영상 200개 스캔 중 상태바가 200→0으로 감소 후 사라짐. 메타 도중
강제 종료 후 재실행 시 재스캔 없이(scanning=false) 메타/썸네일 백필만 재개됨.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:18:09 +09:00
강 한andClaude Fable 5 2bb1711ffa 재실행 시 영상 재처리로 인한 멈춤 완화 — ffmpeg/ffprobe 저우선순위 + 백업 하루 1회
증상: 영상이 많은 라이브러리에서 첫 로딩이 오래 걸리고, 다 불러온 뒤
재실행하면 멈춤. 원인은 미완료 영상 썸네일 백로그가 시작 시
enqueue_pending으로 재개되는데, ffmpeg/ffprobe가 '자식 프로세스'라
스레드 저우선순위(이전 수정)를 상속받지 못해 NORMAL로 전 코어를 포화시켜
WebView UI가 멈춘 것. (재실행 시 전체 재스캔은 없음 — 자동스캔은 dev 전용,
워처도 시작 시 스캔 안 함. 재처리는 미완료 썸네일 재개일 뿐.)

- ffmpeg::command(): Windows CREATE_NO_WINDOW에 BELOW_NORMAL_PRIORITY_CLASS 추가,
  Unix는 pre_exec로 setpriority(nice+10). 검증: 스캔 중 ffmpeg/ffprobe
  PriorityClass=BelowNormal 관측(ffmpeg 406, ffprobe 46 샘플).
- 시작 유지보수 스레드도 저우선순위로, DB 백업(VACUUM INTO=전체 복제)은
  24시간 내 백업 있으면 건너뜀 — 대용량 라이브러리 재실행 부하/디스크 낭비 감소.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:05:41 +09:00
강 한andClaude Fable 5 8ba0c24ce8 중복 탐지 범위 선택 추가 — 현재 폴더/소스 또는 전체
기존엔 항상 라이브러리 전체를 대상으로 했다. 이제 중복 검토 패널에서
현재 보고 있는 뷰(폴더=하위 포함 / 소스)로 범위를 좁힐 수 있고,
폴더/소스 뷰에서는 기본값이 '현재 위치'다. 전체/검색/태그/스마트 뷰는
전체 라이브러리로 고정.

- dedupe::Scope { All | Source | Folder{recursive} } 도입, load_files/run에 적용
  (folder_snapshot과 동일한 경로 프리픽스 스코핑)
- start_dedupe에 folder_id/recursive 파라미터 추가
- DedupePanel: view() 기반 범위 세그먼트 컨트롤
- 테스트: folder_scope_restricts_detection (folderA=1그룹, 전체=2그룹, 누출 없음)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:57:40 +09:00
강 한andClaude Fable 5 df2bb5dc8b 그리드에 썸네일 '생성 중' 스켈레톤 표시
썸네일 미준비 셀이 빈 칸으로 보이던 것을 개선. 스냅샷 flags에
비트1(생성 실패, thumb_state=2)을 추가해 대기/실패를 구분한다.
- 대기(생성 전): 은은한 pulse 스켈레톤(bg-hover)
- 실패: 정적 아이콘(🖼) — 무한 pulse 방지
- 준비됨: 썸네일 이미지

검증: 619개 대기 상태에서 하단 스크롤 시 pulse 스켈레톤 50개 →
생성 완료되며 이미지로 즉시 전환 확인(bg #33363d, animation pulse).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:33:13 +09:00
강 한andClaude Fable 5 31a0487419 폴더 추가 시 UI 멈춤 수정 — 백그라운드 워커 저우선순위 + JPEG DCT 축소 디코드
원인: 실사진(수십 MP) 스캔 시 메타 추출(rayon)과 썸네일 워커가
NORMAL 우선순위로 전 코어를 포화시켜 WebView UI 스레드를 굶김.
풀해상도 JPEG 디코드는 파일당 ~72MB를 할당해 병렬 시 메모리 대역폭까지 포화.

- prio 모듈: 현재 스레드 우선순위 낮추기(Win BELOW_NORMAL / macOS nice+5),
  메타 전용 저우선순위 rayon 풀(코어-1, 전역 풀과 분리)
- 썸네일 워커 스레드·스캔 스레드를 저우선순위로 → CPU 포화 시 UI 우선 스케줄
- meta 이미지/영상 추출을 저우선순위 풀에서 실행
- JPEG는 jpeg-decoder DCT 축소 디코드(1/8 등) 사용:
  24MP 기준 풀디코드 63ms/72MB → 축소 38ms/1MB (1.7배·메모리 ~70배 절감),
  RGB24/L8만 처리하고 그 외(CMYK)는 기존 경로로 폴백

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:19:18 +09:00
강 한andClaude Opus 4.8 b4b1ef3241 소스 제외(인덱스에서 제거) 기능 추가
- 사이드바 소스 행 hover 시 ✕ 버튼 → 확인 후 인덱스/폴더/태그/썸네일
  캐시 제거. 디스크의 실제 파일은 삭제하지 않음.
- 로컬: 파일 워처 해제. 원격: 연결 해제 + 자격증명(키체인/볼트) 삭제.
- maintenance::remove_source (defer_foreign_keys로 자기참조 FK 처리),
  스캔 중 제외 방지, 제외한 소스를 보던 중이면 전체 뷰로 전환.

Rust 테스트: 실제 파일 보존 + 인덱스/썸네일 제거 검증 통과.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 13:41:15 +09:00
강 한andClaude Opus 4.8 5a7952bd2d 후속 개선: 원격 썸네일·자동재연결, RAW 썸네일, 마퀴 선택, 이동 강건성
P1 원격 소스 UX:
- remote_thumbs: VFS 다운로드로 원격 썸네일 생성(이미지 EXIF 내장 우선,
  영상은 미디어서버 bridge URL로 ffmpeg Range 추출)
- 앱 시작 시 키체인 자격증명으로 원격 소스 자동 재연결
- fileops: physical_move에 Windows 공유위반 재시도

P3 그리드/포맷:
- RAW(cr2/nef/arw/dng 등) 내장 JPEG 프리뷰 추출 썸네일(scan_largest_jpeg)
- 그리드 마퀴(드래그 사각형) 다중선택
- .gitattributes 줄바꿈 정규화

Rust 테스트 51개 통과.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:10:53 +09:00
강 한andClaude Opus 4.8 394d1b9805 Archive v0.1.0 — 사진/영상 라이브러리 관리 프로그램
Tauri v2 + SolidJS + SQLite + ffmpeg 사이드카로 구현한 크로스플랫폼
사진·영상 관리 앱. 로컬/NAS(SFTP·WebDAV·FTP) 소스, 가상 그리드,
인앱 재생, 태그/이동/삭제/undo, 중복 탐지, 포터블 배포.

- archive-db: SQLite 스키마·마이그레이션·단일 writer 스레드 + FTS5 trigram
- archive-vfs: VFS 4백엔드(local/sftp/ftp/webdav) + 자격증명(키체인/볼트)
- archive-indexer: 스캔·해시·썸네일·중복탐지·태그·파일작업·유지보수
- archive-media: localhost HTTP 미디어 서버(Range) + ffmpeg 스트림 잡
- 프론트: 3-pane UI, justified 가상 그리드, 라이트박스, 중복 검토 패널

Rust 테스트 49개 통과. CI: win x64/arm64 포터블 zip + macOS universal dmg.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:04:06 +09:00