Discord.py播放Gtts而不保存音频文件



我有这样的代码,可以将文本转换为音频并将其保存为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 中播放,我该如何做到这一点

在gTTS文档中,您可以找到直接播放声音的说明。在discord.py API文档中,您可以看到有一个pipe参数可以设置为FFmpegPCMAudio方法的True

然而,FFmpegPCMAudio方法似乎不起作用,@Armster15为此给出了一个不一致.py问题的有效解决方案。为了清楚起见,您可以将他的代码复制到一个文件(例如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

最新更新