Writing a Mumble Bot in Ruby



Mumble is an open-source voice communication tool with low latency ideal for gaming. It is an alternative to the non-free TeamSpeak and Skype options. The Ruby gem mumble-ruby provides a library to connect and interact with Mumble as a client. These code snippets demonstrate how to connect and communicate in a chat room and private messages. At the very end, there is a fully functional command line chat client that is ready to use to chat on the DevDungeon.com Mumble server!

For more documentation, see the official GitHub mumble-ruby project. Note that it requires Ruby 2.1.0 or greater and the OPUS codec.

Install Prerequisites

# For Debian based distributions like Ubuntu/Linux Mint
# I couldn't get it to work on Windows
sudo apt-get install libopus0
sudo apt-get install libopus-dev

# Install the gem
sudo gem install mumble-ruby

Connecting and Disconnecting

require 'mumble-ruby'

# Create a new client with a few configuration
# values to override the defaults
client = Mumble::Client.new('mumble.devdungeon.com') do |conf|
        # Avoid spaces in username
conf.username = "DevDungeonNeophyte"  # An unregistered name or your registered name
conf.password = ""  # Needed if username is registered


# Wait a couple seconds to establish connection
sleep 2

# Do something with client here...


Configuring All Clients Globally

To configure all clients globally use the following code. New clients created after this will inherit these new defaults. All of the values used here Are the actual defaults, so these won't change anything. If you did want to change the values though this is how you would do it.

Mumble.configure do |conf|
    # Audio configuration
    conf.sample_rate = 48000 # Khz
    conf.bitrate = 32000 # Kb/sec
    # The cert_dir specifies where to look for Certificates
    # It will create a subfolder for each user
    conf.ssl_cert_opts[:cert_dir] = File.expand_path("./")
    conf.ssl_cert_opts[:country_code] = 'US'
    conf.ssl_cert_opts[:organization] = 'github.com'
    conf.ssl_cert_opts[:organization_unit] = 'Engineering'

Join Channel

# Accepts the room name or ID
client.join_channel('The Cellar')

List All Channels

client.channels.each do |channel|
puts channel.inspect

List Users

client.users.each do |user|
puts user.inspect

Sending Messages

# Text message to user
client.text_user('NanoDano', 'Hello NanoDano from the Ruby bot!')

# Image message to user
client.text_user_img('NanoDano', 'image.png')

# Text message to channel
client.text_channel('The Cellar', 'Hello channel from the Ruby bot!')

# Image message to channel
client.text_channel_img('The Cellar', 'image.png')

Receiving Messages

# This callback needs to be set up BEFORE
# the client.connect. Set it up once and every
# time a message is received it will run
# This handles chat and private messages
client.on_text_message do |message|
    puts message.inspect

Mute and Deafen

# Mute and unmute output of client
client.me.mute(false) # unmute

# Silence incoming sound to client
client.me.deafen(false) # undeafen

Playing Wav Files (Experimental)

# The WAV file sample rate needs to match client config

Recording Audio (Experimental)


Streaming Raw PCM Data

# Start streaming from a FIFO queue of raw PCM data
# Uses Music Player Daemon (MPD)
# MPD can be installed on Debian based distros with
# sudo apt-get install mpd

Keeping Bot Alive

You'll need to add a loop to keep the program alive. CTRL-C can be used to interrupt the program and end execution. You could also create some kind of condition upon which to exit. For example, you could have the bot exit after receiving a specific message.

You can also daemonize the script and run it as a background service. Check out the code for Daemonizing Ruby Scripts.

# Configure and connect the client before this loop

while true
    # Just stay online until interrupted
    # Do bot things

Fully Functional Command Line Chat

This program can be run out-of-the-box, assuming you have installed prerequisites listed at the beginning of the page. You can configure the variables but they will also work with the defaults. It connects to the mumble.devdungeon.com Mumble server where you can chat with other people. I recommend at least customizing your user name. When you run it, it will connect, list all the users and channels, and then join a channel. You will see any incoming private or channel messages in your console, and you can type in messages and press enter to send messages to the channel. Have fun and hope to see you on Mumble!

I ran this with Ruby 2.2 on Linux Mint(Debian) after installing the libopus0 and libopus-dev packages with apt-get. I also had to install the mumble-ruby gem. I used RVM to install the latest version of Ruby. Follow the installation instructions on rvm.io if you've never used it. You can then use rvm install 2.2 and rvm use 2.2 --default. If you run in to problems regarding the 'login shell", edit the Gnome Terminal profile settings to turn on login shell option.

# This Ruby program will join the mumble.devdungeon.com Mumble
# server and list all the channels and users
require 'mumble-ruby'

# Set these variables
channel_name = 'The Cellar'
server_host = 'mumble.devdungeon.com'
# User an unregistered name or your registered name
username = "DevDungeonNeophyte" # Avoid spaces in username.
password = "" # Only required for registered names

client = Mumble::Client.new(server_host) do |conf|
conf.username = username
conf.password = password

puts "Connecting. One moment..."

# Wait a couple seconds to establish connection
sleep 2

# Set up callback that will run every time a chat
# or private message is received
client.on_text_message do |message|
    puts "Message Received: " + message.inspect

# One time actions after joining

puts "Server Channels:"
client.channels.each do |channel|
puts channel.inspect
puts "Users Online:"
client.users.each do |user|
puts user.inspect

client.text_channel(channel_name, 'Hello, I am taking my bot for a test run!')

puts "Now waiting for private or channel messages..."
puts "Use CTRL-C to end the program."

# Just stay alive until killed
while true
puts "Enter a message to send to the channel:"
outgoing_message = gets
client.text_channel(channel_name, outgoing_message)
puts "Message sent."