问题
Like the title I need to play a gtts file into a voice channel what is the easiest way to do this? I am using python 3.7. Here is my code so far:
@client.command(name="repeat")
async def repeat(context):
import gtts, ffmpeg
from discord.ext import commands
# grab the user who sent the command
user = context.message.author
voice_channel = user.voice.voice_channel
channel = None
# only play music if user is in a voice channel
if voice_channel != None:
await ctx.send(f"What do you want to say, type cancel to cancel:")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
try:
msg = await client.wait_for("message", check=check, timeout=120)
except asyncio.TimeoutError:
await ctx.send("Sorry, you didn't reply in time!")
if(msg.content == 'cancel'):
return
tts = gtts.gTTS(str(msg.content), lang="en")
tts.save("text.mp3")
# grab user's voice channel
channel = voice_channel.name
await client.say('User is in channel: '+ channel)
# create StreamPlayer
vc = await client.join_voice_channel(voice_channel)
player = vc.create_ffmpeg_player('text.mp3', after=lambda: print('done'))
player.start()
while not player.is_done():
await asyncio.sleep(1)
# disconnect after the player has finished
player.stop()
await vc.disconnect()
else:
await client.say('User is not in a channel.')
I am still new to making bots on discord so my code looks like a dumpster fire, I am currently working on fixing/compacting my code. once again I am using python 3.7
回答1:
So, firstly you should put any imports at the start of your file (Same area you import discord)
Now onto the code, I will simplify it a bit. My code does not ask the user for text, instead this code uses the input called after the command. I.e !repeat Hello
will speak hello
in the voice channel
First, here is some code to connect to a voice channel. For this purpose, we will keep it separate. This is some nice code, and somewhat better then the gtts code I will attempt.
@bot.command()
async def connect(ctx, *, channel: discord.VoiceChannel=None):
"""
Connect to a voice channel
This command also handles moving the bot to different channels.
Params:
- channel: discord.VoiceChannel [Optional]
The channel to connect to. If a channel is not specified, an attempt to join the voice channel you are in
will be made.
"""
if not channel:
try:
channel = ctx.author.voice.channel
except AttributeError:
raise InvalidVoiceChannel('No channel to join. Please either specify a valid channel or join one.')
vc = ctx.voice_client
if vc:
if vc.channel.id == channel.id:
return
try:
await vc.move_to(channel)
except asyncio.TimeoutError:
raise VoiceConnectionError(f'Moving to channel: <{channel}> timed out.')
else:
try:
await channel.connect()
except asyncio.TimeoutError:
raise VoiceConnectionError(f'Connecting to channel: <{channel}> timed out.')
await ctx.send(f'Connected to: **{channel}**', delete_after=20)
Cool, so now we can connect to the channel. So here's my go at actually doing some gtts work. I wont talk to much, it is all commented. However, if theres an issue just leave a comment :)
The following is the required import from gtts import gTTS
@bot.command()
async def repeat(ctx, *, text=None):
"""
A command which saves `text` into a speech file with
gtts and then plays it back in the current voice channel.
Params:
- text [Optional]
This will be the text we speak in the voice channel
"""
if not text:
# We have nothing to speak
await ctx.send(f"Hey {ctx.author.mention}, I need to know what to say please.")
return
vc = ctx.voice_client # We use it more then once, so make it an easy variable
if not vc:
# We are not currently in a voice channel
await ctx.send("I need to be in a voice channel to do this, please use the connect command.")
return
# Lets prepare our text, and then save the audio file
tts = gTTS(text=text, lang="en")
tts.save("text.mp3")
try:
# Lets play that mp3 file in the voice channel
vc.play(discord.FFmpegPCMAudio('text.mp3'), after=lambda e: print(f"Finished playing: {e}"))
# Lets set the volume to 1
vc.source = discord.PCMVolumeTransformer(vc.source)
vc.source.volume = 1
# Handle the exceptions that can occur
except ClientException as e:
await ctx.send(f"A client exception occured:\n`{e}`")
except TypeError as e:
await ctx.send(f"TypeError exception:\n`{e}`")
except OpusNotLoaded as e:
await ctx.send(f"OpusNotLoaded exception: \n`{e}`")
Now, in order to leave the current voice channel you can do the following
@bot.command()
async def disconnect(ctx):
"""
Disconnect from a voice channel, if in one
"""
vc = ctx.voice_client
if not vc:
await ctx.send("I am not in a voice channel.")
return
await vc.disconnect()
await ctx.send("I have left the voice channel!")
来源:https://stackoverflow.com/questions/62494399/how-to-play-gtts-mp3-file-in-discord-voice-channel-the-user-is-in-discord-py