This is an old revision of the document!
Table of Contents
🎵 Ambient Lo-Fi Discord Music Bot – Installation & Usage
This bot plays ambient lo-fi music automatically in your Discord voice channel. It starts with shuffle, continues playing without stopping, and can be controlled via simple commands.
📦 Requirements
- Python 3.10 or newer
- FFmpeg installed (`sudo apt install ffmpeg`)
- A Discord Bot Token
- MP3 files placed in the `music/` directory
- Optional: systemd for autostart on boot
🛠️ Installation
- Clone or copy the bot code into a directory, e.g. `/var/www/mbot/`
- Create a `music/` folder and add your MP3 tracks
- Install required Python packages:
`pip install discord`
🔐 Insert Your Bot Token
Open `bot.py` and replace: `bot.run(“your-bot-token-here”)` with your actual Discord bot token.
🤖 Creating a Discord Bot
- Click New Application, give it a name
- Go to Bot tab → click Add Bot
- Under Privileged Gateway Intents, enable:
- Message Content Intent
- Server Members Intent
- Copy the token and paste it into `bot.py`
🔗 Invite the Bot to Your Server
Go to the OAuth2 → URL Generator tab:
- Scopes: `bot`
- Bot Permissions:
- Connect
- Speak
- Send Messages
- Read Message History
🚀 Starting the Bot
To start manually: `python3 ./bot.py`
Or set up a systemd service:
sudo adduser musikbot sudo chown -R musikbot:musikbot /var/www/mbot
Autostart on server start
sudo nano /etc/systemd/system/musicbot.service
[Unit] Description=Discord Music Bot After=network.target [Service] ExecStart=/usr/bin/python3 /var/www/mbot/bot.py WorkingDirectory=/var/www/mbot Restart=always User=musikbot [Install] WantedBy=multi-user.target
Enable and start the service: `sudo systemctl daemon-reload` `sudo systemctl enable musicbot` `sudo systemctl start musicbot`
🎧 Discord Commands
- `!join` – Bot joins your voice channel and starts shuffle playback
- `!leave` – Bot leaves the voice channel
- `!list` – Lists all available MP3 files
- `!play [filename]` – Plays a specific file or a random one if none is given
- `!next` – Skips to the next track
- `!shuffle` – Shuffles the playlist and starts playback
- `!pause` – Pauses playback
- `!resume` – Resumes playback
- `!stop` – Stops playback
- `!help` – Displays all available commands
🧠 Notes
- The bot plays continuously without stopping after each track
- Volume is set to 100%
- Make sure the bot has “Speak” permissions in the voice channel
- Works best in standard voice channels (not Stage Channels)
📂 Folder Structure
/var/www/mbot/ ├── bot.py ├── music/ │ ├── track1.mp3 │ ├── track2.mp3
📂 bot.py
import discord
from discord.ext import commands
import os
import random
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
intents.guilds = True
bot = commands.Bot(command_prefix="!", intents=intents, help_command=None)
MUSIC_DIR = "music"
playlist = []
current_index = -1
@bot.event
async def on_ready():
print(f"🎵 Bot is online as {bot.user}")
def play_next_track(ctx):
global playlist, current_index
vc = ctx.voice_client
if not vc or not playlist:
return
current_index = (current_index + 1) % len(playlist)
filepath = os.path.join(MUSIC_DIR, playlist[current_index])
source = discord.FFmpegPCMAudio(filepath, options="-filter:a volume=1.0")
def after_playing(error):
if error:
print(f"Playback error: {error}")
else:
play_next_track(ctx)
vc.play(source, after=after_playing)
async def start_shuffle(ctx):
global playlist, current_index
vc = ctx.voice_client
playlist = [f for f in os.listdir(MUSIC_DIR) if f.endswith(".mp3")]
if not playlist:
await ctx.send("📁 No music files found.")
return
random.shuffle(playlist)
current_index = 0
filepath = os.path.join(MUSIC_DIR, playlist[current_index])
source = discord.FFmpegPCMAudio(filepath, options="-filter:a volume=1.0")
def after_playing(error):
if error:
print(f"Playback error: {error}")
else:
play_next_track(ctx)
vc.stop()
vc.play(source, after=after_playing)
await ctx.send(f"🔀 Shuffle started: {playlist[current_index]}")
@bot.command()
async def join(ctx):
member = ctx.guild.get_member(ctx.author.id)
if member and member.voice and member.voice.channel:
channel = member.voice.channel
await channel.connect()
await ctx.send(f"✅ Connected to {channel.name}")
await start_shuffle(ctx)
else:
await ctx.send("❌ You're not in a voice channel.")
@bot.command()
async def leave(ctx):
if ctx.voice_client:
await ctx.voice_client.disconnect()
await ctx.send("👋 Bot has left the voice channel.")
else:
await ctx.send("❌ Bot is not connected.")
@bot.command()
async def list(ctx):
files = [f for f in os.listdir(MUSIC_DIR) if f.endswith(".mp3")]
if not files:
await ctx.send("📁 No music files found.")
else:
msg = "\n".join(f"{i+1}. {f}" for i, f in enumerate(files))
await ctx.send(f"🎶 Available Tracks:\n{msg}")
@bot.command()
async def play(ctx, filename=None):
vc = ctx.voice_client
global playlist, current_index
if not vc:
await ctx.send("❌ Bot is not in a voice channel. Use !join first.")
return
if filename:
filepath = os.path.join(MUSIC_DIR, filename)
if not os.path.isfile(filepath):
await ctx.send("❌ File not found.")
return
playlist = [filename]
current_index = 0
else:
playlist = [f for f in os.listdir(MUSIC_DIR) if f.endswith(".mp3")]
if not playlist:
await ctx.send("📁 No music files found.")
return
current_index = random.randint(0, len(playlist) - 1)
filepath = os.path.join(MUSIC_DIR, playlist[current_index])
source = discord.FFmpegPCMAudio(filepath, options="-filter:a volume=1.0")
def after_playing(error):
if error:
print(f"Playback error: {error}")
else:
play_next_track(ctx)
vc.stop()
vc.play(source, after=after_playing)
await ctx.send(f"▶️ Now playing: {playlist[current_index]}")
@bot.command()
async def next(ctx):
if ctx.voice_client:
play_next_track(ctx)
await ctx.send("⏭️ Skipping to next track.")
else:
await ctx.send("❌ Bot is not in a voice channel.")
@bot.command()
async def shuffle(ctx):
if ctx.voice_client:
await start_shuffle(ctx)
else:
await ctx.send("❌ Bot is not in a voice channel.")
@bot.command()
async def pause(ctx):
if ctx.voice_client and ctx.voice_client.is_playing():
ctx.voice_client.pause()
await ctx.send("⏸️ Playback paused.")
else:
await ctx.send("❌ Nothing is playing.")
@bot.command()
async def resume(ctx):
if ctx.voice_client and ctx.voice_client.is_paused():
ctx.voice_client.resume()
await ctx.send("▶️ Playback resumed.")
else:
await ctx.send("❌ Nothing to resume.")
@bot.command()
async def stop(ctx):
if ctx.voice_client and ctx.voice_client.is_playing():
ctx.voice_client.stop()
await ctx.send("⏹️ Playback stopped.")
else:
await ctx.send("❌ Nothing is playing.")
@bot.command()
async def help(ctx):
help_text = (
"**🎵 Music Bot Commands:**\n"
"`!join` – Bot joins your voice channel and starts shuffle\n"
"`!leave` – Bot leaves the voice channel\n"
"`!list` – Lists all available MP3 files\n"
"`!play [filename]` – Plays a specific file or random if none given\n"
"`!next` – Plays the next track\n"
"`!shuffle` – Shuffles the playlist and starts playback\n"
"`!pause` – Pauses playback\n"
"`!resume` – Resumes playback\n"
"`!stop` – Stops playback\n"
)
await ctx.send(help_text)
bot.run("YOUR_BOT_TOKEN_HERE")
🛟 Support & Extensions
You can expand the bot anytime – with volume control, queue management, or even a web interface. For questions or ideas, feel free to reach out!
