fix: [sound-logo] Lyria WebSocket 메시지 키 형식 수정

- client_content → clientContent (camelCase)
- music_generation_config 중첩 제거 → musicGenerationConfig 최상위
- playback_control 중첩 제거 → playbackControl 최상위
- WAV 헤더 감지 시 decodeAudioData fallback 추가
This commit is contained in:
김보곤
2026-03-08 14:38:51 +09:00
parent 697560b2de
commit 2f1ea3b369

View File

@@ -1836,25 +1836,23 @@ function soundLogo() {
this.bgmProgress = '프롬프트 설정 중...';
ws.send(JSON.stringify({
client_content: {
clientContent: {
weightedPrompts: [{ text: this.bgmPrompt, weight: 1.0 }]
}
}));
ws.send(JSON.stringify({
music_generation_config: {
musicGenerationConfig: {
bpm: this.bgmBpm,
density: this.bgmDensity / 100,
brightness: this.bgmBrightness / 100,
scale: this.bgmScale,
temperature: 1.0,
}
musicGenerationConfig: {
bpm: this.bgmBpm,
density: this.bgmDensity / 100,
brightness: this.bgmBrightness / 100,
scale: this.bgmScale,
temperature: 1.0,
}
}));
ws.send(JSON.stringify({
playback_control: { playbackControl: 'PLAY' }
playbackControl: 'PLAY'
}));
playStartTime = Date.now();
this.bgmProgress = '음악 생성 중... 0/' + duration + '초';
@@ -1920,7 +1918,7 @@ function soundLogo() {
setTimeout(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
playback_control: { playbackControl: 'STOP' }
playbackControl: 'STOP'
}));
setTimeout(() => {
if (ws.readyState === WebSocket.OPEN) ws.close();
@@ -1937,7 +1935,8 @@ function soundLogo() {
async decodeBgmChunks(chunks) {
try {
// base64 청크들을 합쳐서 하나의 PCM 데이터로 변환
console.log('[Lyria] 오디오 디코딩 시작: ' + chunks.length + '개 청크');
// base64 청크들을 합쳐서 하나의 바이트 배열로 변환
const allBytes = [];
for (const chunk of chunks) {
const binaryStr = atob(chunk);
@@ -1946,8 +1945,28 @@ function soundLogo() {
}
}
const pcmData = new Uint8Array(allBytes);
console.log('[Lyria] 전체 PCM 크기:', pcmData.length, 'bytes');
// Lyria RealTime: 16-bit PCM, stereo, 48kHz (little-endian)
if (pcmData.length < 4) {
this.bgmError = '유효한 오디오 데이터가 없습니다.';
this.bgmLoading = false;
return;
}
const ctx = this.getAudioCtx();
// WAV 헤더 감지 (RIFF 매직넘버) → decodeAudioData 사용
const hasWavHeader = pcmData[0] === 0x52 && pcmData[1] === 0x49 && pcmData[2] === 0x46 && pcmData[3] === 0x46;
if (hasWavHeader) {
console.log('[Lyria] WAV 헤더 감지, decodeAudioData 사용');
const buffer = await ctx.decodeAudioData(pcmData.buffer.slice(0));
this.bgmBuffer = buffer;
this.toast('배경음악 생성 완료 (' + buffer.duration.toFixed(1) + '초)');
return;
}
// Raw PCM: Lyria RealTime — 16-bit PCM, stereo, 48kHz (little-endian)
console.log('[Lyria] Raw PCM 디코딩: 48kHz, stereo, 16-bit LE');
const sampleRate = 48000;
const numChannels = 2;
const bytesPerSample = 2;
@@ -1959,7 +1978,6 @@ function soundLogo() {
return;
}
const ctx = this.getAudioCtx();
const buffer = ctx.createBuffer(numChannels, numSamples, sampleRate);
const view = new DataView(pcmData.buffer);
@@ -1968,7 +1986,7 @@ function soundLogo() {
for (let i = 0; i < numSamples; i++) {
const byteOffset = (i * numChannels + ch) * bytesPerSample;
if (byteOffset + 1 < pcmData.length) {
channelData[i] = view.getInt16(byteOffset, true) / 32768; // little-endian
channelData[i] = view.getInt16(byteOffset, true) / 32768;
}
}
}
@@ -1976,6 +1994,7 @@ function soundLogo() {
this.bgmBuffer = buffer;
this.toast('배경음악 생성 완료 (' + buffer.duration.toFixed(1) + '초)');
} catch (e) {
console.error('[Lyria] 오디오 디코딩 실패:', e);
this.bgmError = '오디오 디코딩 실패: ' + e.message;
this.toast('배경음악 오디오 처리에 실패했습니다.', 'error');
} finally {