예제 #1
0
파일: request.py 프로젝트: wquist/DECbot
	def __init__(self, text):
		""" Create a new TTS request.

		The target directory for both the input and output files is specified
		through the configuration YAML; if `tmp` is not specified under `tts`,
		the system-wide temporary directory will be used instead.

		:param text: The input data (the words to by synthesized).
		:type  text: str

		:raises RequestError: The configuration-specified path may be invalid or
		                      inaccessible, raising an error.
		"""
		uid  = uuid4().hex
		path = config.get('tts.tmp', '/tmp')

		# Format the input/output filenames based on the config path and UUID.
		# The class controls the input file, and the output of DEC is a WAV.
		self.input  = '{}/{}.txt'.format(path, uid)
		self.output = '{}/{}.wav'.format(path, uid)

		try:
			# write the conversion request to a file.
			with open(self.input, 'w') as f:
				f.write(text)
		except OSError:
			raise RequestError('Could not write request text to file.')
예제 #2
0
    async def on_ready(self):
        self.send_message = self.bot.get_cog('Text').send_message
        if discord.opus.is_loaded():
            return

        path = config.get('opus')
        if path:
            discord.opus.load_opus(path)

        if not discord.opus.is_loaded():
            raise RuntimeError('Could not load libopus.')
예제 #3
0
파일: request.py 프로젝트: wquist/DECbot
	def cleanup(self):
		""" Remove the request information written to disk.

		Remove the input text and output sound from the filesystem. The
		configuration value 'archive' can be used to prevent this behavior; the
		files will exist until the user deletes them or the parent folder.
		"""
		if not config.get('tts.archive', False):
			# The file(s) may not exist if an exception occurred or the request
			# has not been fulfilled yet, so ignore these errors.
			with contextlib.suppress(FileNotFoundError):
				os.remove(self.input)
				os.remove(self.output)
예제 #4
0
def convert(req, params='[:phoneme on]'):
    """ Invoke the TTS executable.

	:param req: The Request to convert. This takes the text in the `input` file
	            and generates audio data stored in the `output` identifier.
	:type  req: Request
	:param params: The "pre" commands to send to DEC. By default, this enables
	               phonemes, to enable "singing" with pitch specifications.
	               Execute `wine say.exe -h` for more information.
	:type  params: str

	:raises TTSError: If the DEC command fails, this error is raised with the
	                  contents of stderr.
	"""
    path = config.get('tts.bin', config.get('tts'))
    if not path:
        raise TTSError('No TTS executable specified.')

    # Change directory into the configured binary path since `say.exe`
    # depends on other files within (namely a dictionary and .dll), and will
    # not be able to find them when executed from another directory.
    command = 'cd {} && say.exe -pre "{}"'.format(path, params)
    # Apply the request-specific arguments and execute the command.
    command = '{} -w {} < {}'.format(command, req.output, req.input)

    try:
        # Execute the command directly; using an async subprocess seemed
        # significantly slower in comparison.
        error = os.system(command)
    except OSError:
        # An exception means there was an error RUNNING the command, not an
        # error from the command/shell itself.
        raise TTSError('Could not invoke TTS command.')

    if error:
        # A non-zero error code signifies an error with DEC.
        raise TTSError('TTS executable exited with code {}.'.format(error))
예제 #5
0
파일: voice.py 프로젝트: wquist/DECbot
	async def on_ready(self):
		""" Retrieve sibling cogs and perform setup before the bot runs.

		At this point, libopus should have been loaded if it was detected by
		Discord. Otherwise, the path will be grabbed from the config file (it
		must be defined at this point).

		:raises RuntimeError: If libopus could still not be loaded, or no path
		                      was defined in the config, an error is raised.
		"""
		self.send_message = self.bot.get_cog('Text').send_message
		if opus.is_loaded():
			return

		path = config.get('opus')
		if path:
			opus.load_opus(path)

		if not opus.is_loaded():
			raise RuntimeError('Could not load libopus.')