diff --git a/src/calibre/ebooks/oeb/polish/container.py b/src/calibre/ebooks/oeb/polish/container.py index 67e95b0754..a279ffb69b 100644 --- a/src/calibre/ebooks/oeb/polish/container.py +++ b/src/calibre/ebooks/oeb/polish/container.py @@ -903,20 +903,21 @@ class Container(ContainerBase): # {{{ self.parsed_cache.pop(name, None) self.dirtied.discard(name) - def set_media_overlay_durations(self, duration_map): + def set_media_overlay_durations(self, duration_map=None): self.dirty(self.opf_name) for meta in self.opf_xpath('//opf:meta[@property="media:duration"]'): self.remove_from_xml(meta) metadata = self.opf_xpath('//opf:metadata')[0] total_duration = 0 - for item_id, duration in duration_map.items(): + for item_id, duration in (duration_map or {}).items(): meta = metadata.makeelement(OPF('meta'), property="media:duration", refines="#" + item_id) meta.text = seconds_to_timestamp(duration) self.insert_into_xml(metadata, meta) total_duration += duration - meta = metadata.makeelement(OPF('meta'), property="media:duration") - meta.text = seconds_to_timestamp(total_duration) - self.insert_into_xml(metadata, meta) + if duration_map: + meta = metadata.makeelement(OPF('meta'), property="media:duration") + meta.text = seconds_to_timestamp(total_duration) + self.insert_into_xml(metadata, meta) def dirty(self, name): ''' Mark the parsed object corresponding to name as dirty. See also: :meth:`parsed`. ''' diff --git a/src/calibre/ebooks/oeb/polish/tts.py b/src/calibre/ebooks/oeb/polish/tts.py index 19693e2710..dbc339e37f 100644 --- a/src/calibre/ebooks/oeb/polish/tts.py +++ b/src/calibre/ebooks/oeb/polish/tts.py @@ -116,8 +116,10 @@ def mark_sentences_in_html(root, lang: str = '', voice: str = '') -> list[Senten text = ''.join(c.text for c in self.texts) self.pos = 0 for start, length in split_into_sentences_for_tts_embed(text, self.lang): - elem_id = self.wrap_sentence(start, length) - ans.append(Sentence(elem_id, text[start:start+length], self.lang, self.voice)) + stext = text[start:start+length] + if stext.strip(): + elem_id = self.wrap_sentence(start, length) + ans.append(Sentence(elem_id, stext, self.lang, self.voice)) if self.has_tail: p = self.elem.getparent() spans = [] @@ -125,6 +127,8 @@ def mark_sentences_in_html(root, lang: str = '', voice: str = '') -> list[Senten for start, length in split_into_sentences_for_tts_embed(self.elem.tail, self.parent_lang): end = start + length text = self.elem.tail[start:end] + if not text.strip(): + continue if before is None: before = self.elem.tail[:start] span = self.make_wrapper(text, p) @@ -422,7 +426,7 @@ def remove_embedded_tts(container): container.set_media_overlay_durations({}) media_files = set() for item in manifest_items: - smil_id = item.get('media-overlay') + smil_id = item.attrib.pop('media-overlay', '') href = item.get('href') if href and smil_id: name = container.href_to_name(href, container.opf_name) @@ -469,17 +473,23 @@ def embed_tts(container, report_progress=None, callback_to_download_voices=None) return False all_voices = set() total_num_sentences = 0 + files_with_no_sentences = set() for i, (name, pfd) in enumerate(name_map.items()): pfd.root = container.parsed(name) pfd.sentences = mark_sentences_in_html(pfd.root, lang=language) - total_num_sentences += len(pfd.sentences) - for s in pfd.sentences: - key = s.lang, s.voice - pfd.key_map[key].append(s) - all_voices.add(key) - container.dirty(name) + if not pfd.sentences: + files_with_no_sentences.add(name) + else: + total_num_sentences += len(pfd.sentences) + for s in pfd.sentences: + key = s.lang, s.voice + pfd.key_map[key].append(s) + all_voices.add(key) + container.dirty(name) if report_progress(stage, name, i+1, len(name_map)): return False + for rname in files_with_no_sentences: + name_map.pop(rname) if callback_to_download_voices is None: piper.ensure_voices_downloaded(iter(all_voices)) else: