Playing audio files with discord.py - python-3.x

I've recently gotten back into coding and Python and wanted to check out how to make a discord bot. I've managed to send messages and do basic things, but now i can't figure out how to make it play audio in a voice channel.
I can get it to join and leave at will, but as soon as I try to play music, it's just silent. The audio file is already downloaded and it's in the same folder as my program. I do not get any errors, all i know is there is something wrong with the bot. The audio file is not just silence, I have checked. I do not know what is wrong.
What should happen is when i call for the bot and it joins my VC, it should start playing the song.
My code:
#client.command(aliases=['jvc'])
async def joinvc(ctx):
voice_channel = ctx.message.author.voice.channel
voice_client = discord.utils.get(client.voice_clients, guild=ctx.guild)
if voice_client:
if not voice_client.is_connected():
await voice_channel.connect()
voice_client.play(discord.FFmpegPCMAudio(executable='C:\\FFmpeg\\bin\\ffmpeg.exe', source='file.mp3'))
else:
await voice_channel.connect()
voice_client = discord.utils.get(client.voice_clients, guild=ctx.guild)
voice_client.play(discord.FFmpegPCMAudio(executable='C:\\FFmpeg\\bin\\ffmpeg.exe', source='file.mp3'))
Sorry if the code isn't great, but it was the only way I could think of without getting errors. Also I apologize if I forgot anything important or did something wrong, this is my first time using StackOverflow.

Remember to add ffmpeg to path
#client.command()
async def thisisnotacommand(ctx):
channel = ctx.author.voice.channel
vc = await channel.connect()
await ctx.send('Started playing: something')
vc.play(discord.FFmpegPCMAudio('file.mp3'), after=lambda e: print('done', e))
If you don't know how to add ffmpeg to path feel free to msg me Special unit#5323

Related

Bot won't leave voice channel when left alone

I have a personal music bot that plays music for me and friends, I only have a play and leave commands which both work perfectly, but I was wondering if a little upgrade to the bot automatically leaving voice channel when left in it alone was possible. After some reading in documentation, I thought I got it but this piece of my code simply doesn't work, it's almost like python is ignoring it for some reason so I guess I am missing something here...
so I was wondering if there is a reason why my code:
#client.event
async def on_voice_state_update(member):
voice_state = member.guild.voice_client
if len(voice_state.channel.members) == 1:
await voice_state.disconnect()
won't work, I don't get any error messages and literally nothing happens. Is it all as it should be here?
You are missing some arguments for this event. Simply add before and after and you should be fine.
The full event could be:
#client.event
async def on_voice_state_update(member, before, after):
voice_state = member.guild.voice_client
if voice_state is not None and len(voice_state.channel.members) == 1:
# If the bot is connected to a channel and the bot is the only one in the channel
await voice_state.disconnect() # Disconnect the bot from the channel
You can see more in the docs here:
on_voice_state_update

OSError: [Errno 9] Bad file descriptor discord bot

I am working on a discord bot using the discord.py API. I am trying to make the bot join a voice channel and play an mp3 file that is in the same directory. It joins the voice channel but prints the error in the title before playing anything. I was wondering what was causing this error. Relevant code below:
#client.command()
async def playClip(ctx):
global voice
channel=ctx.message.author.voice.channel
voice= get(client.voice_clients, guild=ctx.guild)
if voice and voice.is_connected():
await voice.move_to(channel)
else:
voice= await channel.connect()
voice.play(discord.FFmpegPCMAudio("BravoSix.mp3"))
print("test")
await voice.disconnect()
The problem is that the path you gave to the audio file is bad.
You have to give it the whole path to the file using single backslashes
voice.play(discord.FFmpegPCMAudio("C:\whereever\the\file\is\BravoSix.mp3"))

play audio file on discord voice channel wile file is being generated

I am making a discord bot that reads reddit posts with a text to speech on voice chat but the audio file has to be fully generated for the bot to begin playing so for longer posts the wait time is over 10 minutes. But the file is generated faster then you listen to it so theoretically I could make it after the text is done being downloaded it could wait 3 seconds then playing the file and the audio would work just as if the file was already generated
async def on_message(self, ctx):
if ctx.content.startswith("-p"):
connected = ctx.author.voice
if connected: #if the poster in conected to a voice channel
if is_connected(self) == False: #if the bot not connected to a voice chat it will join the posters voice chat
global voice
voice = await connected.channel.connect()
say(ctx.content.split()[1]) #uses URL of a reddit to make a mp3 file of a TTS reading the post
player = voice.play(discord.FFmpegPCMAudio("out.mp3")) #stream the auidio file to the voice channel
player.start()
the say() function generates the the next line plays the audio
would threading be usefull
if you want the bot to wait 3 seconds, before the file playback method use
import time than time.sleep(3) number 3 indicates the number of seconds how long the bot will wait, full code =
..
import time
..
async def on_message(self, ctx):
if ctx.content.startswith("-p"):
connected = ctx.author.voice
if connected: #if the poster in conected to a voice channel
if is_connected(self) == False: #if the bot not connected to a voice chat it will join the posters voice chat
global voice
voice = await connected.channel.connect()
say(ctx.content.split()[1]) #uses URL of a reddit to make a mp3 file of a TTS reading the post
time.sleep(3)
player = voice.play(discord.FFmpegPCMAudio("out.mp3")) #stream the auidio file to the voice channel
player.start()

Discord bot timed mute channel on event

So I'm new using python I'm not that good at all and I wanted to create a bot meme based when a user says "Za warudo!" the channel will get muted for 10 seconds and send an image of a gif also set
so I could do the image it was pretty easy to do I also want to add a cooldown of around 120 seconds or more I don't want this command to get spammed.
#client.event
async def on_message(message):
channel = message.channel
if message.content.startswith('ZA WARUDO!'):
with open('zawarudo.gif', 'rb') as picture:
await client.send_file(channel, picture)
anyway, I just can't understand how to do this timed channel mute should I use a role for it? if I do how am I gonna give it to everyone in the server?
i was able to do it myself
await channel.set_permissions(everyone, send_messages=False)
await asyncio.sleep(10)
await channel.set_permissions(everyone, send_messages=True)

Discord receive audio

I want to receive Audio from Discord to make a speech recognition. I haven't found something in the python Discord APi. The speech recognition is no problem, but I have no idea how to receive Audio from Discord. Maybe someone can help me.
A recent update to the discord.py fork pycord added the possibility to record audio, which you could then use for speech recognition.
To start recording the audio, you simply need to call VoiceClient.start_recording with a Sink, a function that will be called after you stopped recording, and optional arguments for that function. An example would be:
import discord
bot = discord.Bot(debug_guilds=[719996466290098180])
#bot.command()
async def start_record(ctx):
await ctx.author.voice.channel.connect() # Connect to the voice channel of the author
ctx.voice_client.start_recording(discord.sinks.MP3Sink(), finished_callback, ctx) # Start the recording
await ctx.respond("Recording...")
async def finished_callback(sink, ctx):
# Here you can access the recorded files:
recorded_users = [
f"<#{user_id}>"
for user_id, audio in sink.audio_data.items()
]
files = [discord.File(audio.file, f"{user_id}.{sink.encoding}") for user_id, audio in sink.audio_data.items()]
await ctx.channel.send(f"Finished! Recorded audio for {', '.join(recorded_users)}.", files=files)
#bot.command()
async def stop_recording(ctx):
ctx.voice_client.stop_recording() # Stop the recording, finished_callback will shortly after be called
await ctx.respond("Stopped!")
bot.run(Token)
Because this is not an audio stream, you can't use it to make a virtual assistant that will automatically listen to you, but you can record the voice channel and get what was said in it.
This functionality doesn't really exist. There is a VoiceClient.poll_voice_ws coroutine, but that just reads directly from the socket. You'll have to come up with some way of decoding that into audio and further handling it yourself.

Resources