Botamusique re-implements many media player features - web interface, playing music from youtube.
However, there are traditional FOSS media servers out there implementing the same features, like Mopidy.
In this post, I'll show you how to make Mopidy do all the media-related heavy lifting, and how to only redirect the audio from Mopidy so you can hear it in a Mumble server.
I understand you may already have e.g. Navidrome or Jellyfin on your local network and may be annoyed by having to install "yet another" media server.
A bit of explanation of why we're using Mopidy instead of e.g. Subsonic:
Opening the Mopidy web UI in multiple browser windows and pressing "Play" in one of them will show the notification Browser1 resumed playback in all of the other windows. Then, the audio will be played on the server where Mopidy is installed (NOT in the browsers).
Subsonic on the other hand would allow each browser window to have a separate audio stream. In Subsonic's defense though, it supports Jukebox mode in certain implementations (see gonic Subsonic server implementation).
Mopidy has a nice Mopidy-Youtube extension which seamlessly integrates with Mopidy's own search functionality.
Subsonic on the other hand is all about a playing local media files and has no youtube support.
Mopidy-Youtube is just one of many extensions. With extensions, Mopidy can also:
Mopidy-Subidy.All of the above sound good for a music bot use-case or usage by a power user.
Mopidy plays audio to a local, hardware audio output by default. However, you don't want to hear audio through on the built-in speakers of your server where Mopidy will be running. You want sound to be heard in a channel on your Mumble server.
This section focuses only on the basics:
In further sections, you'll learn how to broadcast Mopidy's audio output to the network and get Mumble to consume that audio stream.
I recommend following the below instructions on your personal computer first. When you are sure everything is working - move the setup to your server.
Install Mopidy using your Linux distribution's package manager. (on Arch Linux paru -S mopidy)
Run $ mopidy in the terminal to see if it starts at all and go to http://localhost:6680 to see the if the (rather empty) default page is there.
There's not much for you to do on that page, because I didn't tell you how to install a web interface yet.
Mopidy has no web interface by default - you need to download it separately. I'll show you how to install the iris web UI.
Install according to the instructions here (on Arch Linux paru -S mopidy-iris), then restart mopidy.
Now go to http://localhost:6680/iris/, where you should see a web UI. Next, I'll show you how to play a song from the file system and youtube.
We'll be debugging sending audio over the network to Mumble, so it's good to have good old reliable playback of audio files from the filesystem.
Playing from filesystem is supported out of the box - no need to download anything.
When you've first ran Mopidy, it should've created a ~/.config/mopidy/mopidy.conf file for you.
Open it in your editor of choice, find the [file] section and modify it as such (remember to restart mopidy once you're done):
[file]
enabled = true
media_dirs = /path/to/folder/containing/music/files
Now go to http://localhost:6680/iris/library/browse, then click the "Files" tile. Find a song and double click it to see if it plays through your personal computer's speakers.
Now let's move on to playing audio from youtube videos.
Playback of youtube videos' audio is supported by the Mopidy-Youtube extension - install it using the below instructions.
WARNING: By default, Mopidy-Youtube uses the youtube-dl executable by to download videos. Unfortunately, when I tried to use it that way, it kept showing me errors related to "uploader_id" and did not play any sound. Thankfully, Mopidy-Youtube's settings let you change youtube-dl to something else. I changed it to use yt-dlp instead of youtube-dl. That fixed all of my video download issues. The below instructions take that fix into account.
Run:
pip install Mopidy-Youtube # this is how I install mopidy-youtube, if you used another way, skip this
pip install yt-dlp
then in your mopidy.conf add:
[youtube]
enabled = true
youtube_dl_package = yt_dlp
# yt_dlp with an underscore, not with a dash
and restart Mopidy.
Here it's helpful to start Mopidy from the terminal (just $ mopidy). It's so you can inspect the output in case any errors occur when trying to play your first youtube video using yt-dlp from Mopidy.
Now let's see if the youtube integration works, and whether we can search and play videos.
In the Iris web interface, click Search in the sidebar in the top left. Before your first search, know that the search results take a moment to load, take notice of the loading indicator in the bottom right (after running a search).
Now, type in any search term as if you were on youtube's regular webpage, e.g. "audio test". Double click one of the results and see if you hear any audio.
If you can't find the search bar, just go to this link: http://localhost:6680/iris/search/all/youtube%20audio%20test
If the search is not returning any results, look at the right side of the search bar and see if a "Sources" button is visible there. If it's there, click it and select "Youtube". For some reason it disappeared for me now, but it appears sometimes.
If it's still not returning any results, something's broken deeper down. See if there's any red text in the terminal output. Look at yt-dlp's issue tracker on github to see if other people are having the same problem. Sometimes a change on youtube's side breaks yt-dlp and you need to wait for an udpate of yt-dlp.
Currently Mopidy should be only playing audio to your local headphones or speakers.
In this section, you'll move one step closer to playing your music in Mumble - you'll take Mopidy's audio output and broadcast it on your network, so other applications can do something with the audio. One such application could be … a Mumble bot that'd listen to the audio you are broadcasting and play it back in Mumble.
wink wink wink in the section after this one cough
Streaming to the network is really easy to set up (once you have the code handed to you on a silver plattter haha). There's only one step - modify your ~/.config/mopidy/mopidy.conf like this:
[audio]
output = audioconvert ! audio/x-raw,format=S16LE,rate=48000,channels=2 ! udpsink host=127.0.0.1 port=5004
The syntax is a bit uncommon, but this is how you write gstreamer pipelines. There's an example of gstreamer syntax on the Mopidy wiki too.
Basically, the above snippet does this:
add_sound hereNow that you have an audio stream being broadcasted on your network, you just need a bot that'll listen to that stream and play it back in your Mumble's server channel as if it were "speaking".
I have to thank user bitconnector from github for writing this example of a music bot that plays a local audio file in a Mumble channel. I wouldn't have figured out how to do this without it.
pip install pymumble because the bot code depends on this library. All other dependencies are Python builtins udp.py93.184.216.34 IP address in udp.py to the IP address of your Mumble server.murmur (Mumble server) installed, you can run murmur locally and set the IP in the script to 127.0.0.164738pymumble_py3.Mumble() to take that into account. See the docs here for available argumentspython udp.pyudp.py as you normally would so you can listen to your bot "speak" audio. The bot should already be connected and have the nickname mopidyplayerThe udp.py bot should start playing audio in Mumble.
The bot code to put into udp.py:
import socket
import time
import subprocess as sp
import pymumble_py3
UDP_IP = "127.0.0.1"
UDP_PORT = 5004
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# REMEMBER TO CHANGE THE IP HERE TO YOUR MUMBLE SERVER'S IP
# If your server needs a passsword to connect to it, use the password= argument
# If your server uses a port different than the Mumble default of 64738, use the port= argument and pass the port as a number
mumble = pymumble_py3.Mumble('93.184.216.34', 'mopidyplayer', stereo=True, reconnect=True)
mumble.set_codec_profile('audio')
mumble.start()
mumble.is_ready() #wait for Mumble to get ready to avoid errors after startup
mumble.set_bandwidth(192000)
sock.bind((UDP_IP, UDP_PORT))
while True:
while True:
raw_music, addr = sock.recvfrom(65507)
if not raw_music:
break
mumble.sound_output.add_sound(raw_music)
while mumble.sound_output.get_buffer_size() > 0.5: #
time.sleep(0.01)
time.sleep(2)Mopidy-Mumble extension than go through all this…rtpL16pay pipeline component in gstreamer in Mopidy. It outputs only big endian S16BE so you'd need to swap the endianness on the Python script side, using raw_music[::-1], because pymumble only takes S16LE little endian.Instead of streaming audio directly from Mopidy's [audio] output to the Mumble bot like I've shown above, you might've come across Mopidy's wiki recommendation:
If you want to play the audio on another computer than the one running Mopidy, you can stream the audio from Mopidy through an Icecast audio streaming server.
Unfortunately, audio streamed from Icecast will have a lot of delay. When you press "Play" in the web UI, you'll hear sound in Mumble after a couple of seconds, instead of instantly. Same if you stop the playback. The delay makes listening to things in Mumble rather unenjoyable.
Here's what Thomas B. Ruecker - one of the Icecast maintainers - has to say on the topic (source, accessed at 2023-06-25):
Don't use Icecast if you need sub-second latency!
Don't use Icecast if you need sub-10-second latency and don't have full control over the whole chain of software and network!
Yes, this is an answer, not a comment. Icecast is not designed for such use cases. It was designed for 1-to-n bulk broadcast of data over HTTP in non-synchronized fashion.
What you are explaining sounds like you really should consider something that was designed to be low latency, like web-RTC.
If you think you really should use Icecast, please explain why. Because your question speaks otherwise. I'm all for more Icecast use, I'm it's maintainer after all, but its application should make sense.
Additionally, streaming audio directly from Mopidy's [audio] output is also simpler, because you need to only set up Mopidy and the Mumble bot. Here you need Icecast in addition.
Nonetheless, I used Icecast for this purpose for a while. If for some reason you need to too, some instructions are below.
Icecast can be installed on Arch Linux using pacman -S icecast.
On Debian, it's apt install icecast2.
The [audio] snippets on the linked Mopidy wiki page are meant to be put in ~/.config/mopidy/mopidy.conf (or /etc/mopidy/mopidy.conf if you start mopidy using a systemd service). Put those snippets in now.
The snippets conveniently already contain the default credentials for Icecast.
To run, do icecast -c path_to_icecast_config_file.xml (copy config file from /etc/icecast.xml). Do not modify the default config - it's not necessary.
You can also start Icecast using the systemd service systemctl start icecast (icecast2 on Debian)
So, provided that you:
[audio] section in mopidy.confYou should now be able to play some song in Mopidy and listen it from your browser through the Icecast stream.
To listen to the Icecast stream, go to http://youriphere:8000/mopidy (the resource is /mopidy because the line of code in the [audio] section in mopidy.conf we've added has mount=mopidy - the /mopidy path gets registered automatically when mopidy starts. You don't need to modify the icecast config to add the /mopidy path manually)
Now go to the Iris web UI and play a song. If you can hear the song you're playing, congrats! That's it!
WARNING: The instructions above worked fine for me on Arch Linux, but on Debian 11 Bullseye I ran into the following issue:
youriphere:8000/mopidy returns 404, and mopidy's logs (journalctl -eu mopidy) say ERROR [MainThread] mopidy.audio.gst GStreamer error: Could not connect to serverTo fix this, I recommend following the excellent guide over at jc-lan: https://jc-lan.org/2020/05/26/mopidy-fails-to-connect-to-icecast2-server-with-ubuntu-20-04/
This issue is also mentioned at the top of the Mopidy's Icecast wiki page I've linked (regarding libshout3).