# 한국어 Qwen 음성 자산 기록 현재 상태: 로컬 GPU 음성 생성과 파일 검사를 완료했습니다. **사용자가 2026-10-05 한국 시간에 count_01·guide_collect·guide_count 세 실제 게임 파일을 듣고 “세 파일 모두 괜찮습니다”라고 승인했습니다.** 해당 세 파일만 청취 승인 상태이며 나머지 숫자와 음성은 청취 미검수 초안입니다. 효과음과 배경음악은 사용자가 나중에 추가하기로 했습니다. ## 출처와 이용조건 - 확인 날짜: 2026-10-05 한국 시간. [공식 Qwen3-TTS 저장소](https://github.com/QwenLM/Qwen3-TTS), [모델 카드](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice)를 확인했습니다. - 모델: `Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice`, 고정 revision `0c0e3051f131929182e2c023b9537f8b1c68adfe`, 한국어/Sohee. 기존 conda 환경 `qwen3-tts`를 재사용했습니다. 가중치·토크나이저·프로세서 전체 snapshot은 저장소 밖에 캐시하며 게임에는 포함하지 않습니다. - 모델 카드는 Apache-2.0을 선언하고, 설치된 qwen-tts 0.1.1에는 Apache-2.0 코드 라이선스가 포함되어 있습니다. 실제 모델 카드와 코드 라이선스 원문은 `SourceAssets/Audio/Voice/licenses/`에 보존했습니다. 공개된 이용조건을 기록한 것이며 생성 음성의 독점권을 주장하지 않습니다. - 공유 프로필에는 정확한 지시문·seed 42·생성 인자·장치·dtype·attention을 기록하고 기기별 캐시 절대경로를 넣지 않았습니다. 초기 지시문: `5~7세 아이에게 이야기하듯 따뜻하고 밝게, 천천히 또렷하게 읽어 주세요. 숫자는 정확하게 읽고 과장된 비명이나 웃음소리는 넣지 마세요.` ## 실제 환경과 생성 증거 기존 CPU torch를 설치된 torchaudio 2.11.0과 버전이 맞는 공식 `torch==2.11.0+cu128` wheel로 교체했습니다. torch의 직접 요구조건 `setuptools<82`를 충족하도록 setuptools 83.0.0만 81.0.0으로 변경했습니다. 환경 재생성이나 무관한 패키지 일괄 업그레이드는 하지 않았습니다. 실제 환경은 Python 3.12.15, qwen-tts 0.1.1, torch 2.11.0+cu128, torchaudio 2.11.0+cpu, transformers 4.57.3, soundfile 0.14.0, huggingface-hub 0.36.2입니다. CUDA 12.8 / NVIDIA GeForce RTX 4080 SUPER에서 CUDA 제곱·합 연산 결과 140을 확인했습니다. torch CUDA·qwen-tts·torchaudio import가 성공했고 SDPA/bfloat16으로 실제 GPU 추론이 성공했습니다. FlashAttention과 SoX는 설치하지 않았습니다. 첫 표본 회차 `20261004T161148012934Z_47f3a009`에서 count_01/count_04/count_07/count_10/guide_collect를 생성했습니다. 모델 로딩 3.214초, GPU 최대 할당 메모리 4,232,247,296바이트, 원본 출력 24,000 Hz 모노 FLOAT WAV입니다. 클립별 길이·프레임 수·생성 시간·SHA-256은 해당 회차 manifest에 기록했습니다. 확대 회차 `20261004T161231511126Z_aa20f404`에서는 대본·프로필·파일 해시가 같은 이전 다섯 클립을 재사용하고 나머지 숫자와 guide_count를 실제 생성했습니다. manifest에는 원래 생성 회차와 파일, 실제 인자와 모델 기본값, 환경, 해시, 클립별 결과를 기록했습니다. 생성 성공과 파일 검사 성공을 발음 합격으로 해석하지 않습니다. 후속 GPU 확인은 실제 모델 장치 `cuda:0`, 로딩 2.976초, 생성 1.826초, 최대 할당 메모리 4,227,715,072바이트, 24,000 Hz / 13,440프레임 / 0.56초를 확인했습니다. 해당 증거와 파형은 무시된 검사 산출물 `artifacts/verification/FirstSlice/Voice/gpu-probe.json` 및 `gpu-probe.wav`에 있습니다. ## 게임 연결용 초안 초안 경로는 `Assets/MagnetismHeroes/UnityRuntime/Presentation/Audio/Voice/`입니다. 원본 FLOAT WAV는 보존하고 실제 polyphase 리샘플링으로 44,100 Hz 모노 PCM16 편집본을 만들었습니다. 발화 구간은 잘라내지 않았습니다. `edited//selection.json`에서 원본 해시와 편집본·게임 파일 해시를 연결합니다. 기존 게임 파일과 새 편집본 내용이 다르면 제작 도구는 기존 파일을 덮어쓰지 않습니다. | ID | 길이 | 상태 | | --- | ---: | --- | | count_01 | 0.56초 | T2 필수 음성, 2026-10-05 사용자 청취 승인 | | guide_collect | 2.00초 | T2 필수 음성, 2026-10-05 사용자 청취 승인 | | guide_count | 3.60초 | T2 필수 음성, 2026-10-05 사용자 청취 승인 | | count_02,03,04,06,07,08,09,10 | 0.48~1.44초 | 이후 계수용 초안, 청취 미검수 | | count_05 | 9.12초 | 긴 공백과 후반 소리의 이상 후보로 게임 연결에서 제외 | 승인 대상은 아래 실제 게임 WAV의 SHA-256입니다. 파일과 selection 이력의 편집본 해시가 일치함을 대조한 뒤 검수자·날짜·사용자 발언·승인 해시를 selection에 기록했습니다. 이 승인은 다른 숫자나 다른 대본·프로필·파일로 확대하지 않습니다. | ID | 승인 SHA-256 | | --- | --- | | count_01 | `13a882ce1620140d447635e14f2d4758045d5e348960c17386df1c720050c100` | | guide_collect | `62e15c9e38c36f4094a6c7e9c5148510141290b5f41db5aad9dc1d8f1a158594` | | guide_count | `debe29b89f3e2856f2bf4c5e01707a5f0a0657e5768c03be385ec88fa2328b40` | count_05의 전체 원본과 편집 후보는 원인 확인을 위해 보존했습니다. 숫자 한 단어가 2초보다 길면 초안 내보내기를 차단합니다. 이 기준은 검수 필요 신호이며 자동 발음 검사가 아닙니다. 같은 프로필로 특정 클립을 다시 만들 때는 `--ids count_05 --regenerate`를 사용하며 이전 회차를 보존합니다. 동일 프로필·seed 42로 count_05만 다시 생성한 회차 `20261004T162201751189Z_a400364e`에서도 9.12초 출력이 재현되었습니다. 실제 `cuda:0` 모델 로딩 2.974초, 추론 22.271초, 최대 GPU 할당 4,386,499,584바이트였습니다. 생성 자체는 성공했지만 정상 초안으로 채택하지 않았고 두 회차의 원본을 모두 보존했습니다. 파일 길이만으로 발음 합격을 선언하지 않으며, 이후 직접 청취한 뒤 같은 모델·목소리 범위에서 지시문·생성 설정을 검토해야 합니다. ## 검증 명령과 결과 모든 명령은 기존 환경의 Python 또는 `conda run --no-capture-output -n qwen3-tts`로 실행합니다. 아래 명령의 실행 위치는 프로젝트 루트입니다. ```powershell python -m unittest discover -s tools/audio -p 'test_*.py' -v python tools/audio/generate_voice.py --catalog SourceAssets/Audio/Voice/voice-catalog.json --profile SourceAssets/Audio/Voice/qwen-profile.json --ids count_01,count_04,count_07,count_10,guide_collect python tools/audio/generate_voice.py --catalog SourceAssets/Audio/Voice/voice-catalog.json --profile SourceAssets/Audio/Voice/qwen-profile.json python tools/audio/generate_voice.py --catalog SourceAssets/Audio/Voice/voice-catalog.json --profile SourceAssets/Audio/Voice/qwen-profile.json --validate-only --manifest SourceAssets/Audio/Voice/generated/20261004T161231511126Z_aa20f404/manifest.json ``` 초기 RED는 생성기 모듈이 없어 종료 코드 1이었습니다. 최종 GREEN에서는 동작 검증 테스트 16개가 종료 코드 0으로 통과했습니다. 잘못된 카탈로그, 현재 대본·프로필과 부분 검사 범위, 실패하거나 비정상적인 WAV, 누락·손상 WAV, 대본·설정 변경, 해시 변조, 이전 원본 보존, 리샘플링, 다른 게임 파일 덮어쓰기 거부, 긴 숫자 출력 차단, 특정 클립만 새 회차로 생성하는 동작, 전부 재사용할 때 모델 로딩 없이 현재 패키지·장치와 원본 생성 환경을 연결하는 동작을 검사합니다. 회차 입력 snapshot 보존·손상 검사와 검증 전용 경로의 비로딩 검사도 포함합니다. 첫 표본 생성·확대 생성·검사 전용 명령은 각각 종료 코드 0이었습니다. `--validate-only`는 모델을 로딩하거나 다운로드하지 않습니다. ID를 생략하면 현재 T2 필수 세 클립 전체를 검사하고, `--ids`를 지정하면 선택 범위를 결과에 기록합니다. 생성한 열두 클립을 모두 지정한 파일·이력 검사는 종료 코드 0이었지만 count_05의 별도 음질 문제는 합격으로 처리하지 않았습니다. 잘못된 ID `missing`은 해당 ID를 포함한 오류와 종료 코드 1을 반환했습니다. 마지막 `pip check`는 종료 코드 0으로 충돌이 없었습니다. 실제 후속 로그는 구현 worktree의 `artifacts/verification/FirstSlice/Voice/` 아래 `python-tests.log`, `validate-all-generated.log`, `validate-invalid-id.log`입니다. 산출물은 Git에서 제외하고 원본 manifest와 선택 파일 해시는 추적합니다. 전부 재사용하는 실제 CLI 검사 회차 `20261004T165608559600Z_21530dcf`는 세 필수 클립을 재사용하고 종료 코드 0으로 통과했습니다. 새 manifest에 현재 Python·패키지 버전, `nvidia-smi`로 확인한 RTX 4080 SUPER 장치, `modelLoad=not_needed`, 서로 다른 두 원본 생성 회차의 manifest 경로·SHA-256·실제 생성 환경을 기록했습니다. 원본 manifest 해시도 대조했습니다. 모델 로딩·재추론은 하지 않았으며 기존 승인 파일과 기본 프로필을 변경하지 않았습니다. 해당 실행 로그는 `reuse-environment.log`입니다. Unity `.meta`는 통합 후 실제 Editor import로 생성해야 하며 직접 작성하지 않았습니다. 남은 검수는 승인된 세 파일을 제외한 발화의 청취·승인 해시 기록, count_05 및 이후 안내 음성 검수, Android 빌드의 음성 큐·믹스 재생 확인입니다. ## 회차별 실제 입력 보존 보완 이전 manifest는 실제 입력의 해시만 담고 있어 공유 카탈로그·프로필을 변경하면 과거 WAV의 대본과 말투 지시·seed 등을 직접 복원하기 어려웠습니다. 새 회차는 `generated//catalog.json`과 `profile.json`에 전체 실제 입력을 보존합니다. manifest의 `inputSnapshots`가 이 두 파일을 가리키며 기존 `catalogHash`·`profileHash`와 구조화된 JSON의 SHA-256을 대조합니다. 프로필 snapshot에는 모델 ID와 고정 revision, 언어, 목소리, 지시문, 장치, dtype, attention, seed, 생성 인자가 그대로 남습니다. 실제 모델 기본값과 적용 인자는 기존 환경 기록으로 함께 확인합니다. snapshot은 새 회차 폴더를 만들 때 한 번 저장하고 공유 입력 변경이나 다른 회차 생성으로 덮어쓰지 않습니다. 재사용은 원래 회차·파일·파일 해시·대본 및 설정 해시 연결을 유지하며, 해당 원본 manifest와 원본 입력 snapshot도 확인합니다. snapshot 누락·손상·해시 불일치 또는 현재 입력과 회차 입력의 불일치는 검증 실패입니다. `--validate-only`는 파일과 이력만 읽으며 모델이나 네트워크를 사용하지 않습니다. 기존 네 회차는 manifest와 WAV를 변경하지 않았습니다. 현재 고정 입력의 실제 구조화 해시가 각 과거 manifest의 `catalogHash=491c9cd0bb7068a47b33bdd0b19ece1ba634217ec0ed9cc3e2c5aa7bd3802755`, `profileHash=a5740d9db8a4aaebf08d0ac3b8f3225693f878aa2868143f01191a059e2680e8`과 정확히 일치함을 모두 대조한 후, 각 폴더에 입력 sidecar 두 파일씩 추가했습니다. 기존 manifest에는 snapshot 필드를 소급 작성하지 않았으며 고정 파일명 규칙으로 sidecar를 연결합니다. 전환 기록은 `input-snapshot-migration.json`에 기존 manifest 해시·검증한 입력 해시·sidecar 경로·날짜·보존 artifact 해시를 담았습니다. 기존 원본 WAV, 네 manifest, 공유 입력, 사용자 승인 selection, 게임 WAV 등 총 31개 artifact의 SHA-256이 전환 전후 동일했습니다. 새 추론을 수행한 것처럼 기록하지 않았습니다. 입력 보존 회귀 검사 네 개는 구현 전 RED(종료 1, 실패 3개·오류 1개)를 재현했고, 보완 후 전체 16개가 GREEN(종료 0)이었습니다. 공유 입력을 실제 변경한 후에도 과거 snapshot의 전체 대본·설정과 원본 WAV가 보존되는지 검사했습니다. legacy sidecar 검사와 원본 snapshot 누락을 통한 재사용 연결 실패도 확인했습니다. 새 회차 `20261004T171918683576Z_7a8cbd60`는 세 필수 음성을 전부 재사용하고 실제 입력 snapshot과 manifest를 기록했으며 CLI 종료 0이었습니다. 기존 네 회차와 새 회차의 검증 전용 명령은 각각 명시된 생성 범위에 대해 종료 0이었습니다. 이때 모델 loader·장치 명령을 차단했고 torch·qwen_tts·huggingface_hub가 import되지 않았음을 별도 JSON 증거에 기록했습니다. 원본을 건드리지 않는 검사 복사본에서 snapshot 누락·손상·해시 불일치, manifest 해시 불일치, 현재 프로필 불일치의 실제 CLI 다섯 건은 각각 종료 1을 반환했습니다. 승인된 세 게임 WAV와 기본 프로필은 변경하지 않았습니다. 증거 경로는 `artifacts/verification/FirstSlice/Voice/InputSnapshots/`의 `red-tests.log`, `green-tests.log`, `legacy-migration.log`, `reuse-new-snapshot-run.log`, `validate-only-proof.json` 및 `.log`, `negative-cli-proof.json` 및 `.log`입니다. 이는 입력·파일·이력 검증 증거이며 미검수 음성의 청각 합격을 뜻하지 않습니다.