как воспроизвести mp3-файл gtts в голосовом канале Discord, в котором находится пользователь (discord.py) - PullRequest
0 голосов
/ 21 июня 2020

Как и заголовок, мне нужно воспроизвести файл gtts в голосовом канале. Какой самый простой способ сделать это? Я использую python 3.7. Вот мой код:

@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.')

Я все еще новичок в создании ботов на Discord, поэтому мой код выглядит как пожар в мусорном контейнере, в настоящее время я работаю над исправлением / сжатием моего кода. еще раз использую python 3,7

1 Ответ

1 голос
/ 21 июня 2020

Итак, во-первых, вы должны поместить любой импорт в начало вашего файла (в той же области, где вы импортируете discord)

Теперь о коде, я немного его упрощу. Мой код не запрашивает у пользователя текст, вместо этого этот код использует ввод, вызываемый после команды. Т.е. !repeat Hello будет говорить hello в голосовом канале

Во-первых, вот код для подключения к голосовому каналу. Для этого мы будем держать его отдельно. Это неплохой код, который несколько лучше, чем код gtts, который я попробую.

@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)

Круто, теперь мы можем подключиться к каналу. Итак, вот мой go на самом деле выполняет некоторую работу с gtts. Я не буду много говорить, это все комментируется. Однако, если есть проблема, просто оставьте комментарий:)

Требуется следующий импорт 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}`")

Теперь, чтобы покинуть текущий голосовой канал, вы можете сделать следующие

@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!")
...