Source code for aeneas.diagnostics

#!/usr/bin/env python
# coding=utf-8

# aeneas is a Python/C library and a set of tools
# to automagically synchronize audio and text (aka forced alignment)
#
# Copyright (C) 2012-2013, Alberto Pettarin (www.albertopettarin.it)
# Copyright (C) 2013-2015, ReadBeyond Srl   (www.readbeyond.it)
# Copyright (C) 2015-2017, Alberto Pettarin (www.albertopettarin.it)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
This module contains the following classes:

* :class:`~aeneas.diagnostics.Diagnostics`,
  checking whether the setup of ``aeneas`` was successful.

This module can be executed from command line with::

    python -m aeneas.diagnostics

.. versionadded:: 1.4.1
"""

from __future__ import absolute_import
from __future__ import print_function
import sys

import aeneas.globalfunctions as gf


[docs]class Diagnostics(object): """ Check whether the setup of ``aeneas`` was successful. """ @classmethod
[docs] def check_shell_encoding(cls): """ Check whether ``sys.stdin`` and ``sys.stdout`` are UTF-8 encoded. Return ``True`` on failure and ``False`` on success. :rtype: bool """ is_in_utf8 = True is_out_utf8 = True if sys.stdin.encoding not in ["UTF-8", "UTF8"]: is_in_utf8 = False if sys.stdout.encoding not in ["UTF-8", "UTF8"]: is_out_utf8 = False if (is_in_utf8) and (is_out_utf8): gf.print_success(u"shell encoding OK") else: gf.print_warning(u"shell encoding WARNING") if not is_in_utf8: gf.print_warning(u" The default input encoding of your shell is not UTF-8") if not is_out_utf8: gf.print_warning(u" The default output encoding of your shell is not UTF-8") gf.print_info(u" If you plan to use aeneas on the command line,") if gf.is_posix(): gf.print_info(u" you might want to 'export PYTHONIOENCODING=UTF-8' in your shell") else: gf.print_info(u" you might want to 'set PYTHONIOENCODING=UTF-8' in your shell") return True return False
@classmethod
[docs] def check_ffprobe(cls): """ Check whether ``ffprobe`` can be called. Return ``True`` on failure and ``False`` on success. :rtype: bool """ try: from aeneas.ffprobewrapper import FFPROBEWrapper file_path = gf.absolute_path(u"tools/res/audio.mp3", __file__) prober = FFPROBEWrapper() properties = prober.read_properties(file_path) gf.print_success(u"ffprobe OK") return False except: pass gf.print_error(u"ffprobe ERROR") gf.print_info(u" Please make sure you have ffprobe installed correctly") gf.print_info(u" (usually it is provided by the ffmpeg installer)") gf.print_info(u" and that its path is in your PATH environment variable") return True
@classmethod
[docs] def check_ffmpeg(cls): """ Check whether ``ffmpeg`` can be called. Return ``True`` on failure and ``False`` on success. :rtype: bool """ try: from aeneas.ffmpegwrapper import FFMPEGWrapper input_file_path = gf.absolute_path(u"tools/res/audio.mp3", __file__) handler, output_file_path = gf.tmp_file(suffix=u".wav") converter = FFMPEGWrapper() result = converter.convert(input_file_path, output_file_path) gf.delete_file(handler, output_file_path) if result: gf.print_success(u"ffmpeg OK") return False except: pass gf.print_error(u"ffmpeg ERROR") gf.print_info(u" Please make sure you have ffmpeg installed correctly") gf.print_info(u" and that its path is in your PATH environment variable") return True
@classmethod
[docs] def check_espeak(cls): """ Check whether ``espeak`` can be called. Return ``True`` on failure and ``False`` on success. :rtype: bool """ try: from aeneas.textfile import TextFile from aeneas.textfile import TextFragment from aeneas.ttswrappers.espeakttswrapper import ESPEAKTTSWrapper text = u"From fairest creatures we desire increase," text_file = TextFile() text_file.add_fragment(TextFragment(language=u"eng", lines=[text], filtered_lines=[text])) handler, output_file_path = gf.tmp_file(suffix=u".wav") ESPEAKTTSWrapper().synthesize_multiple(text_file, output_file_path) gf.delete_file(handler, output_file_path) gf.print_success(u"espeak OK") return False except: pass gf.print_error(u"espeak ERROR") gf.print_info(u" Please make sure you have espeak installed correctly") gf.print_info(u" and that its path is in your PATH environment variable") gf.print_info(u" You might also want to check that the espeak-data directory") gf.print_info(u" is set up correctly, for example, it has the correct permissions") return True
@classmethod
[docs] def check_tools(cls): """ Check whether ``aeneas.tools.*`` can be imported. Return ``True`` on failure and ``False`` on success. :rtype: bool """ try: from aeneas.tools.convert_syncmap import ConvertSyncMapCLI # disabling this check, as it requires the optional dependency youtube-dl # COMMENTED from aeneas.tools.download import DownloadCLI from aeneas.tools.execute_job import ExecuteJobCLI from aeneas.tools.execute_task import ExecuteTaskCLI from aeneas.tools.extract_mfcc import ExtractMFCCCLI from aeneas.tools.ffmpeg_wrapper import FFMPEGWrapperCLI from aeneas.tools.ffprobe_wrapper import FFPROBEWrapperCLI # disabling this check, as it requires the optional dependency Pillow # COMMENTED from aeneas.tools.plot_waveform import PlotWaveformCLI from aeneas.tools.read_audio import ReadAudioCLI from aeneas.tools.read_text import ReadTextCLI from aeneas.tools.run_sd import RunSDCLI from aeneas.tools.run_vad import RunVADCLI from aeneas.tools.synthesize_text import SynthesizeTextCLI from aeneas.tools.validate import ValidateCLI gf.print_success(u"aeneas.tools OK") return False except: pass gf.print_error(u"aeneas.tools ERROR") gf.print_info(u" Unable to import one or more aeneas.tools") gf.print_info(u" Please check that you installed aeneas properly") return True
@classmethod
[docs] def check_cdtw(cls): """ Check whether Python C extension ``cdtw`` can be imported. Return ``True`` on failure and ``False`` on success. :rtype: bool """ if gf.can_run_c_extension("cdtw"): gf.print_success(u"aeneas.cdtw AVAILABLE") return False gf.print_warning(u"aeneas.cdtw NOT AVAILABLE") gf.print_info(u" You can still run aeneas but it will be significantly slower") gf.print_info(u" Please refer to the installation documentation for details") return True
@classmethod
[docs] def check_cmfcc(cls): """ Check whether Python C extension ``cmfcc`` can be imported. Return ``True`` on failure and ``False`` on success. :rtype: bool """ if gf.can_run_c_extension("cmfcc"): gf.print_success(u"aeneas.cmfcc AVAILABLE") return False gf.print_warning(u"aeneas.cmfcc NOT AVAILABLE") gf.print_info(u" You can still run aeneas but it will be significantly slower") gf.print_info(u" Please refer to the installation documentation for details") return True
@classmethod
[docs] def check_cew(cls): """ Check whether Python C extension ``cew`` can be imported. Return ``True`` on failure and ``False`` on success. :rtype: bool """ if gf.can_run_c_extension("cew"): gf.print_success(u"aeneas.cew AVAILABLE") return False gf.print_warning(u"aeneas.cew NOT AVAILABLE") gf.print_info(u" You can still run aeneas but it will be a bit slower") gf.print_info(u" Please refer to the installation documentation for details") return True
@classmethod
[docs] def check_all(cls, tools=True, encoding=True, c_ext=True): """ Perform all checks. Return a tuple of booleans ``(errors, warnings, c_ext_warnings)``. :param bool tools: if ``True``, check aeneas tools :param bool encoding: if ``True``, check shell encoding :param bool c_ext: if ``True``, check Python C extensions :rtype: (bool, bool, bool) """ # errors are fatal if cls.check_ffprobe(): return (True, False, False) if cls.check_ffmpeg(): return (True, False, False) if cls.check_espeak(): return (True, False, False) if (tools) and (cls.check_tools()): return (True, False, False) # warnings are non-fatal warnings = False c_ext_warnings = False if encoding: warnings = cls.check_shell_encoding() if c_ext: # we do not want lazy evaluation c_ext_warnings = cls.check_cdtw() or c_ext_warnings c_ext_warnings = cls.check_cmfcc() or c_ext_warnings c_ext_warnings = cls.check_cew() or c_ext_warnings # return results return (False, warnings, c_ext_warnings)
def main(): errors, warnings, c_ext_warnings = Diagnostics.check_all() if errors: sys.exit(1) if c_ext_warnings: gf.print_warning(u"All required dependencies are met but at least one Python C extension is not available") sys.exit(2) else: gf.print_success(u"All required dependencies are met and all available Python C extensions are working") sys.exit(0) if __name__ == '__main__': main()