11 KiB
Find-Word v0.2.5 독립 리뷰 수정 결과
2026-10-14 UTC · /home/hermes/worktrees/find-word-v0.2.5 · fix/v0.2.5-ambience-loudness.
HEAD 812540c7438639f25b886cfd620201d92de15362 유지. commit/push/merge/tag/deploy 미실행.
릴리스 판정: 차단
정규화 결함은 strict TDD로 수정했다. 전용 **FFmpeg ebur128=peak=true**가 릴리스 수용 계기이며,
8개 exact 최종 WAV 모두 −32.5 LUFS, spread 0.0 LU, 최대 true peak −6.2 dBTP다.
독립 pyloudnorm 0.2.0 / soundfile 0.13.1도 −32.6062~−32.5291 LUFS, spread 0.0771547792 LU로
목표 ±0.2 LU / spread≤0.4 LU를 통과했다. loudnorm input_i를 수용 계기로 사용하는 주장은 철회했다.
그러나 같은 faster-whisper/VAD 설정으로 새 바이트를 검사했을 때 market 1개 segment가 반환되었다.
requiredEmptyPassed=false이므로 릴리스를 중단한다. npm test도 143 통과 / 1 실패이며,
실패하는 테스트는 새 exact-WAV ASR 결과에 requiredEmptyPassed=true를 요구한다. 조건을 면제하지 않았다.
- exact market WAV SHA-256:
7178307c48c192ac396dcd3c880c377bf56b45e829b459b1feca9f986437e632 - 보존한 원본 구간: 24–36초. ASR 반환 구간: 10.45–12.45초. 반환 끝 시각도 수정하지 않았다.
- 후보 텍스트:
Let's go, let's go, let's go.(검증된 전사가 아님) - mall/cafe 및 다른 5개는 segment 0개. market을 포함한 필수 3개 전부 empty 조건은 미충족.
- 실패 원문, 실행 로그, 현재 unit 실패.
설정/threshold/모델/선택 구간을 바꾸거나 반환 segment를 삭제하지 않았다.
humanListeningAcceptance=false, legalPrivacyClearance=false다. 이전 Oz 승인은 당시 v0.2.3 exact WAV에 한정된다.
ASR의 후보 텍스트가 실제 발화를 입증한다고 주장하지 않으며, 이를 이유로 필수 gate를 면제하지도 않는다.
거부된 역사와 불변 보존
독립 리뷰 결과를 적용했다. 이전 loudnorm input_i는 spread 0.01 LU를 보고했지만 같은 WAV의 전용 FFmpeg ebur128은 2.0 LU, 별도 pyloudnorm 0.2.0은 1.925 LU였다. 당시 정규화 결과는 릴리스 조건 실패다. 계기 차이를 진단값으로만 분류하고 ebur128 equality assertion을 제거한 판단은 철회했다.
이전 RESULT 사본,
당시 bundle,
당시 정규화 계획을 별도 보관했다.
기존 .agent/evidence-v0.2.5 150개 파일은 전부 byte 동일하며 새 증거는 review-fixes/에만 추가했다.
상위 evidence의 GREEN/완료 표시는 거부된 당시 기준의 역사이며 현재 릴리스 통과를 뜻하지 않는다.
기존 불변 파일 660개, voice WAV 101개, source 8개의 hash/bytes와 원본 선택 구간·creator·license·attribution을
보존했다. source plan hash는 3529c8534be204208ac504a0f4c1a69b312131f9bbff92aa9a3135d61d24db65다.
history hash 목록,
보존 검증 결과.
구현과 manifest
- 불변 source plan으로 모든 원본 SHA-256/bytes를 먼저 검증한다. 기존 seek 및 짧은 Ogg의 full decode/sample trim fallback, 12초/24kHz/mono와 양끝 50ms 선형 fade를 보존한다.
- 정확한 faded f32 PCM을 새
ebur128=peak=true프로세스로 측정한다. - 모든 환경의 공통 target −32.5 LUFS에서
gain_db=target−measured_i를 구한다. market의 입력 I=−26.4 LUFS, TP=−0.1 dBTP이므로 gain=−6.1 dB로 파형을 보존하며 내부 ceiling에 맞춘다. - 입력 true peak+gain이 −6.2 dBTP를 넘으면 변환 전에 실패한다.
volume=<gain_db>dB:precision=double만 적용하고 FFmpegpcm_s16le로 인코딩한다. - staged WAV를 새 ebur128 프로세스로 측정한다. 오차가 ±0.2 LU 밖일 때만 같은 원본 PCM에서 스칼라를 보정한다. 매번 peak를 사전 검사하며 최대 총 3회다. 비수렴/NaN/측정 실패/내부 peak 초과는 공개를 차단한다.
- staging의 8 WAV·manifest·notice 전체를 검증하고 새 ebur128 측정으로 bundle spread≤0.4 LU 및
각 파일 target±0.2 LU/TP≤−6 dBTP를 강제한 뒤 단일
renameat2(RENAME_EXCHANGE)로 원자 교환한다.
이번 8개는 모두 첫 시도에 통과하여 보정 반복은 필요하지 않았다. 모든 sample에 동일 scalar만 적용하고 PCM16 반올림 오차만 남는다는 실제 FFmpeg fixture 검사, corrective gain/비수렴/peak 초과 검사가 있다. 실패하면 기존 공개 디렉터리를 보존하는 검증/쓰기/교환/중단 테스트도 유지했다.
manifest는 입력 ebur128 통계, faded PCM hash, 각 iteration의 정확한 gain/filter, 예측 peak/출력 통계, 최종 ebur128 통계, 목표/허용오차/spread/내부·릴리스 ceiling/최대 반복 수와 FFmpeg 6.1.1-3ubuntu5 버전을 기록한다. 정규화 계획도 같은 계약이다. 12초, 288,000 frames, mono 24kHz PCM16, 576,044 bytes와 고유 hash/non-silence/양끝 0을 유지한다.
| 환경 | 원본 시작 초 | gain dB | 최종 ebur128 LUFS | 최종 dBTP |
|---|---|---|---|---|
| street | 35 | +3.2 | −32.5 | −10.2 |
| mall | 36 | −10.4 | −32.5 | −12.2 |
| theater | 45 | −6.8 | −32.5 | −16.1 |
| department | 90 | −8.4 | −32.5 | −16.6 |
| market | 24 | −6.1 | −32.5 | −6.2 |
| subway | 65 | −16.0 | −32.5 | −16.2 |
| cafe | 0 | −13.0 | −32.5 | −18.2 |
| rain | 180 | +19.7 | −32.5 | −12.1 |
독립 ebur128 script/hash/raw summary/결과, 독립 pyloudnorm script/hash/version/결과. 일반 npm test는 Python 표준 라이브러리와 FFmpeg만 사용하며 네트워크나 전역 pyloudnorm을 요구하지 않는다. 독립 meter는 별도 disposable venv에서 실행했다. 7개 의존성 전부 version/wheel SHA-256을 고정한 lock과 재현 명령을 보존했다.
같은 원본에서 별도 임시 디렉터리로 두 번 재생성해 공개 WAV/notice/입력·iteration·최종 통계가 동일함을 확인했다. manifest 생성 시각만 제외한다. 재현 결과. 재현성 범위는 기록한 도구 빌드/플랫폼이며 다른 FFmpeg 빌드의 byte 동일성을 주장하지 않는다.
런타임과 검증
기존 고정 배경 gain G=0.4198884518664126을 변경하지 않았다. 환경·SNR·intro 유무와 무관하다. voice/intro RMS .03, SNR은 voice 상대 gain만, master는 세 경로에 동일 적용한다. 보수적 상한 B=.55,V=.25,I=.20, SNR_MAX=12, intro=1.8, ceiling=.8을 유지한다.
G = 0.8 / (0.55 + 0.25*10^(12/20) + 0.20*1.8)
|mix| ≤ master * G * (B + V*10^(12/20) + I*1.8) ≤ 0.8
101 voice×8 배경×25 SNR, 20,200개 조합을 다시 검사했다. 새 background 최대 sample peak는 0.471954345703125, voice=0.2052977830171585, intro=0.14995422959327698이며, 실측 peak를 대입한 최악 합성 상계는 0.6546804814413929 < .8이다. 배경 gain 집합의 크기는 1이다. 전수 runtime/doc 검사.
| 검사 | 결과 | 증거 |
|---|---|---|
| ebur128 TDD | RED 2.0 LU 실패 → GREEN | 01, 06 |
| 선형 gain/peak/비수렴 TDD | RED → 7 PASS | 02, 04 |
| ASR gate TDD | RED, 실제 재검사도 FAIL 유지 | 03, 08 |
| build manifest 계약 TDD | RED → 해당 39 PASS | 07, 15 |
npm run lint |
PASS | 14 |
npm test |
143 PASS / 1 FAIL (ASR) | 15 |
| 전체 Python | 47 PASS | 11 |
npm run build |
PASS, 109 WAV 및 notice/manifest 일치 | 16 |
npm audit --json |
취약점 0개 | audit |
| system Chrome desktop/mobile | 36 PASS, skipped/flaky/unexpected=0 | 17, summary |
| 문서 변경 후 관련 계약/runtime 재검사 | 12 PASS | 21 |
| 불변 이력/원본/음성/public-dist | PASS | 20 |
Chrome은 system executable의 sandbox를 켜서 실행했다. 실제 프로세스 인자에 --no-sandbox가 없음을
기록했다. desktop/mobile은 viewport/touch emulation이며
물리 모바일/Safari 인증은 아니다. 109 WAV의 24/44.1/48/96kHz decode/peak와 8환경×3 SNR의 native GainNode,
3문항·종료·재청취·오류 재시도·무결성·axe·네트워크를 검증했다. 정상 흐름 console/page 오류·실패 요청·외부 요청·axe 위반은 모두 0개다. 의도적인 404/변조 오류는 정상 흐름 통계와 구분한다.
각 프로젝트 436개 리샘플 측정에서 최대 background=0.4879775941371918, voice=0.20585650454525403,
intro=0.14999594059820148로 기존 보수적 상한 이하다. 두 프로젝트 모두 24개 GainNode 관측의
예약 gain은 0.4198884518664126, 실제 Float32 plateau는 0.4198884665966034로 동일하다.
README/CHANGELOG/ARCHITECTURE/AUDIO_PROVENANCE/DEPLOYMENT/정규화 계획/manifest/테스트 한국어 주석을
현재 계기와 릴리스 차단 상태로 수정했다. 제품/query 버전 0.2.5, 정확한
Designed by OZ at Heat-T Medical Inc. 및 제3자 notice/market CC BY-SA 4.0은 유지한다.
원래 TASK/ACCEPTANCE와 이전 릴리스 기록은 역사로 보존하며 이번 사용자 지시가 수용 계기와 gate를 정한다.
현재 수정본의 loudness 통과를 전체 릴리스 통과로 확대하지 않는다.