How can I create live voice chat for my multiplayer game?

Godot Version

4.7.1

Question

for the last week or so I’ve been trying to implement a live voice chat system into my game, but so far I haven’t gotten any where.

I’ve followed a good 3 tutorials but the result has always been about the same, being all I hear is static, despite the code being 1:1. My only guess is that it isn’t sending the right voice data or something in that boat, but I’m not sure how to fix it.

The audio bus (if its not muted) for recording is replaying my voice back to me perfectly so I know that’s working.

I was originally using an amplitude method for detecting voice input, which kinda worked. At some point I swapped over to and RMS method, which broke it, and after going back to amplitude it just wasn’t detecting anything anymore so not sure what I did there


# // Constants //
const VCInputThreshold := 0.005;

# // Variables //
var RecordEffect : AudioEffectCapture; ## Effect used for recording mic audio
var VCToggled : bool = false; ## Whether or not VC is toggled on. Used when VC mode is set to toggled
var OutputBuffers : Dictionary[Node, PackedFloat32Array];
func _process(_delta):
	if CanSpeak : ## Dont worry about this, its true
		ProcessMic();
	
	# // Output
	ProcessOutputs();
func AddOutputAudio(Output : Node, AudioData : PackedFloat32Array) : ## adds an audio to an output to be played
	if !Output is AudioStreamPlayer and !Output is AudioStreamPlayer3D : return;
	if !Output.stream or !Output.stream in AudioStreamGenerator : print("Output has invalid stream."); return;
	
	if !Output in OutputBuffers :
		OutputBuffers[Output] = PackedFloat32Array();
		
		if !Output.playing :
			Output.play();
		
		Output.stream.mix_rate = Steam.getVoiceOptimalSampleRate();
	
	OutputBuffers[Output].append_array(AudioData);

# // processing

func ProcessMic() : ## Processes the users mic input
	var SterioData : PackedVector2Array = RecordEffect.get_buffer(RecordEffect.get_frames_available());
	
	if SterioData.size() > 0 :
		
		# // Acquire data
		var data := PackedFloat32Array();
		data.resize(SterioData.size());
		var SumOfSquares := 0.0;
		
		for Index in range(SterioData.size()) :
			var Value : float = (SterioData[Index].x + SterioData[Index].y) / 2;
			#MaxAmplitude = max(Value, MaxAmplitude);
			SumOfSquares += Value * Value;
			data[Index] = Value;
		
		var MeanSquare : float = SumOfSquares / SterioData.size();
		
		if sqrt(MeanSquare) < VCInputThreshold : # Too quite, cancel.
			return
		
		rpc_id(1, "_send_player_audio", data);

func ProcessOutputs() : ## Processes all outputs
	for Output : Node in OutputBuffers :
		if !Output is AudioStreamPlayer and !Output is AudioStreamPlayer3D : continue;
		
		var Playback : AudioStreamGeneratorPlayback = Output.get_stream_playback();
		
		print("Output: ", Output.name);
		
		if OutputBuffers[Output].size() <= 0 :
			Playback.push_frame(Vector2.ZERO);
		else :
			for i in range (min(Playback.get_frames_available(), OutputBuffers[Output].size())) :
				Playback.push_frame(Vector2(OutputBuffers[Output][0], OutputBuffers[Output][0]));
				OutputBuffers[Output].remove_at(0);

I’ll also note that the RPC functions used to relay the data aren’t modifying it in anyway and are delivering it to the correct clients. If its important, I am using GodotSteam for some of the multiplayer stuff

So if anyone knows of any working tutorials I could try or might know what I’m doing wrong please let me know! Thanks in advanced