2026-10-14 12:12:13 +00:00
|
|
|
|
# Find-Word v0.2.5 오디오 출처와 재현
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
## 포함 자산과 생성 설정
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
|
|
|
|
|
| 대상 | 생성 방식 | 원문/설정 | 배포 방식 |
|
|
|
|
|
|
| --- | --- | --- | --- |
|
2026-10-14 07:15:07 +00:00
|
|
|
|
| `public/audio/intro.wav` | Microsoft Edge online TTS neural 음성 | `src/content.ts`의 INTRO | 24kHz mono PCM16 WAV |
|
|
|
|
|
|
| 목표 음성 100개 | 같은 provider·voice | 10 패턴 × 10 단어, `renderSentence` | 같은 WAV |
|
2026-10-14 10:01:46 +00:00
|
|
|
|
| 8개 배경 환경 | 공개 라이선스 실제 현장 녹음 | `public/ambience/manifest.json` | 12초·24kHz mono PCM16 WAV |
|
2026-10-14 07:15:07 +00:00
|
|
|
|
| 화면 파형·S 캐릭터 | 직접 작성한 CSS | `App.tsx`, `styles.css` | CSS |
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
voice는 **`ko-KR-HyunsuMultilingualNeural`**, rate는 **`-6%`**, pitch는
|
|
|
|
|
|
**`-4Hz`**, 생성 클라이언트는 **edge-tts 7.3.1**이다. 직접 작성한 한국어
|
|
|
|
|
|
문장을 온라인 provider에 보내 MP3 응답을 받은 뒤 FFmpeg로 PCM을 만든다.
|
|
|
|
|
|
음성 복제나 사람의 녹음 샘플을 사용하지 않는다. 웃음은 INTRO의 ‘으하하하~~’를
|
|
|
|
|
|
같은 voice로 합성한다. 앱은 저장한 WAV만 같은 출처에서 가져오며 런타임 외부
|
|
|
|
|
|
TTS/API, speechSynthesis, 인증정보가 필요하지 않다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
청취용 샘플은 [intro.wav](../public/audio/intro.wav)와
|
|
|
|
|
|
[luck-apple.wav](../public/audio/luck-apple.wav)이다. 101개 전체 생성 결과의
|
|
|
|
|
|
크기·길이 범위와 독립 검증은 [v0.1.1 RESULT](../.agent/RESULT-v0.1.1.md)에 기록한다.
|
|
|
|
|
|
`public/audio/manifest.json`은 version, provider, voice, rate, pitch, sampleRate,
|
|
|
|
|
|
생성 시각, 실측 edge-tts/FFmpeg 버전, 파일별 원문·SHA-256·bytes·duration·RMS·peak를 담는다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
## 설치와 생성
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
생성 환경은 Linux (기존 디렉터리 교체에 `renameat2(RENAME_EXCHANGE)` 필요),
|
|
|
|
|
|
Python 3.11 이상, FFmpeg, Node.js 22.22.2 이상이다. **이미 포함된 WAV를
|
|
|
|
|
|
빌드·실행할 때는 Python/FFmpeg/provider 연결이 필요 없다.** 생성기 계약 테스트는
|
|
|
|
|
|
Python과 FFmpeg를 사용하되 네트워크 없이 동작한다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-10-14 07:15:07 +00:00
|
|
|
|
python3 -m venv .venv-audio
|
|
|
|
|
|
.venv-audio/bin/python -m pip install -r requirements-audio.txt
|
|
|
|
|
|
.venv-audio/bin/python -m pip check
|
2026-10-14 06:19:24 +00:00
|
|
|
|
npm run audio:generate
|
2026-10-14 07:15:07 +00:00
|
|
|
|
npm test
|
2026-10-14 06:19:24 +00:00
|
|
|
|
npm run build
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
`audio:generate`는 `.venv-audio/bin/python scripts/generate_audio.py`로 고정되어
|
|
|
|
|
|
전역 Python으로 대체되지 않는다. `requirements-audio.txt`는 edge-tts==7.3.1과
|
|
|
|
|
|
전이 의존성 버전을 고정한다. 생성기는 실제 설치 버전을 조회하고 7.3.1이 아니면
|
|
|
|
|
|
외부 요청 전에 실패한다. `.venv-audio/`는 Git과 배포물에서 제외한다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
원문을 Node type stripping으로 앱 데이터에서 읽고, 101개 모두 같은 파일시스템의
|
|
|
|
|
|
`public/.audio-stage-*/`에 순차 생성한다. 각 provider 요청은 최대 60초, 최대
|
|
|
|
|
|
3회 시도이며 실패 사이 1초/2초를 기다린다. FFmpeg도 60초 제한이 있다.
|
|
|
|
|
|
재시도 전 불완전 MP3를 삭제하고 변환·검증 실패는 즉시 중단한다. 로그에는
|
|
|
|
|
|
파일명·시도 횟수만 남기고 provider stderr/응답·쿠키·인증 헤더를 저장하지 않는다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
전체 WAV와 manifest를 검증한 뒤 기존 `public/audio`와 완성 디렉터리를 단일
|
|
|
|
|
|
원자 교환으로 바꾼다. 실패·Ctrl-C는 기존 디렉터리의 바이트를 그대로 보존한다.
|
|
|
|
|
|
원자 교환을 지원하지 않는 파일시스템에서는 실패하며 비원자 방식으로 우회하지 않는다.
|
|
|
|
|
|
성공 후 이전 자산과 임시 MP3를 정리한다. 강제 종료(SIGKILL)·전원 손실 때는
|
|
|
|
|
|
숨김 staging 폴더가 남을 수 있으나 공개 디렉터리는 교환 전 또는 후의 전체 집합이다.
|
|
|
|
|
|
이는 전원 손실 시 저장장치 내구성 보장을 뜻하지 않는다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
고정 클라이언트와 설정으로 **생성 절차**를 재현할 수 있다. 원격 모델·서비스 버전은
|
|
|
|
|
|
고정할 수 없어 재생성 WAV의 바이트 동일성은 보장하지 않는다. 새 실행의 manifest를
|
|
|
|
|
|
검토해야 한다. 빌드는 이미 생성한 WAV의 해시를 보존하고 101개 모두 포함됐는지 확인한다.
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
## 레벨 처리와 검증
|
2026-10-14 06:19:24 +00:00
|
|
|
|
|
2026-10-14 07:15:07 +00:00
|
|
|
|
MP3를 24kHz mono signed 16-bit little-endian PCM으로 디코드한다. 파일 전체에
|
|
|
|
|
|
동일한 선형 gain을 적용해 RMS 0.10을 목표로 하며 증폭은 최대 2배, peak는
|
|
|
|
|
|
0.89로 제한한다. 동적 압축·노이즈 게이트·침묵 제거·시간 변형은 하지 않는다.
|
|
|
|
|
|
원래 신호의 자음과 억양을 보존하면서 파일 간 레벨 차이와 피크를 완화한다.
|
|
|
|
|
|
|
|
|
|
|
|
생성기와 독립 자산 테스트는 101개 파일의 원문·집합·SHA-256·bytes·duration,
|
|
|
|
|
|
24kHz mono PCM16, 1–20초 길이, RMS > 100/32768, full-scale 미도달,
|
2026-10-14 10:01:46 +00:00
|
|
|
|
총 48MiB 미만을 검사한다. 기존 음성 단독 검사는 RMS 0.03과 +6dB에서 peak < 0.8을
|
2026-10-14 12:12:13 +00:00
|
|
|
|
요구한다. v0.2.5 최대 +12dB 혼합은 [고정 headroom 수식](ARCHITECTURE.md#오디오)으로 별도 검증한다.
|
|
|
|
|
|
앱은 voice/intro의 RMS 정규화를 유지하고 배경 loudness 정규화 PCM을 그대로 쓴다.
|
2026-10-14 07:15:07 +00:00
|
|
|
|
물리적 음압이나 주파수별 청감을 보정한 값은 아니다.
|
|
|
|
|
|
|
|
|
|
|
|
## 도구 라이선스와 서비스 조건
|
|
|
|
|
|
|
|
|
|
|
|
- [edge-tts 7.3.1 LICENSE](https://github.com/rany2/edge-tts/blob/7.3.1/LICENSE):
|
|
|
|
|
|
대부분의 코드에 LGPLv3, `srt_composer.py`에만 MIT가 적용된다.
|
|
|
|
|
|
[공식 프로젝트](https://github.com/rany2/edge-tts)는 Microsoft Edge의 온라인
|
|
|
|
|
|
TTS를 이용하는 클라이언트다. 클라이언트 라이선스가 provider 사용·음성 출력의
|
|
|
|
|
|
재배포 권한을 대신 부여하지 않는다. 이 프로젝트는 클라이언트/모델을 번들하지 않는다.
|
|
|
|
|
|
- [FFmpeg 공식 라이선스](https://ffmpeg.org/legal.html): 빌드 옵션에 따라 LGPL/GPL이
|
|
|
|
|
|
적용된다. 실제 사용 버전은 manifest에 남기며 실행 파일은 배포하지 않는다.
|
|
|
|
|
|
- [Microsoft Services Agreement](https://www.microsoft.com/en-us/servicesagreement)의
|
|
|
|
|
|
AI Services 등 해당 서비스 조건은 도구의 오픈소스 라이선스와 별개다.
|
|
|
|
|
|
위 문서 §13(s)(vi)는 출력의 권리·사용 가능성을 이용자가 판단하도록 설명한다.
|
|
|
|
|
|
API 키 없이 호출된다는 사실이 상업 사용·재배포의 포괄적 허락이나 SLA를 뜻하지 않는다.
|
|
|
|
|
|
배포자는 자신의 이용 상황에 적용되는 최신 조건을 확인해야 한다.
|
|
|
|
|
|
- 프로젝트는 생성 음성 자체에 **독점 권리를 주장하지 않는다**. [LICENSE](../LICENSE)의
|
|
|
|
|
|
소스·문서 권리 유보와 provider 및 제3자의 권리는 구분한다. 런타임 React,
|
|
|
|
|
|
ReactDOM, scheduler의 MIT 전문은 [THIRD_PARTY_NOTICES.md](../THIRD_PARTY_NOTICES.md)에 있다.
|
|
|
|
|
|
|
|
|
|
|
|
문서 확인일: 2026-10-14 UTC. provider의 음성 목록, rate/pitch 지원, 가용성,
|
|
|
|
|
|
접근 제한, 조건은 바뀔 수 있다. 온라인 생성이 중단되어도 포함된 WAV의 빌드·재생에는
|
|
|
|
|
|
영향이 없다. 실패 시 다른 voice로 자동 대체하지 않는다.
|
|
|
|
|
|
|
|
|
|
|
|
## 청감과 평가의 한계
|
|
|
|
|
|
|
|
|
|
|
|
자동 검증은 PCM 신호·무결성·재생 흐름을 확인한다. 한국어 발음, 유사 자모의
|
|
|
|
|
|
구분, 웃음의 자연스러움과 실제 사용자의 난이도는 청취 평가가 필요하다.
|
2026-10-14 10:01:46 +00:00
|
|
|
|
대표 샘플과 게임 내 소음 혼합 상태를 직접 들어 인수 판단한다. 배경은 실제 현장 녹음의 짧은 구간이다. 이 게임의 수치는 임상 검증·치료·청력 판정용이 아니다.
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-10-14 12:12:13 +00:00
|
|
|
|
## v0.2.5 loudness 정규화
|
|
|
|
|
|
|
|
|
|
|
|
**exact 자산 소유자 승인:** loudness 수정은 두 계기를 통과했다. 새 market WAV의 동일 VAD ASR 조건은
|
|
|
|
|
|
여전히 실패하며, 릴리스는 아래 Oz의 새 exact-byte 청취 승인 경로로만 수용한다. 법적/privacy clearance는 없다.
|
|
|
|
|
|
기존 loudnorm input_i의 0.01 LU spread는 같은 파일의 전용 ebur128 **2.0 LU**, 독립 pyloudnorm 0.2.0
|
|
|
|
|
|
**1.925 LU** 결과에 의해 거부되었다. loudnorm input_i를 수용 계기로 인정하지 않는다.
|
|
|
|
|
|
[거부된 당시 RESULT](../.agent/evidence-v0.2.5/review-fixes/rejected-RESULT-v0.2.5.md),
|
|
|
|
|
|
[기존 원문 측정](../.agent/evidence-v0.2.5/independent-loudness.json)과 기존 증거 전체는 불변 역사다.
|
|
|
|
|
|
|
|
|
|
|
|
원본 8개 SHA-256/bytes·creator·license·attribution·선택 구간을 모두 보존했다.
|
|
|
|
|
|
[정규화 계획](../.agent/AMBIENCE-NORMALIZATION-v0.2.5.json)은 불변 source plan의 SHA-256을 포함한다.
|
|
|
|
|
|
도구는 **ffmpeg version 6.1.1-3ubuntu5**이며 일반 회귀 검사는 Python 표준 라이브러리와 FFmpeg만 사용한다.
|
|
|
|
|
|
|
|
|
|
|
|
1. 원본 전체의 hash/bytes를 검증한 뒤 기존 seek/full decode sample trim으로 승인 구간을 추출한다.
|
|
|
|
|
|
2. 24kHz mono float PCM 288,000 samples에 기존 양끝 50ms 선형 fade를 적용한다.
|
|
|
|
|
|
3. 정확한 faded PCM을 새 `ebur128=peak=true` 프로세스로 측정하고 **gain_db=−32.5−measured_i**를 계산한다.
|
|
|
|
|
|
4. **measured_true_peak+gain_db > −6.2 dBTP**면 변환 전에 실패한다. market의 파형을 보존할 수 있도록
|
|
|
|
|
|
공통 목표를 −32.5 LUFS로 선택했다. −6.2 내부 ceiling은 최종 −6 dBTP 조건에 0.2 dB 여유를 둔다.
|
|
|
|
|
|
5. 같은 PCM에 오직 `volume=<gain_db>dB:precision=double`을 적용하고 FFmpeg `pcm_s16le`로 인코딩한다.
|
|
|
|
|
|
표준 `wave` writer는 44-byte WAV 헤더를 쓴다. compressor/limiter/loudnorm은 사용하지 않는다.
|
|
|
|
|
|
6. staged WAV 전체를 새 ebur128 프로세스로 측정한다. 목표 오차가 ±0.2 LU 밖일 때만 원래 faded PCM에서
|
|
|
|
|
|
스칼라를 보정한다. 최대 총 3회, 매 시도 peak 사전 검사를 수행하고 비수렴은 실패한다.
|
|
|
|
|
|
7. 전체 staging의 형식/길이/fade/출처/notice/hash를 검증하고 ebur128을 다시 실행한다.
|
|
|
|
|
|
**목표 ±0.2 LU, spread ≤0.4 LU, true peak ≤−6 dBTP**를 강제한다. 생성 중에는 −6.2도 강제한다.
|
|
|
|
|
|
전부 통과한 8 WAV·manifest·고지를 단일 `renameat2(RENAME_EXCHANGE)`로 교환한다.
|
|
|
|
|
|
source mismatch·NaN·측정/쓰기/교환 실패·목표/peak 위반은 이전 공개 디렉터리를 보존한다.
|
|
|
|
|
|
|
|
|
|
|
|
manifest `normalization`에는 목표/허용오차/spread/두 ceiling/계기/최대 반복 수가 있고,
|
|
|
|
|
|
`toolVersions.ffmpeg`에는 실제 도구 버전이 있다. 각 `conversion.loudness`는 faded PCM hash,
|
|
|
|
|
|
입력 ebur128 통계, 매 iteration의 정확한 gain/filter/예측 peak/출력 통계와 최종 통계를 보존한다.
|
|
|
|
|
|
이번 8개는 모두 **첫 시도에 수렴**하여 보정 반복이 필요하지 않았다.
|
|
|
|
|
|
|
|
|
|
|
|
| 환경 | 원본 구간(초) | 입력 LUFS | gain dB | 최종 LUFS | true peak dBTP | sample peak |
|
|
|
|
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
|
|
|
|
| street | 35–47 | -35.7 | 3.2 | -32.5 | -10.2 | 0.31008911 |
|
|
|
|
|
|
| mall | 36–48 | -22.1 | -10.4 | -32.5 | -12.2 | 0.23022461 |
|
|
|
|
|
|
| theater | 45–57 | -25.7 | -6.8 | -32.5 | -16.1 | 0.15737915 |
|
|
|
|
|
|
| department | 90–102 | -24.1 | -8.4 | -32.5 | -16.6 | 0.14721680 |
|
|
|
|
|
|
| market | 24–36 | -26.4 | -6.1 | -32.5 | -6.2 | 0.47195435 |
|
|
|
|
|
|
| subway | 65–77 | -16.5 | -16.0 | -32.5 | -16.2 | 0.15432739 |
|
|
|
|
|
|
| cafe | 0–12 | -19.5 | -13.0 | -32.5 | -18.2 | 0.12213135 |
|
|
|
|
|
|
| rain | 180–192 | -52.2 | 19.7 | -32.5 | -12.1 | 0.24734497 |
|
|
|
|
|
|
|
|
|
|
|
|
최종 전용 ebur128: **−32.5 LUFS 전수, spread 0.0 LU**, 최대 true peak **−6.2 dBTP**.
|
|
|
|
|
|
생성기를 import하지 않는 [독립 회귀 테스트](../tests/python/test_loudness_audio.py)가 이 동등성을 강제한다.
|
|
|
|
|
|
별도 disposable **pyloudnorm 0.2.0 / soundfile 0.13.1**의 exact-WAV 측정은
|
|
|
|
|
|
**−32.6062~−32.5291 LUFS, spread 0.0772 LU**, 최대 목표 오차 **0.1063 LU 미만**으로 통과했다.
|
|
|
|
|
|
[결과/스크립트/고정 의존성과 해시](../.agent/evidence-v0.2.5/review-fixes/README.md)를 별도로 보존한다.
|
|
|
|
|
|
일반 npm test는 이 패키지 설치나 네트워크가 필요 없다. 같은 FFmpeg/입력/플랫폼에서 두 번 다시 생성한
|
|
|
|
|
|
WAV/notice/측정 통계의 재현성도 검사했다. manifest의 생성 시각만 달라진다.
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 scripts/ambience_audio.py
|
|
|
|
|
|
python3 -m unittest discover -s tests/python -v
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
[새 exact-WAV ASR 결과](../.agent/evidence-v0.2.5/review-fixes/final-asr.json)는 동일한
|
|
|
|
|
|
faster-whisper **1.2.1**, tiny revision `d90ca5fe260221311c53c58e660288d3deb8d356`, CPU int8,
|
|
|
|
|
|
beam_size=5, best_of=5, 기본 Silero VAD, condition_on_previous_text=true를 사용했다.
|
|
|
|
|
|
**market 1 segment, mall/cafe 0개, requiredEmptyPassed=false**다. market hash는
|
|
|
|
|
|
`7178307c48c192ac396dcd3c880c377bf56b45e829b459b1feca9f986437e632`이다.
|
|
|
|
|
|
반환 구간 10.45–12.45초와 텍스트 ` Let's go, let's go, let's go.`를 수정 없이 보존했다.
|
|
|
|
|
|
텍스트는 검증된 전사가 아니며 환각일 수 있다. ASR 원문 SHA-256
|
|
|
|
|
|
`98acdb16bc5dce57bb3609b705b63125e5511c2d5f7b26bdde54f4b7bd9a5e49`와 모든 설정/segment를 보존한다.
|
|
|
|
|
|
ASR 보고서 자체의 **humanListeningAcceptance=false, legalPrivacyClearance=false**도 변경하지 않는다.
|
|
|
|
|
|
|
|
|
|
|
|
제품 소유자 Oz는 `/home/hermes/voice-memos/find-word-v0.2.5-normalized-ambience-review.zip`의
|
|
|
|
|
|
현재 8 WAV·manifest·notice를 받은 뒤 **“승인합니다. 이대로 진행하세요”**라고
|
|
|
|
|
|
**2026-10-14T11:29:51Z / 2026-10-14 20:29:51 KST**에 회신했다. 사용자가 전달한 이 새 회신은
|
|
|
|
|
|
별도 [RELEASE-APPROVAL](../.agent/RELEASE-APPROVAL-v0.2.5.json)에 기록한다.
|
|
|
|
|
|
ZIP SHA-256은 `bb2e974b652df43db4a1f2a59716836e2c521839c724b34d4b71c1b40c3322e5`,
|
|
|
|
|
|
현재 manifest SHA-256은 `6433bf23af35f24031c6bbe784dd0abf9330f276da6b8705e47c7a1144a285b7`이며
|
|
|
|
|
|
모든 WAV/notice 해시도 기록했다. 이 별도 인수 기록은 **productOwnerReleaseApproval=true,
|
|
|
|
|
|
humanListeningAcceptance=true, legalPrivacyClearance=false**다. 법적/privacy clearance나 ASR의 PASS를 주장하지 않는다.
|
|
|
|
|
|
|
|
|
|
|
|
`python3 scripts/release_approval.py`는 동일 설정의 자동 empty-ASR 조건 **OR** 유효한 exact-byte 소유자
|
|
|
|
|
|
청취 승인을 요구한다. 현재 통과 사유는 후자뿐이다. 승인 문구/범위/시각/소유자/flags와 고정 ZIP hash를
|
|
|
|
|
|
검사하고 ZIP의 manifest·notice·8 WAV를 현재 파일과 바이트 단위로 비교한다. 다른 자산/manifest/ZIP,
|
|
|
|
|
|
필수 정보 누락, 법적 clearance 과장은 거부한다. 원래 실패 테스트·실패 로그는
|
|
|
|
|
|
[release-approval 증거](../.agent/evidence-v0.2.5/release-approval/README.md)에 보존하며
|
|
|
|
|
|
현재 회귀 테스트는 원문 실패의 불변성과 별도 승인 계약을 각각 검사한다. 이전 v0.2.3 승인의 범위는 그대로다.
|
|
|
|
|
|
|
|
|
|
|
|
## v0.2.3 현장 녹음 파생본 — 역사 기록
|
|
|
|
|
|
|
|
|
|
|
|
아래 절의 “현재/최종”은 v0.2.3 당시 상태를 뜻한다. 당시 exact manifest/WAV는
|
|
|
|
|
|
[v0.2.3 snapshot](../.agent/evidence-v0.2.5/baseline/ambience/)에 보존했고 원본 evidence는 수정하지 않았다.
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-10-14 10:01:46 +00:00
|
|
|
|
|
|
|
|
|
|
원본 선정 계약은 [.agent/AMBIENCE-SOURCES-v0.2.3.json](../.agent/AMBIENCE-SOURCES-v0.2.3.json),
|
|
|
|
|
|
배포 바이트의 출처·직접 URL·저작자·라이선스·변환·SHA-256·bytes·duration·RMS·peak는
|
2026-10-14 12:12:13 +00:00
|
|
|
|
[manifest](../.agent/evidence-v0.2.5/baseline/ambience/manifest.json), 정확한 attribution과 변경 고지는
|
|
|
|
|
|
[AMBIENCE_NOTICES](../.agent/evidence-v0.2.5/baseline/ambience/AMBIENCE_NOTICES.md)에 있다. 이 고지는 dist에도 포함되고 UI에서 링크한다.
|
2026-10-14 10:01:46 +00:00
|
|
|
|
여덟 원본 모두 서로 다른 현장 녹음이며 NC/ND 자산을 사용하지 않는다. 원본은 저장소/빌드에 포함하지 않는다.
|
|
|
|
|
|
|
|
|
|
|
|
| 환경 | 저작자 | 라이선스 | 원본 구간(초) |
|
|
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
|
|
| 길거리 | cori (Cori Samuel) | PD-author | 35–47 |
|
|
|
|
|
|
| 쇼핑몰 | thore (Thore) | PD-author | 36–48 |
|
|
|
|
|
|
| 극장 | ElevatorFan2020 | CC0 1.0 | 45–57 |
|
|
|
|
|
|
| 백화점 | icmusic | CC0 1.0 | 90–102 |
|
|
|
|
|
|
| 시장 | Marie Flutre | CC BY-SA 4.0 | 24–36 |
|
|
|
|
|
|
| 지하철 | PascalHD | CC BY 4.0 | 65–77 |
|
|
|
|
|
|
| 카페 | Marble Toast | CC0 1.0 | 0–12 |
|
|
|
|
|
|
| 비 오는 거리 | Extemporalist | CC0 1.0 | 180–192 |
|
|
|
|
|
|
|
|
|
|
|
|
Commons primary 페이지/API와 Freesound primary 페이지의 라이선스 근거를 evidence에 보존한다.
|
|
|
|
|
|
Freesound 두 원본은 지정된 preview MP3이다. 프로젝트의 비공개 라이선스를 제3자 녹음에
|
|
|
|
|
|
적용하지 않으며, 시장 파생 WAV는 **CC BY-SA 4.0**으로 계속 공개·수정·재배포할 수 있다.
|
|
|
|
|
|
지하철은 **CC BY 4.0**의 PascalHD credit·변경 고지·라이선스 링크를 유지한다.
|
|
|
|
|
|
|
|
|
|
|
|
재현: 검증한 원본 8개를 `/tmp/findword-ambience-sources`에 놓고
|
|
|
|
|
|
`python3 scripts/ambience_audio.py`를 실행한다. 계획의 파일별 `selectedSegmentStartSeconds`에서 12초를 선택하고,
|
|
|
|
|
|
FFmpeg로 mono 24kHz float PCM 디코드 후 양끝 50ms 선형 fade, RMS 목표 .08,
|
|
|
|
|
|
최대 증폭 4배/peak .85 중 가장 작은 선형 gain을 적용한다. 마지막은 표준 44-byte
|
|
|
|
|
|
WAV 헤더의 PCM16이다. 시간 변형·절차적 합성·원본 음성 대체는 없다.
|
|
|
|
|
|
원본 SHA-256과 실측 FFmpeg 버전을 함께 기록하므로 같은 원본/도구로 재현 가능하다.
|
|
|
|
|
|
|
|
|
|
|
|
런타임은 음성/배경 각각 RMS .03 후 상대 gain `10^(dB/20)`을 적용한다. −12~+12 dB
|
|
|
|
|
|
범위에서도 세 경로의 최악 피크 합을 공통 감쇠하여 최대 .8로 제한한다. 양끝 fade가
|
|
|
|
|
|
있는 배경을 loop하고 목표 끝에서 정리한다. 전체 버퍼 RMS 기준이며 짧은 시간창별
|
|
|
|
|
|
SNR이나 실제 음압을 보증하지 않는다. 원본 녹음의 우연한 사람 말소리는 환경의 일부다.
|
|
|
|
|
|
자동 검사로 음악·개인 대화의 완전한 부재를 인증할 수 없으므로 사람의 최종 청취 검토가 필요하다.
|
|
|
|
|
|
|
|
|
|
|
|
기존 neural WAV 101개의 원문·해시는 v0.1.1 그대로다. 음성 manifest의 version은
|
|
|
|
|
|
배포 버전 0.2.3, `generatedForVersion`은 0.1.1이며 원래 생성 시각·도구 정보는 보존한다.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 리뷰 후 출처 고정과 원자 발행
|
|
|
|
|
|
|
|
|
|
|
|
승인 계획의 `expectedSourceSha256`와 `sourceBytes`는 불변 입력이다. 생성기는 로컬 경로나
|
|
|
|
|
|
현재 파일에서 이 승인값을 새로 기록하지 않으며, 여덟 원본의 해시·크기를 **첫 변환 전**에 모두 검사한다.
|
|
|
|
|
|
한 원본이라도 다르거나 누락되면 실패한다. `sourceVerification`은 검증 상태·일자·방법·보존된 증거를 가리킨다.
|
|
|
|
|
|
임시 경로를 담던 `verifiedLocalSource` 필드는 제거했다.
|
|
|
|
|
|
|
|
|
|
|
|
`directMediaDurationSeconds`는 **directUrl에서 받은 바로 그 바이트**의 ffprobe `format.duration`이다.
|
|
|
|
|
|
Freesound 항목은 preview MP3의 길이이며 primary 페이지 원본 길이 또는 반올림한 표시 길이가 아니다.
|
|
|
|
|
|
배포 manifest의 `duration`과 `conversion.durationSeconds`는 파생 WAV의 길이(12초),
|
|
|
|
|
|
`selectedSegmentStartSeconds`는 파일별 불변 승인 시작점이며 생성기는 별도 hardcoded map 없이 이 값을 읽는다.
|
|
|
|
|
|
`conversion.startSeconds`는 같은 값이어야 한다. 시작점은 유한한 0 이상 수이고, 시작점+12초가
|
|
|
|
|
|
`directMediaDurationSeconds` 이하여야 한다. 누락·음수·NaN·Infinity·문자열·bool·범위 초과는 첫 변환 전에 거부한다. 원본 전체 디코드와 실제 수치는
|
|
|
|
|
|
[보존된 source-integrity.json](../.agent/evidence-v0.2.3/source-integrity.json)에 있다.
|
|
|
|
|
|
|
|
|
|
|
|
생성기는 출력 폴더와 같은 부모의 `.ambience-stage-*/ready`에서 8 WAV·manifest·`AMBIENCE_NOTICES.md`를
|
|
|
|
|
|
완성한다. 정확한 파일 집합, 고유 해시, 원본 계획, PCM 형식·길이·fade·RMS·peak,
|
|
|
|
|
|
항목별 저작자/primary URL/direct URL/라이선스 링크/outputLicense/변경 설명을 다시 검사한다.
|
|
|
|
|
|
존재하는 symlink 및 dangling symlink 출력을 모두 거부한다. Linux `renameat2(RENAME_EXCHANGE)` 한 번이 교체의
|
|
|
|
|
|
commit 지점이며, 최초 생성은 같은 파일시스템의 rename 한 번이다. 지원하지 않는 환경에서는 실패한다.
|
|
|
|
|
|
파일별 overlay를 하지 않으므로 오래된 파일이 남지 않고 고지도 음원과 같은 디렉터리로 교체된다.
|
|
|
|
|
|
|
|
|
|
|
|
commit 전 변환·쓰기·검증·교환 실패 또는 중단은 이전 디렉터리를 보존한다. syscall 이후에는 완성된 새 디렉터리가
|
|
|
|
|
|
공개된 상태다. SIGKILL 등 강제 종료는 숨은 임시 디렉터리를 남길 수 있지만 부분 배포는 만들지 않는다.
|
|
|
|
|
|
전원 손실에 대한 디스크 내구성이나 여러 HTTP 요청에 걸친 snapshot 격리를 주장하지 않는다.
|
|
|
|
|
|
앞선 독립 리뷰에서는 기존 109 WAV를 재생성하지 않았다. 이후 아래 privacy refinement에서
|
|
|
|
|
|
전체 현장음 bundle을 원자 재생성했으며 mall/market/cafe 3개만 바이트가 바뀌었다.
|
|
|
|
|
|
**사람의 현장음 청취 인수는 미실행**이다.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 최종 privacy excerpt refinement
|
|
|
|
|
|
|
|
|
|
|
|
현재 선택은 **mall 36–48초, market 24–36초, cafe 0–12초**다. Neo가 동일한
|
|
|
|
|
|
`scripts/ambience_audio.convert` 경로와 아래 ASR 설정으로 해시 고정 원본을 재검사해 제시한
|
|
|
|
|
|
market/cafe 후보를 사용했다. 제공받은 재검사 설명은
|
|
|
|
|
|
[selection-context.json](../.agent/evidence-v0.2.3/privacy-screening/retry-market24-cafe0/selection-context.json)에
|
|
|
|
|
|
별도로 기록했으며, 원본 후보 결과를 최종 WAV 검사 결과로 대신하지 않았다.
|
|
|
|
|
|
|
|
|
|
|
|
승인 원본 8개의 SHA-256·bytes·ffprobe 길이를 먼저 대조하고 하드닝된 생성기로
|
|
|
|
|
|
8 WAV·manifest·notice 전체를 staging/검증/원자 교환했다.
|
|
|
|
|
|
[생성 실측 기록](../.agent/evidence-v0.2.3/privacy-screening/retry-market24-cafe0/regeneration.json)에
|
|
|
|
|
|
현재 해시·RMS·peak·변환이 있다. 이번 재시도는 market/cafe 두 WAV만 변경했다.
|
|
|
|
|
|
**101개 voice, 다섯 unaffected ambience, 기존 mall 36초 WAV는 모두 바이트 동일**하다.
|
|
|
|
|
|
|
|
|
|
|
|
일부 Ogg 구간은 FFmpeg timestamp/seek 때문에 12초보다 몇 프레임 짧게 출력된다.
|
|
|
|
|
|
짧은 결과일 때만 처음부터 디코드한 24kHz PCM의 `round(start × 24000)`부터 정확한 288,000개
|
|
|
|
|
|
sample을 선택하고 출력 PTS를 sample 수로 재설정한다. silent padding이나 time stretching은 없다.
|
|
|
|
|
|
정말 원본이 짧으면 여전히 실패하며 `conversion.seekMethod`가 실제 경로를 기록한다.
|
|
|
|
|
|
|
|
|
|
|
|
[final-asr.json](../.agent/evidence-v0.2.3/privacy-screening/final-asr.json)은 정확한 현재 8 WAV를
|
|
|
|
|
|
로컬 **faster-whisper 1.2.1, tiny multilingual, CPU int8, beam_size=5, best_of=5,
|
|
|
|
|
|
기본 Silero VAD 활성화, condition_on_previous_text=true**로 검사한 원문이다.
|
|
|
|
|
|
모델 revision `d90ca5fe260221311c53c58e660288d3deb8d356`, 모델/VAD 파일 해시,
|
|
|
|
|
|
라이브러리 버전·전체 설정·각 입력 해시·반환 segment/info를 저장했다.
|
|
|
|
|
|
이전 실패 실행과 모든 decoder/VAD 인자가 같은지 스크립트가 대조한다.
|
|
|
|
|
|
**mall/market/cafe 각각 segment 0개, duration_after_vad=0.0, requiredEmptyPassed=true**다.
|
|
|
|
|
|
다른 다섯 WAV도 segment 0개다. threshold 조절이나 반환 segment 삭제는 하지 않았다.
|
|
|
|
|
|
테스트는 지정 시작점·true gate·VAD 설정·실제 WAV/manifest 해시와 아래 false 인수값을 함께 강제한다.
|
|
|
|
|
|
|
|
|
|
|
|
**humanListeningAcceptance=false, legalPrivacyClearance=false**를 유지한다.
|
|
|
|
|
|
Tiny-model ASR은 screening signal일 뿐이며 빈 결과는 말소리·음악·개인 대화가 없음을 증명하지 않는다.
|
|
|
|
|
|
출력 text/language도 환각일 수 있고 충실한 전사나 화자 식별로 주장하지 않는다.
|
|
|
|
|
|
독립적인 사람 청취 인증은 수행하지 않았다. 다만 제품 소유자 Oz는 2026-10-14 제공된
|
|
|
|
|
|
최종 WAV 8개 청취 검수 묶음과 명시된 자동 검사 한계를 기준으로 현재 자산 그대로 릴리스를
|
|
|
|
|
|
진행하도록 승인했다. 이 승인은 제3자의 법적/privacy clearance를 대신하지 않는다.
|
|
|
|
|
|
|
|
|
|
|
|
이전 market 60–72초/cafe 180–192초 실행은 market 3개/cafe 1개 segment를 반환하여
|
|
|
|
|
|
**requiredEmptyPassed=false**였으며 release acceptance 실패였다.
|
|
|
|
|
|
그 실행의 모든 screening 파일은 읽기 전용
|
|
|
|
|
|
[prior-attempt-market60-cafe180](../.agent/evidence-v0.2.3/privacy-screening/prior-attempt-market60-cafe180/)
|
|
|
|
|
|
아래 바이트 그대로 보존했다. [당시 final-asr.json](../.agent/evidence-v0.2.3/privacy-screening/prior-attempt-market60-cafe180/final-asr.json)을
|
|
|
|
|
|
성공으로 덮어쓰지 않았고 회귀 테스트가 이전 실패 상태와 모든 보존 파일 해시를 검사한다.
|
|
|
|
|
|
|
|
|
|
|
|
[기존 no-VAD 증거](../.agent/evidence-v0.2.3/privacy-screening/no-vad-asr.json)도 바이트 그대로 남겼다.
|
|
|
|
|
|
이 결과는 mall 36초/market 60초/cafe 180초에서 환각일 수 있는 candidate text를 냈으며,
|
|
|
|
|
|
새 market/cafe WAV의 검사 결과가 아니다. **no-VAD 결과는 지정된 VAD gate를 대체하거나 뒤집지 않는다.**
|
|
|
|
|
|
두 방법 모두 말소리/음악의 부재를 증명하지 않으며 사람의 청취 인수나 법적/privacy clearance를 제공하지 않는다.
|
|
|
|
|
|
Neo의 [이전 후보 scan](../.agent/evidence-v0.2.3/privacy-screening/candidate-scan-original.json),
|
|
|
|
|
|
[이전 파생본 ASR](../.agent/evidence-v0.2.3/privacy-screening/prior-derivatives-asr-original.json),
|
|
|
|
|
|
[당시 provenance](../.agent/evidence-v0.2.3/privacy-screening/earlier-asr-provenance.json)도 변경하지 않았다.
|
|
|
|
|
|
raw JSON에 없던 설정이나 입력 연결을 사후에 있었던 것으로 주장하지 않는다.
|
|
|
|
|
|
|
|
|
|
|
|
새 RED → GREEN, 전체 검증과 보존 기록은
|
|
|
|
|
|
[retry-market24-cafe0](../.agent/evidence-v0.2.3/privacy-screening/retry-market24-cafe0/),
|
|
|
|
|
|
현재 검증 요약은 [RESULT](../.agent/RESULT-v0.2.3.md)의 마지막 절에 있다.
|