48 lines
1.7 KiB
Python
48 lines
1.7 KiB
Python
import subprocess
|
|
import shlex
|
|
import io
|
|
from discord.opus import Encoder
|
|
import discord
|
|
|
|
# Huge thanks to https://github.com/Rapptz/discord.py/issues/5192#issuecomment-669515571
|
|
|
|
|
|
class FFmpegPCMAudio(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
|