【问题标题】:Discord.py Play Gtts Without Saving The Audio FileDiscord.py 在不保存音频文件的情况下播放 Gtts
【发布时间】:2021-09-08 09:05:12
【问题描述】:

我有这段代码可以将文本转换为音频并将其保存为 mp3,然后加入语音频道并播放音频文件

@commands.command()
async def tts(self, ctx, *, text):
     sound = gtts(text=text, lang="en", slow=False).save("test.mp3")
     channel=voice_channel.name
     await ctx.send('User is in channel: '+ channel)
     vc = await voice_channel.connect()
     vc.play(discord.FFmpegPCMAudio('test.mp3'), after=print("Done"))

如果不将文本保存为语音并直接从 gtts 播放,我将如何做到这一点

【问题讨论】:

标签: python discord.py


【解决方案1】:

gTTS documentation 中,您可以找到直接播放声音的说明。在discord.py API documentation 中,您会看到pipe 参数可以设置为True 用于FFmpegPCMAudio 方法。

但是,FFmpegPCMAudio 方法似乎无法正常工作,为此,@Armster15 已在 discord.py 问题上提供了a working solution。您可以将他的代码复制到一个文件(例如FFmpegPCMAudioGTTS.py)并将类名重命名为FFmpegPCMAudioGTTS,以便清楚起见,因为此方法不适用于普通流(仅适用于 gTTS)。

因此,您的代码可以变成:

from FFmpegPCMAudioGTTS import FFmpegPCMAudioGTTS

@commands.command()
async def tts(self, ctx, *, text):
    sound = gtts(text=text, lang="en", slow=False)
    sound_fp = BytesIO()
    sound.write_to_fp(sound_fp)
    channel = voice_channel.name
    await ctx.send('User is in channel: ' + channel)
    vc = await voice_channel.connect()
    vc.play(FFmpegPCMAudioGTTS(sound_fp.read(), pipe=True), after=print("Done"))

FFmpegPCMAudioGTTS.py

import subprocess
import shlex
import io
from discord.opus import Encoder
import discord

class FFmpegPCMAudioGTTS(discord.AudioSource):
    def __init__(self, source, *, executable='ffmpeg', pipe=False, stderr=None, before_options=None, options=None):
        stdin = None if not pipe else source
        args = [executable]
        if isinstance(before_options, str):
            args.extend(shlex.split(before_options))
        args.append('-i')
        args.append('-' if pipe else source)
        args.extend(('-f', 's16le', '-ar', '48000', '-ac', '2', '-loglevel', 'warning'))
        if isinstance(options, str):
            args.extend(shlex.split(options))
        args.append('pipe:1')
        self._process = None
        try:
            self._process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=stderr)
            self._stdout = io.BytesIO(
                self._process.communicate(input=stdin)[0]
            )
        except FileNotFoundError:
            raise discord.ClientException(executable + ' was not found.') from None
        except subprocess.SubprocessError as exc:
            raise discord.ClientException('Popen failed: {0.__class__.__name__}: {0}'.format(exc)) from exc
    def read(self):
        ret = self._stdout.read(Encoder.FRAME_SIZE)
        if len(ret) != Encoder.FRAME_SIZE:
            return b''
        return ret
    def cleanup(self):
        proc = self._process
        if proc is None:
            return
        proc.kill()
        if proc.poll() is None:
            proc.communicate()

        self._process = None

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-11
    • 2018-02-01
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多