@@ -50,8 +50,10 @@ public async Task<TextToSpeechResponse> TextToSpeechAsync(TextToSpeechRequest re
5050 return voiceResponse ;
5151 }
5252
53- // 스트림 기반으로 음성 데이터 읽기 (LOH 방지)
54- voiceResponse . AudioData = await ReadAudioDataWithPoolAsync ( response . Content ) ;
53+ // ArrayPool 기반으로 음성 데이터 읽기 (LOH 방지)
54+ var ( memoryOwner , dataSize ) = await ReadAudioDataWithPoolAsync ( response . Content ) ;
55+ voiceResponse . AudioMemoryOwner = memoryOwner ;
56+ voiceResponse . AudioDataSize = dataSize ;
5557 voiceResponse . ContentType = response . Content . Headers . ContentType ? . ToString ( ) ;
5658
5759 if ( response . Headers . Contains ( "X-Audio-Length" ) )
@@ -64,7 +66,7 @@ public async Task<TextToSpeechResponse> TextToSpeechAsync(TextToSpeechRequest re
6466 }
6567
6668 _logger . LogDebug ( "[TTS][Response] 오디오 길이: {AudioLength:F2}초, ContentType: {ContentType}, 바이트: {Length}, 소요시간: {Elapsed}ms" ,
67- voiceResponse . AudioLength , voiceResponse . ContentType , voiceResponse . AudioData ? . Length ?? 0 , elapsed ) ;
69+ voiceResponse . AudioLength , voiceResponse . ContentType , voiceResponse . AudioDataSize , elapsed ) ;
6870
6971 return voiceResponse ;
7072 }
@@ -82,42 +84,50 @@ public async Task<TextToSpeechResponse> TextToSpeechAsync(TextToSpeechRequest re
8284 /// <summary>
8385 /// ArrayPool을 사용하여 스트림 기반으로 음성 데이터를 읽습니다 (LOH 할당 방지)
8486 /// </summary>
85- private async Task < byte [ ] ? > ReadAudioDataWithPoolAsync ( HttpContent content )
87+ private async Task < ( IMemoryOwner < byte > ? , int ) > ReadAudioDataWithPoolAsync ( HttpContent content )
8688 {
8789 const int chunkSize = 32768 ; // 32KB 청크 크기
88- byte [ ] ? buffer = null ;
90+ byte [ ] ? readBuffer = null ;
8991 MemoryStream ? memoryStream = null ;
9092
9193 try
9294 {
93- buffer = _arrayPool . Rent ( chunkSize ) ;
95+ readBuffer = _arrayPool . Rent ( chunkSize ) ;
9496 memoryStream = new MemoryStream ( ) ;
9597
9698 using var stream = await content . ReadAsStreamAsync ( ) ;
9799 int bytesRead ;
98100
99101 // 청크 단위로 데이터 읽어서 MemoryStream에 복사
100- while ( ( bytesRead = await stream . ReadAsync ( buffer , 0 , chunkSize ) ) > 0 )
102+ while ( ( bytesRead = await stream . ReadAsync ( readBuffer , 0 , chunkSize ) ) > 0 )
101103 {
102- await memoryStream . WriteAsync ( buffer , 0 , bytesRead ) ;
104+ await memoryStream . WriteAsync ( readBuffer , 0 , bytesRead ) ;
103105 }
104106
105- var result = memoryStream . ToArray ( ) ;
107+ var totalSize = ( int ) memoryStream . Length ;
108+
109+ // ArrayPool에서 최종 데이터 크기만큼 메모리 할당
110+ var resultMemoryOwner = MemoryPool < byte > . Shared . Rent ( totalSize ) ;
111+
112+ // MemoryStream에서 최종 메모리로 복사
113+ memoryStream . Position = 0 ;
114+ await memoryStream . ReadAsync ( resultMemoryOwner . Memory . Slice ( 0 , totalSize ) ) ;
115+
106116 _logger . LogDebug ( "[TTS][ArrayPool] 음성 데이터 읽기 완료: {Size} bytes, 청크 크기: {ChunkSize}" ,
107- result . Length , chunkSize ) ;
117+ totalSize , chunkSize ) ;
108118
109- return result ;
119+ return ( resultMemoryOwner , totalSize ) ;
110120 }
111121 catch ( Exception ex )
112122 {
113123 _logger . LogError ( ex , "[TTS][ArrayPool] 음성 데이터 읽기 실패" ) ;
114- return null ;
124+ return ( null , 0 ) ;
115125 }
116126 finally
117127 {
118- if ( buffer != null )
128+ if ( readBuffer != null )
119129 {
120- _arrayPool . Return ( buffer ) ;
130+ _arrayPool . Return ( readBuffer ) ;
121131 }
122132 memoryStream ? . Dispose ( ) ;
123133 }
0 commit comments