Skip to content

GodotSteamKit Tutorials - Voice

By Gramps


This tutorial will cover the basics of using the Steam Voice custom node from the GodotSteamKit.

Usage

Once you have the GodotSteamKit installed, there will be a new node: SteamVoice which just a basic Node node. Make sure this is added to any scene you want voice chat to work in or your game's setting section if you want to test voice chat functionality with loopback.

Recording Voice

Just like in our regular Voice tutorial, you will probably want to offer both open mic and press-to-talk options with a toggle to switch between the two and, especially for in-game voice chat, attach these to action hotkeys. Borrowing the example from other tutorial:

var is_open_mic: bool = false

func _input(event: InputEvent) -> void:
    if event.is_action_pressed("voice_toggle"):
        is_open_mic = not is_open_mic
        record_voice(steam_id, is_open_mic)
    if event.is_action_pressed("voice_talk"):
        record_voice(steam_id)
    if event.is_action_released("voice_talk"):
        record_voice(steam_id, false)

For our example, we create two new input actions: voice_toggle and voice_talk, as well as a new variable to keep track of whether the mic is on or not. Both will trigger the same record_voice() function in the Voice node which takes two parameters: steam_id and is_recording, the latter defaults to true.

You must pass the Steam ID of the local user to this function, though you could also just alter the node's script to always use your local user's Steam ID instead.

Sending The Voice Data

The node's script does require some minor alterations to send the voice data to other players unless you are just testing the voice audio using use_loopback. We will cover both RPCs and Steam Networking.

RPC

If you want to use RPCs, you can modify line 63 (where the comment is) to an RPC the process_voice_data().

func _get_voice_data() -> void:
    var voice_data: Dictionary = Steam.getVoice()
    if voice_data['result'] == Steam.VoiceResult.VOICE_RESULT_OK and voice_data['written'] > 0:
        process_voice_data.rpc(voice_data['buffer'])

You will also want to add an @rpc line above the func process_voice_data(), starting at line 69:

@rpc("any_peer", "call_remote", "unreliable")
func process_voice_data(voice_data: PackedByteArray) -> void:

Steam Networking

Based on our Networking Message tutorial, you can modify line 63 (where the comment is) to a packet like:

func _get_voice_data() -> void:
    var voice_data: Dictionary = Steam.getVoice()
    if voice_data['result'] == Steam.VoiceResult.VOICE_RESULT_OK and voice_data['written'] > 0:
        Networking.send_message(0, {"voice": voice_data['result']})

Your packet logic may vary but the above version sends the voice data to everyone and specifies the packet as 'voice'. On the receiving end, our networking script triggers a signal which connects to the process_voice_data() function in the next section.

Audio Testing

However, if you are using the node to do voice testing in your game's audio settings, there really isn't anything else you need to do except toggled use_loopback in the Inspector or pass true to it in your code.

Playing The Voice Data

Each of the above methods should connect to the node's process_voice_data(voice_data: PackedByteArray) function which will process the data and pass it to the internal AudioStreamPlayer.

And that is it.

Properties

SAMPLE_RATE

Set as the default sample rate. Steam Voice only uses a range of 11025 to 48000; do not set this outside of that range if you change it.

use_loopback

Whether the local player can hear themselves or not. This should not be used in-game.

use_optimal_sample_rate

Whether to use Steam's suggested optimal sample rate or not. This will set it to whatever getVoiceOptimalSampleRate() returns. For me, using the optimal rate made the voice sound high-pitched though.

Functions

process_voice_data

Process the voice buffer and play it out through the voice_playback stream. This must be the voice data buffer returned from getVoice().

record_voice

Record the voice of the local user. You must pass the local user's Steam ID.