diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp index 10e0456..fb92f5f 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp @@ -1224,6 +1224,11 @@ void UPS_AI_ConvAgent_ElevenLabsComponent::HandleAudioReceived(const TArray= 0) ? (NetDbgCVar > 0) : bDebug; + if (OpusEncoder.IsValid()) { // Opus path: compress then send. @@ -1235,14 +1240,28 @@ void UPS_AI_ConvAgent_ElevenLabsComponent::HandleAudioReceived(const TArray CompressedData; CompressedData.Append(OpusWorkBuffer.GetData(), CompressedSize); + + if (bNetAudioDebug) + { + const float Ratio = (CompressedSize > 0) + ? static_cast(PCMData.Num()) / static_cast(CompressedSize) + : 0.0f; + UE_LOG(LogPS_AI_ConvAgent_ElevenLabs, Log, + TEXT("[NET-SRV] Opus audio chunk: %u bytes sent (raw %d → %.1fx compression)."), + CompressedSize, PCMData.Num(), Ratio); + } + MulticastReceiveAgentAudio(CompressedData); } } else { // Fallback: send raw PCM (no compression). ~32 KB/s at 16kHz 16-bit mono. - // Fine for LAN; revisit with proper Opus if internet play is needed. - // UE5 limits replicated TArrays to 65535 elements, so we must chunk. + // Only hit if Opus init failed. Chunk small so the Unreliable RPC is + // NOT auto-promoted to reliable when fragmented: UE re-sends an + // unreliable bunch reliably once it splits into more than ~8 partial + // bunches, which would reintroduce the reliable-buffer overflow. + // ~4 KB ≈ 4 bunches → stays unreliable. static bool bWarnedOnce = false; if (!bWarnedOnce) { @@ -1251,13 +1270,21 @@ void UPS_AI_ConvAgent_ElevenLabsComponent::HandleAudioReceived(const TArray Chunk; Chunk.Append(PCMData.GetData() + Offset, ChunkSize); + + if (bNetAudioDebug) + { + UE_LOG(LogPS_AI_ConvAgent_ElevenLabs, Warning, + TEXT("[NET-SRV] RAW PCM chunk: %d bytes sent (NO compression — Opus disabled)."), + ChunkSize); + } + MulticastReceiveAgentAudio(Chunk); Offset += ChunkSize; } diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_ElevenLabsComponent.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_ElevenLabsComponent.h index 8581aaf..2712eb0 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_ElevenLabsComponent.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_ElevenLabsComponent.h @@ -484,8 +484,12 @@ public: UFUNCTION(Server, Reliable) void ServerRequestInterrupt(); - /** Broadcast agent audio to all clients (Opus-compressed or raw PCM fallback). */ - UFUNCTION(NetMulticast, Reliable) + /** Broadcast agent audio to all clients (Opus-compressed or raw PCM fallback). + * Unreliable: realtime audio — a lost/oversized packet is dropped (minor + * glitch) rather than backing up the reliable buffer and dropping the + * connection. Keep each call small (Opus ~1-4KB) so it isn't auto-promoted + * to reliable when fragmented into partial bunches. */ + UFUNCTION(NetMulticast, Unreliable) void MulticastReceiveAgentAudio(const TArray& AudioData); /** Notify all clients that the agent started speaking (first audio chunk). */