2026-10-14 07:15:07 +00:00
|
|
|
|
# Find-Word v0.1.1 오디오 출처와 재현
|
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 |
|
|
|
|
|
|
| 8개 배경 환경 | 직접 작성한 결정론적 DSP | `ENVIRONMENTS`, 고정 seed | 브라우저 메모리에서 합성 |
|
|
|
|
|
|
| 화면 파형·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 미도달,
|
|
|
|
|
|
총 48MiB 미만을 검사한다. 런타임 RMS 0.03과 최대 +6dB에서도 peak < 0.8을
|
|
|
|
|
|
요구한다. 기존 앱은 Web Audio에서 배경·음성을 RMS 정규화한 뒤 상대 SNR을 적용한다.
|
|
|
|
|
|
물리적 음압이나 주파수별 청감을 보정한 값은 아니다.
|
|
|
|
|
|
|
|
|
|
|
|
## 도구 라이선스와 서비스 조건
|
|
|
|
|
|
|
|
|
|
|
|
- [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 신호·무결성·재생 흐름을 확인한다. 한국어 발음, 유사 자모의
|
|
|
|
|
|
구분, 웃음의 자연스러움과 실제 사용자의 난이도는 청취 평가가 필요하다.
|
|
|
|
|
|
대표 샘플과 게임 내 소음 혼합 상태를 직접 들어 인수 판단한다. 배경은 장소를
|
|
|
|
|
|
추상화한 합성 신호다. 이 게임의 수치는 임상 검증·치료·청력 판정용이 아니다.
|