Using New Audio Instances, but cant figure out how to make it server sided

Hello all,

Thanks for your help.
So currently my system only somewhat works, it works, its just only works on the client.

I am trying to route everyone’s mics as long as their AudioDeviceInput is not muted, and they are on the authorized team to a single ChannelMixer (All players → Channel Mixer). And then also route this single Channel Mixer to all players (Channel Mixer → All Players). Also when I say all players I mean all players that match a single criteria. I also added reverb to this channel mixer just so I can identify weather this works or not. Currently it is working, but only the client can hear it (I know this because when I tested with two players only I could hear my own reverb, same for the other player).

Local Script in StarterPlayerScripts:

local AudioOutput 
local AudioInput

function UpdatePlayer()
	if game.Players.LocalPlayer.Team == game.Teams["Authorized Team"] then
		if AudioOutput == nil then
			-- Create Audio Output (for listening to the shared channel)
			AudioOutput = Instance.new("AudioDeviceOutput", game.Workspace.Camera)
			local wireOut = Instance.new("Wire", AudioOutput)
			wireOut.SourceInstance = game.Workspace.SharedRadioChannelMixer.AudioReverb
			wireOut.TargetInstance = AudioOutput

			-- Create Audio Input (for sending to the shared channel)
			AudioInput = Instance.new("AudioDeviceInput", game.Workspace.Camera)
			AudioInput.Player = game.Players.LocalPlayer
			AudioInput.Muted = true
			local wireIn = Instance.new("Wire", AudioInput)
			wireIn.SourceInstance = AudioInput
			wireIn.TargetInstance = game.Workspace.SharedRadioChannelMixer

			-- UI Toggle for muting/unmuting microphone
			local toggleButton = game.Players.LocalPlayer.PlayerGui:FindFirstChild("ToggleUI") and game.Players.LocalPlayer.PlayerGui.ToggleUI:FindFirstChild("ToggleButton")
			if toggleButton then
				toggleButton.MouseButton1Click:Connect(function()
					AudioInput.Muted = not AudioInput.Muted
					toggleButton.Text = tostring(AudioInput.Muted)
				end)
				toggleButton.Text = tostring(AudioInput.Muted)
			end
		end
	else
		if AudioOutput ~= nil then
			AudioOutput:Destroy()
			AudioOutput = nil
		end

		if AudioInput ~= nil then
			AudioInput:Destroy()
			AudioInput = nil
		end
	end
end

repeat task.wait() until game.Players.LocalPlayer.Character
UpdatePlayer()
game.Players.LocalPlayer:GetAttributeChangedSignal("Team"):Connect(function()
	UpdatePlayer()
end)

game.Players.LocalPlayer.CharacterAdded:Connect(function()
	UpdatePlayer()
end)

Image of the explorer:


I know my issue is probably because I am only using a local script but I am not sure how I would incorporate this into a server sided thing.

Thanks,
abcxomisgood

You cannot fully convert this script to server-side because AudioDeviceInput, AudioDeviceOutput, Wire, and most voice-related APIs in Roblox require client-side context. These instances are Local-only and will not replicate from the server.

Server
local rs = game:GetService("ReplicatedStorage")
local ev = Instance.new("RemoteEvent")
ev.Name = "VoiceToggle"
ev.Parent = rs

game.Players.PlayerAdded:Connect(function(plr)
	local function checkTeam()
		ev:FireClient(plr, plr.Team == game.Teams["Authorized Team"])
	end
	plr:GetPropertyChangedSignal("Team"):Connect(checkTeam)
	checkTeam()
end)
Client
local rs = game:GetService("ReplicatedStorage")
local ev = rs:WaitForChild("VoiceToggle")

local cam = workspace.CurrentCamera
local plr = game.Players.LocalPlayer
local gui = plr:WaitForChild("PlayerGui")

local out, input

function setupVoice(state)
	if state then
		if not out then
			out = Instance.new("AudioDeviceOutput", cam)
			local wOut = Instance.new("Wire", out)
			wOut.SourceInstance = workspace.SharedRadioChannelMixer.AudioReverb
			wOut.TargetInstance = out

			input = Instance.new("AudioDeviceInput", cam)
			input.Player = plr
			input.Muted = true
			local wIn = Instance.new("Wire", input)
			wIn.SourceInstance = input
			wIn.TargetInstance = workspace.SharedRadioChannelMixer

			local b = gui:FindFirstChild("ToggleUI")
			b = b and b:FindFirstChild("ToggleButton")
			if b then
				b.MouseButton1Click:Connect(function()
					input.Muted = not input.Muted
					b.Text = tostring(input.Muted)
				end)
				b.Text = tostring(input.Muted)
			end
		end
	else
		if out then out:Destroy() out = nil end
		if input then input:Destroy() input = nil end
	end
end

ev.OnClientEvent:Connect(setupVoice)

Add a RemoteEvent named VoiceSetup to ReplicatedStorage (or rename it)
Think that’s the furthest it can be pushed to server-side.

I found a fix to make it server sided, but now I think I broke roblox’s default voice chat somehow because other players can only hear when the AudioDeviceInput instance I Created is not muted instead of still being able to hear other players in proximity with ROBLOX"s default voice chat.
Im not sure how I even could have possibly broke it but maybe someone has more knowledge on this than I do.

Server:

function UpdatePlayer(plr:Player)
	if plr.Team == game.Teams["Authorized Team"] then
		local Mic = Instance.new("AudioDeviceInput", plr)
		Mic.Player = plr
		Mic.Name = "RadioMicrophone"
		Mic.Muted = true
		local Wire = Instance.new("Wire", Mic)
		Wire.TargetInstance = game.Workspace.SharedRadioChannelMixer
		Wire.SourceInstance = Mic
	else
		if plr:FindFirstChild("RadioMicrophone") then
			plr.RadioMicrophone:Destroy()
		end
	end
end

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function()
		UpdatePlayer(plr)
	end)
	plr:GetAttributeChangedSignal("Team"):Connect(function()
		UpdatePlayer(plr)
	end)
end)

Client:

local AudioOutput

function UpdatePlayer()
	if game.Players.LocalPlayer.Team == game.Teams["Authorized Team"] then
		if AudioOutput == nil then
			-- Create Audio Output (for listening to the shared channel)
			AudioOutput = Instance.new("AudioDeviceOutput", game.Workspace.Camera)
			local wireOut = Instance.new("Wire", AudioOutput)
			wireOut.SourceInstance = game.Workspace.SharedRadioChannelMixer.AudioReverb
			wireOut.TargetInstance = AudioOutput
			
		end
	else
		if AudioOutput ~= nil then
			AudioOutput:Destroy()
			AudioOutput = nil
		end

	end
end

repeat task.wait() until game.Players.LocalPlayer.Character
UpdatePlayer()
game.Players.LocalPlayer:GetAttributeChangedSignal("Team"):Connect(function()
	UpdatePlayer()
end)

game.Players.LocalPlayer.CharacterAdded:Connect(function()
	UpdatePlayer()
end)

Tool (Regular script, not local script):

repeat task.wait() until game.Players[script.Parent.Parent.Parent.Name]

local plr:Player = script.Parent.Parent.Parent
print(plr)
local AudioInput = plr:WaitForChild("RadioMicrophone")

script.Parent.Activated:Connect(function()
	AudioInput.Muted = not AudioInput.Muted
	if AudioInput.Muted == true then
		script.Parent.Handle.Part.BrickColor = BrickColor.new("Really red") else script.Parent.Handle.Part.BrickColor = BrickColor.new("Neon green")
	end
end)