From e94123ad4910ea14dc2c77c80e3f7b848c1238ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Mon, 9 Mar 2026 22:29:07 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[rd,=20approvals]=20=EB=88=84=EB=9D=BD?= =?UTF-8?q?=20=EB=AC=B8=EC=84=9C=202=EA=B1=B4=20=EB=B3=B5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - features/rd/sound-logo-studio.md (사운드 로고 스튜디오) - dev/changes/20260306_purchase_request_payment_method.md (품의서 지급방법) --- ...0260306_purchase_request_payment_method.md | 69 +++++ sam/docs/features/rd/sound-logo-studio.md | 244 ++++++++++++++++++ 2 files changed, 313 insertions(+) create mode 100644 sam/docs/dev/changes/20260306_purchase_request_payment_method.md create mode 100644 sam/docs/features/rd/sound-logo-studio.md diff --git a/sam/docs/dev/changes/20260306_purchase_request_payment_method.md b/sam/docs/dev/changes/20260306_purchase_request_payment_method.md new file mode 100644 index 0000000..67308f5 --- /dev/null +++ b/sam/docs/dev/changes/20260306_purchase_request_payment_method.md @@ -0,0 +1,69 @@ +# 품의서 지급방법 UI 개선 + +**날짜:** 2026-03-06 +**작업자:** Claude Code + +## 변경 개요 + +품의서 2종(구매품의서, 비용정산품의서)에 지급방법 선택 기능을 추가/개선하였다. + +## 변경 내용 + +### 1. 구매품의서 (pr_purchase) - 지급방법 추가 + +- 납품 정보(납품업체/납품예정일/납품장소) 아래에 **지급방법 radio** 추가 +- 옵션: `법인카드` / `계좌이체` +- **일괄 선택** 방식 (전체 구매건에 하나의 지급방법) + +### 2. 비용정산품의서 (pr_settlement) - 지급방법 행별 변경 + +- 기존: 테이블 아래에 일괄 radio (법인카드/개인선지출) +- 변경: 각 내역행에 **지급방법 select** 컬럼 추가 +- 테이블 하단에 **지급방법별 합계표** 추가 (법인카드 합계 / 개인선지출 합계) +- 이유: 하나의 정산서에 법인카드/개인선지출 내역이 혼재할 수 있음 + +### 3. 지출품의서 (pr_expense) - 라벨 변경 + +- `사용일자` -> `지출일자` 라벨 변경 (폼 + 조회 화면) + +## 수정된 파일 + +| 파일 | 변경 내용 | +|------|----------| +| `mng/resources/views/approvals/partials/_purchase-request-form.blade.php` | 구매품의서 지급방법 radio 추가, 비용정산품의서 행별 select + 합계표, 지출일자 라벨 변경 | +| `mng/resources/views/approvals/partials/_purchase-request-show.blade.php` | 구매품의서/비용정산품의서 조회 화면 동기화 | + +## Alpine.js 데이터 변경 + +### 구매품의서 + +```javascript +// formData에 추가 +payment_method: initialData?.payment_method || '', + +// getFormData()에 포함 +{ ...base, ..., payment_method: this.formData.payment_method } +``` + +### 비용정산품의서 + +```javascript +// makeItem()에 추가 +payment_method: data?.payment_method || '', + +// computed 속성 추가 +get corporateCardTotal() { /* corporate_card 행만 합산 */ }, +get personalAdvanceTotal() { /* personal_advance 행만 합산 */ }, + +// getFormData() 변경 +// 기존: payment_method: this.formData.payment_method (일괄) +// 변경: 각 item.payment_method (행별) + corporate_card_total, personal_advance_total +``` + +## 관련 문서 + +- [결재 양식 기술 명세](../features/approvals/form-types.md) - 섹션 12, 14 업데이트 + +--- + +**최종 업데이트**: 2026-03-06 diff --git a/sam/docs/features/rd/sound-logo-studio.md b/sam/docs/features/rd/sound-logo-studio.md new file mode 100644 index 0000000..d21ed27 --- /dev/null +++ b/sam/docs/features/rd/sound-logo-studio.md @@ -0,0 +1,244 @@ +# 사운드 로고 스튜디오 + +> **작성일**: 2026-03-08 +> **상태**: 운영 중 +> **라우트**: `/rd/sound-logo` +> **뷰**: `resources/views/rd/sound-logo/index.blade.php` + +--- + +## 1. 개요 + +사운드 로고 스튜디오는 기업 시그니처 사운드(사운드 로고)를 제작하는 올인원 도구이다. Web Audio API 기반 시퀀서, Gemini AI 어시스트, TTS 음성 오버레이, Lyria RealTime BGM 생성을 하나의 SPA에서 통합 제공한다. + +**핵심 기능:** +- 시퀀서 기반 사운드 로고 수동/프리셋 제작 +- Gemini AI가 프롬프트 기반으로 음표 시퀀스 자동 설계 +- Gemini TTS로 나레이션 음성 생성 (여성/남성/아이, 30종 음성, 속도 조절) +- Lyria RealTime WebSocket으로 AI 배경음악 실시간 생성 +- 시퀀서/BGM 상호 배타적 재생 + TTS 공통 합성 +- WAV 내보내기 + +--- + +## 2. 아키텍처 + +### 2.1 3레이어 오디오 구조 + +``` +┌─────────────────────────────────────────────────────────┐ +│ Layer 1: 사운드 로고 (시퀀서 또는 AI BGM — 상호 배타적) │ +│ ├── A) 시퀀서 (수동 편집 / 프리셋 / AI 생성) │ +│ └── B) AI 배경음악 (Lyria RealTime) │ +├─────────────────────────────────────────────────────────┤ +│ Layer 2: 음성 TTS (Gemini) ─── 양쪽 모드 공통 │ +├─────────────────────────────────────────────────────────┤ +│ DynamicsCompressor (클리핑 방지) → AudioContext.dest │ +└─────────────────────────────────────────────────────────┘ +``` + +- **시퀀서 모드**: 수동/프리셋/AI 생성 음표 + TTS 합성. BGM 제외. +- **BGM 모드**: AI 배경음악 + TTS 합성. 시퀀서 음표 제외. +- 판단 기준: `bgmBuffer` 존재 여부 + +### 2.2 기술 스택 + +| 계층 | 기술 | 설명 | +|------|------|------| +| 프론트엔드 | Blade + Alpine.js | 단일 SPA | +| 오디오 엔진 | Web Audio API | OscillatorNode, BufferSourceNode, DynamicsCompressorNode | +| AI 시퀀서 | Gemini 2.5 Flash | 프롬프트 → JSON 음표 시퀀스 | +| TTS | `gemini-2.5-flash-preview-tts` | 30종 음성, Director's Note 스타일 제어 | +| BGM | Lyria RealTime (WebSocket) | `models/lyria-realtime-exp`, 48kHz 스테레오 PCM | +| 저장 | 없음 (클라이언트 전용) | WAV 내보내기로 결과물 보존 | + +--- + +## 3. 시퀀서 (Layer 1-A) + +### 3.1 입력 모드 + +| 모드 | 설명 | +|------|------| +| **수동** | 음표 그리드에서 직접 추가/삭제/편집 | +| **프리셋** | 사전 정의된 사운드 패턴 선택 (기업 시그널, 알림음 등) | +| **AI 생성** | 프롬프트 입력 → Gemini가 음표 시퀀스 JSON 반환 | + +### 3.2 음표 데이터 구조 + +```json +{ + "type": "note | chord | rest", + "note": "C5", + "chord": ["C4", "E4", "G4"], + "duration": 0.2, + "velocity": 0.8 +} +``` + +### 3.3 신디사이저 설정 + +| 파라미터 | 범위 | 설명 | +|---------|------|------| +| `synth` | sine, triangle, square, sawtooth | 파형 | +| `volume` | 0~1 | 마스터 볼륨 | +| `adsr.attack` | 1~500ms | 어택 | +| `adsr.decay` | 10~1000ms | 디케이 | +| `adsr.sustain` | 0~1.0 | 서스테인 | +| `adsr.release` | 10~3000ms | 릴리즈 | +| `reverb` | 0~1 | 리버브 양 | + +--- + +## 4. 음성 오버레이 — TTS (Layer 2) + +### 4.1 음성 카테고리 + +| 카테고리 | 음성 수 | 주요 음성 | +|---------|---------|----------| +| **여성** | 9종 | Kore(단정), Aoede(산뜻), Leda(따뜻), Zephyr(차분) 등 | +| **남성** | 9종 | Puck(밝음), Charon(깊음), Orus(안정), Fenrir(무게) 등 | +| **아이** | 5종 | Leda 기반(여아), Puck 기반(남아) 등 | + +### 4.2 속도 조절 + +| 단계 | Director's Note | +|------|----------------| +| 1 (매우 느림) | "아주 천천히 또박또박 말해주세요." | +| 2 (느림) | "조금 느린 속도로 말해주세요." | +| 3 (보통) | (지시문 없음) | +| 4 (빠름) | "조금 빠른 속도로 말해주세요." | +| 5 (매우 빠름) | "아주 빠른 속도로 말해주세요." | + +### 4.3 오디오 형식 + +- 출력: `audio/L16;rate=24000` (16-bit PCM, 24kHz, 모노, little-endian) +- 디코딩: `DataView.getInt16(offset, true)` → Float32 변환 + +--- + +## 5. AI 배경음악 — Lyria (Layer 1-B) + +### 5.1 WebSocket 프로토콜 + +``` +브라우저 ──WebSocket──→ Google Lyria RealTime API + (wss://generativelanguage.googleapis.com/ws/...BidiGenerateMusic) +``` + +서버는 API 키만 전달(`GET /lyria-config`), 실제 WebSocket 통신은 브라우저에서 직접 수행한다. + +### 5.2 메시지 흐름 + +``` +1. setup → { setup: { model: "models/lyria-realtime-exp" } } +2. (수신) ← { setupComplete: {} } +3. 프롬프트 → { clientContent: { weightedPrompts: [...] } } +4. 설정 → { musicGenerationConfig: { bpm, density, brightness, scale, temperature } } +5. 재생 → { playbackControl: "PLAY" } +6. (수신 반복) ← { serverContent: { audioChunks: [{ data: "base64..." }] } } +7. 정지 → { playbackControl: "STOP" } +8. (종료) ← WebSocket close +``` + +### 5.3 BGM 파라미터 + +| 파라미터 | 범위 | 설명 | +|---------|------|------| +| `bgmPrompt` | 텍스트 | 음악 분위기 설명 | +| `bgmBpm` | 60~180 | BPM | +| `bgmDensity` | 0~100 | 밀도 (0~1 변환) | +| `bgmBrightness` | 0~100 | 밝기 (0~1 변환) | +| `bgmScale` | C_MAJOR 등 | 음계 | +| `bgmDuration` | 5~60초 | 생성 길이 | + +### 5.4 오디오 형식 + +- 출력: 16-bit PCM, 48kHz, 스테레오, little-endian +- WAV 헤더 감지 시 `decodeAudioData` fallback + +--- + +## 6. API 엔드포인트 + +### 6.1 사운드 로고 (RdController) + +| HTTP | URI | 메서드 | 설명 | +|------|-----|--------|------| +| GET | `/rd/sound-logo` | `soundLogo()` | 스튜디오 페이지 | +| POST | `/rd/sound-logo/generate` | `soundLogoGenerate()` | AI 음표 시퀀스 생성 (Gemini) | +| POST | `/rd/sound-logo/tts` | `soundLogoTts()` | TTS 음성 생성 (Gemini TTS) | +| GET | `/rd/sound-logo/lyria-config` | `soundLogoLyriaConfig()` | Lyria WebSocket 접속 설정 반환 | + +### 6.2 CM송/나레이션 (CmSongController) + +| HTTP | URI | 메서드 | 설명 | +|------|-----|--------|------| +| GET | `/rd/cm-song` | `index()` | 나레이션 목록 | +| GET | `/rd/cm-song/create` | `create()` | 나레이션 제작 | +| POST | `/rd/cm-song` | `store()` | 나레이션 저장 | +| GET | `/rd/cm-song/{id}` | `show()` | 나레이션 상세 | +| DELETE | `/rd/cm-song/{id}` | `destroy()` | 나레이션 삭제 | +| GET | `/rd/cm-song/{id}/download` | `download()` | 음성 파일 다운로드 | +| POST | `/rd/cm-song/generate-lyrics` | `generateLyrics()` | AI 가사 생성 (Gemini) | +| POST | `/rd/cm-song/generate-audio` | `generateAudio()` | TTS 음성 생성 | + +### 6.3 CM송 데이터 모델 + +| 모델 | 테이블 | 설명 | +|------|--------|------| +| `CmSong` | `cm_songs` | 나레이션 (회사명, 업종, 가사, 음성파일) | + +**저장 경로**: `tenant` 디스크 → `cm-songs/{tenant_id}/{filename}.wav` + +--- + +## 7. 오디오 엔진 상세 + +### 7.1 마스터 출력 체인 + +``` +각 소스 (Oscillator / BufferSource) + → GainNode (개별 볼륨) + → DynamicsCompressorNode (마스터 리미터) + → AudioContext.destination +``` + +**컴프레서 설정:** +- threshold: -6dB +- knee: 10dB +- ratio: 12:1 +- attack: 3ms +- release: 150ms + +### 7.2 WAV 내보내기 + +`OfflineAudioContext`로 오프라인 렌더링 후 `bufferToWav()` 변환. +- 샘플레이트: 44,100Hz +- 채널: 2 (스테레오) +- 비트: 16-bit PCM +- 오프라인 컨텍스트에도 동일한 DynamicsCompressor 적용 + +--- + +## 8. 관련 파일 + +| 파일 | 설명 | +|------|------| +| `resources/views/rd/sound-logo/index.blade.php` | SPA 뷰 (Alpine.js, ~2100줄) | +| `app/Http/Controllers/RdController.php` | 사운드 로고 API (4 메서드) | +| `app/Http/Controllers/Rd/CmSongController.php` | CM송/나레이션 CRUD (8 메서드) | +| `app/Models/Rd/CmSong.php` | CM송 모델 | +| `app/Helpers/AiTokenHelper.php` | Gemini 토큰 사용량 추적 | + +--- + +## 관련 문서 + +- [R&D 메뉴 개요](README.md) — R&D 전체 메뉴 구조 +- [AI 분석 리포트](../ai/README.md) — Gemini API 활용 패턴 참고 +- [사운드 로고 생성기 기획서](../../plans/sound-logo-generator-plan.md) — 초기 기획 + +--- + +**최종 업데이트**: 2026-03-08