def dummy_sync_map(self): sync_map = SyncMap() frag = TextFragment("f001", Language.EN, "Fragment 1") sync_map.append(SyncMapFragment(frag, 0, 12.345)) frag = TextFragment("f002", Language.EN, "Fragment 2") sync_map.append(SyncMapFragment(frag, 12.345, 23.456)) frag = TextFragment("f003", Language.EN, "Fragment 3") sync_map.append(SyncMapFragment(frag, 23.456, 34.567)) return sync_map
def dummy_sync_map(self): sync_map = SyncMap() frag = TextFragment(u"f001", Language.ENG, [u"Fragment 1"]) sync_map.add_fragment(SyncMapFragment(frag, 0, 12.345)) frag = TextFragment(u"f002", Language.ENG, [u"Fragment 2"]) sync_map.add_fragment(SyncMapFragment(frag, 12.345, 23.456)) frag = TextFragment(u"f003", Language.ENG, [u"Fragment 3"]) sync_map.add_fragment(SyncMapFragment(frag, 23.456, 34.567)) return sync_map
def test_append_fragment_multiple(self): tfl = TextFile() self.assertEqual(len(tfl), 0) tfl.append_fragment(TextFragment("a1", Language.EN, "fragment 1")) self.assertEqual(len(tfl), 1) tfl.append_fragment(TextFragment("a2", Language.EN, "fragment 2")) self.assertEqual(len(tfl), 2) tfl.append_fragment(TextFragment("a3", Language.EN, "fragment 3")) self.assertEqual(len(tfl), 3)
def test_add_fragment_multiple(self): tfl = TextFile() self.assertEqual(len(tfl), 0) tfl.add_fragment(TextFragment(u"a1", Language.ENG, [u"fragment 1"])) self.assertEqual(len(tfl), 1) tfl.add_fragment(TextFragment(u"a2", Language.ENG, [u"fragment 2"])) self.assertEqual(len(tfl), 2) tfl.add_fragment(TextFragment(u"a3", Language.ENG, [u"fragment 3"])) self.assertEqual(len(tfl), 3) self.assertEqual(tfl.chars, 30)
def total_FA(soundfile, mylines, myhead, mytail, config=None): """Runs Aeneas as a library. This function isn't in use, currently, as we haven't managed to get reliable results in this way.""" # create Task object if config is None: config_string = ( u"task_language=nor|is_text_type=plain|os_task_file_format=json|is_audio_file_head_length=%s|is_audio_file_tail_length=%s" % (myhead, mytail)) print(config_string) else: config_string = ( u"task_language=nor|is_text_type=plain|os_task_file_format=json|is_audio_file_head_length=%s|is_audio_file_tail_length=%s|%s" % (myhead, mytail, config)) print(config_string) task = Task(config_string=config_string) print(task) task.audio_file_path_absolute = soundfile textfile = TextFile() print(textfile) #task.sync_map_file_path_absolute = outfile for identifier, frag_text in mylines: textfile.add_fragment( TextFragment(identifier, Language.NOR, frag_text, frag_text)) task.text_file = textfile print(len(task.text_file)) ExecuteTask(task).execute() syncmaplist = task.sync_map.fragments return syncmaplist
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
def _add_fragment(cls, syncmap, identifier, lines, begin, end, language=None): """ Add a new fragment to ``syncmap``. :param syncmap: the syncmap to append to :type syncmap: :class:`~aeneas.syncmap.SyncMap` :param identifier: the identifier :type identifier: string :param lines: the lines of the text :type lines: list of string :param begin: the begin time :type begin: :class:`~aeneas.exacttiming.TimeValue` :param end: the end time :type end: :class:`~aeneas.exacttiming.TimeValue` :param language: the language :type language: string """ syncmap.add_fragment( SyncMapFragment(text_fragment=TextFragment(identifier=identifier, lines=lines, language=language), begin=begin, end=end))
def test_fragment_length(self): text = TextFragment(lines=[u"Hello", u"World"]) frag = SyncMapFragment(text_fragment=text, begin=TimeValue("1.234"), end=TimeValue("6.234")) self.assertEqual(frag.chars, 10) self.assertEqual(frag.length, 5) self.assertEqual(frag.has_zero_length, False)
def test_fragment_rate_zero(self): text = TextFragment(lines=[u"Hello", u"World"]) frag = SyncMapFragment(text_fragment=text, begin=TimeValue("1.234"), end=TimeValue("1.234")) self.assertEqual(frag.audio_duration, 0) self.assertEqual(frag.chars, 10) self.assertIsNone(frag.rate, None)
def tfl(self, frags): tfl = TextFile() for language, lines in frags: tfl.add_fragment( TextFragment(language=language, lines=lines, filtered_lines=lines)) return tfl
def test_fragment_regular_rate_zero_text(self): text = TextFragment() frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.REGULAR, begin=TimeValue("1.234"), end=TimeValue("6.234")) self.assertEqual(frag.length, 5) self.assertEqual(frag.chars, 0) self.assertEqual(frag.rate, 0)
def test_fragment_regular_rate_zero_length(self): text = TextFragment(lines=[u"Hello", u"World"]) frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.REGULAR, begin=TimeValue("1.234"), end=TimeValue("1.234")) self.assertEqual(frag.length, 0) self.assertEqual(frag.chars, 10) self.assertIsNone(frag.rate)
def test_fragment_rate_valid(self): text = TextFragment(lines=[u"Hello", u"World"]) frag = SyncMapFragment(text_fragment=text, begin=TimeValue("1.234"), end=TimeValue("6.234")) self.assertEqual(frag.audio_duration, 5) self.assertEqual(frag.chars, 10) self.assertEqual(frag.rate, 2.000) self.assertEqual(frag.rate, Decimal("2.000"))
def dummy_sync_map(self): sync_map = SyncMap() frag = TextFragment(u"f001", Language.ENG, [u"Fragment 1"]) sync_map.add_fragment( SyncMapFragment(text_fragment=frag, begin=TimeValue("0.000"), end=TimeValue("12.345"))) frag = TextFragment(u"f002", Language.ENG, [u"Fragment 2"]) sync_map.add_fragment( SyncMapFragment(text_fragment=frag, begin=TimeValue("12.345"), end=TimeValue("23.456"))) frag = TextFragment(u"f003", Language.ENG, [u"Fragment 3"]) sync_map.add_fragment( SyncMapFragment(text_fragment=frag, begin=TimeValue("23.456"), end=TimeValue("34.567"))) return sync_map
def test_fragment_regular_rate_non_zero(self): text = TextFragment(lines=[u"Hello", u"World"]) frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.REGULAR, begin=TimeValue("1.234"), end=TimeValue("6.234")) self.assertEqual(frag.length, 5) self.assertEqual(frag.chars, 10) self.assertEqual(frag.rate, 2.000) self.assertEqual(frag.rate, Decimal("2.000"))
def test_fragment_not_regular_rate_zero_length(self): for t in SyncMapFragment.NOT_REGULAR_TYPES: text = TextFragment() frag = SyncMapFragment(text_fragment=text, fragment_type=t, begin=TimeValue("1.234"), end=TimeValue("1.234")) self.assertEqual(frag.length, 0) self.assertEqual(frag.chars, 0) self.assertIsNone(frag.rate)
def _level_time_map_to_tree(self, text_file, time_map, tree=None, add_head_tail=True): """ Convert a level time map into a Tree of SyncMapFragments. The time map is a list of pairs ``[start_time, end_time]``, of length equal to number of fragments + 2, where the two extra elements are for the HEAD (first) and TAIL (last). :param text_file: the text file object :type text_file: :class:`~aeneas.textfile.TextFile` :param list time_map: the time map :param tree: the tree; if ``None``, a new Tree will be built :type tree: :class:`~aeneas.tree.Tree` :rtype: :class:`~aeneas.tree.Tree` """ if tree is None: tree = Tree() if add_head_tail: fragments = ([ TextFragment(u"HEAD", self.task.configuration["language"], [u""]) ] + text_file.fragments + [ TextFragment(u"TAIL", self.task.configuration["language"], [u""]) ]) i = 0 else: fragments = text_file.fragments i = 1 for fragment in fragments: interval = time_map[i] sm_frag = SyncMapFragment(fragment, interval[0], interval[1]) tree.add_child(Tree(value=sm_frag)) i += 1 return tree
def test_fragment_regular_rate_slack(self): params = [("20.000", "-0.500", "0.500"), ("10.000", "-1.000", "0.000"), ("5.000", "-2.000", "-1.000")] text = TextFragment(lines=[u"Hello", u"World"]) for r, e_zero, e_nonzero in params: frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.REGULAR, begin=TimeValue("1.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_slack(Decimal(r)), TimeValue(e_zero)) frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.REGULAR, begin=TimeValue("0.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_slack(Decimal(r)), TimeValue(e_nonzero))
def test_fragment_nonspeech_rate_slack(self): params = [("20.000", "0.000", "1.000"), ("10.000", "0.000", "1.000"), ("5.000", "0.000", "1.000")] text = TextFragment() for r, e_zero, e_nonzero in params: frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.NONSPEECH, begin=TimeValue("1.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_slack(Decimal(r)), TimeValue(e_zero)) frag = SyncMapFragment(text_fragment=text, fragment_type=SyncMapFragment.NONSPEECH, begin=TimeValue("0.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_slack(Decimal(r)), TimeValue(e_nonzero))
def test_fragment_not_regular_rate_lack(self): params = [("20.000", "0.000", "0.000"), ("10.000", "0.000", "0.000"), ("5.000", "0.000", "0.000")] text = TextFragment() for t in SyncMapFragment.NOT_REGULAR_TYPES: for r, e_zero, e_nonzero in params: frag = SyncMapFragment(text_fragment=text, fragment_type=t, begin=TimeValue("1.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_lack(Decimal(r)), TimeValue(e_zero)) frag = SyncMapFragment(text_fragment=text, fragment_type=t, begin=TimeValue("0.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_lack(Decimal(r)), TimeValue(e_nonzero))
def inject_long_nonspeech_fragments(self, pairs, replacement_string): """ Inject nonspeech fragments corresponding to the given intervals in this fragment list. It is assumed that ``pairs`` are consistent, e.g. they are produced by ``fragments_ending_inside_nonspeech_intervals``. :param list pairs: list of ``(TimeInterval, int)`` pairs, each identifying a nonspeech interval and the corresponding fragment index ending inside it :param string replacement_string: the string to be applied to the nonspeech intervals """ self.log(u"Called inject_long_nonspeech_fragments") # set the appropriate fragment text if replacement_string in [ None, gc.PPV_TASK_ADJUST_BOUNDARY_NONSPEECH_REMOVE ]: self.log(u" Remove long nonspeech") lines = [] else: self.log( [u" Replace long nonspeech with '%s'", replacement_string]) lines = [replacement_string] # first, make room for the nonspeech intervals self.log(u" First pass: making room...") for nsi, index in pairs: self[index].interval.end = nsi.begin self[index + 1].interval.begin = nsi.end self.log(u" First pass: making room... done") self.log(u" Second pass: append nonspeech intervals...") for i, (nsi, index) in enumerate(pairs, 1): identifier = u"n%06d" % i self.add(SyncMapFragment(text_fragment=TextFragment( identifier=identifier, language=None, lines=lines, filtered_lines=lines), interval=nsi, fragment_type=SyncMapFragment.NONSPEECH), sort=False) self.log(u" Second pass: append nonspeech intervals... done") self.log(u" Third pass: sorting...") self.sort() self.log(u" Third pass: sorting... done")
def test_fragment_head_tail_rate_slack(self): params = [("20.000", "0.000", "0.000"), ("10.000", "0.000", "0.000"), ("5.000", "0.000", "0.000")] text = TextFragment() for t in [SyncMapFragment.HEAD, SyncMapFragment.TAIL]: for r, e_zero, e_nonzero in params: frag = SyncMapFragment(text_fragment=text, fragment_type=t, begin=TimeValue("1.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_slack(Decimal(r)), TimeValue(e_zero)) frag = SyncMapFragment(text_fragment=text, fragment_type=t, begin=TimeValue("0.000"), end=TimeValue("1.000")) self.assertEqual(frag.rate_slack(Decimal(r)), TimeValue(e_nonzero))
def test_append_fragment(self): tfl = TextFile() self.assertEqual(len(tfl), 0) tfl.append_fragment(TextFragment("a1", Language.EN, "fragment 1")) self.assertEqual(len(tfl), 1)
def test_tf_lines_invalid_str(self): with self.assertRaises(TypeError): tf = TextFragment(lines=[b"foo"])
def _create_syncmap(self, adjusted_map): """ Create a sync map out of the provided interval map, and store it in the task object. Return a success bool flag. """ self._log("Creating sync map") self._log([ "Number of fragments in adjusted map (including HEAD and TAIL): %d", len(adjusted_map) ]) # adjusted map has 2 elements (HEAD and TAIL) more than text_file if len(adjusted_map) != len(self.task.text_file.fragments) + 2: self._log( "The number of sync map fragments does not match the number of text fragments (+2)", Logger.CRITICAL) return False try: sync_map = SyncMap() head = adjusted_map[0] tail = adjusted_map[-1] # get language language = Language.EN self._log(["Language set to default: %s", language]) if len(self.task.text_file.fragments) > 0: language = self.task.text_file.fragments[0].language self._log(["Language read from text_file: %s", language]) # get head/tail format head_tail_format = self.task.configuration.os_file_head_tail_format # note that str() is necessary, as head_tail_format might be None self._log(["Head/tail format: %s", str(head_tail_format)]) # add head sync map fragment if needed if head_tail_format == SyncMapHeadTailFormat.ADD: head_frag = TextFragment(u"HEAD", language, [u""]) sync_map_frag = SyncMapFragment(head_frag, head[0], head[1]) sync_map.append(sync_map_frag) self._log(["Adding head (ADD): %.3f %.3f", head[0], head[1]]) # stretch first and last fragment timings if needed if head_tail_format == SyncMapHeadTailFormat.STRETCH: self._log([ "Stretching (STRETCH): %.3f => %.3f (head) and %.3f => %.3f (tail)", adjusted_map[1][0], head[0], adjusted_map[-2][1], tail[1] ]) adjusted_map[1][0] = head[0] adjusted_map[-2][1] = tail[1] i = 1 for fragment in self.task.text_file.fragments: start = adjusted_map[i][0] end = adjusted_map[i][1] sync_map_frag = SyncMapFragment(fragment, start, end) sync_map.append(sync_map_frag) i += 1 # add tail sync map fragment if needed if head_tail_format == SyncMapHeadTailFormat.ADD: tail_frag = TextFragment(u"TAIL", language, [u""]) sync_map_frag = SyncMapFragment(tail_frag, tail[0], tail[1]) sync_map.append(sync_map_frag) self._log(["Adding tail (ADD): %.3f %.3f", tail[0], tail[1]]) self.task.sync_map = sync_map self._log("Creating sync map: succeeded") return True except Exception as e: self._log("Creating sync map: failed") self._log(["Message: %s", str(e)]) return False
def test_add_fragment(self): tfl = TextFile() self.assertEqual(len(tfl), 0) tfl.add_fragment(TextFragment(u"a1", Language.ENG, [u"fragment 1"])) self.assertEqual(len(tfl), 1) self.assertEqual(tfl.chars, 10)
def test_tf_lines_unicode_empty_string_multiple(self): tf = TextFragment(lines=[u"", u"", u""]) self.assertEqual(len(tf), 3)
def test_tf_lines_unicode_multiple(self): tf = TextFragment(lines=[u"foo", u"bar", u"baz"]) self.assertEqual(len(tf), 3)
def test_tf_lines_unicode(self): tf = TextFragment(lines=[u"foo"]) self.assertEqual(len(tf), 1)
def test_tf_lines_invalid_str_mixed(self): with self.assertRaises(TypeError): tf = TextFragment(lines=[u"foo", b"bar", u"baz"])