working backend
This commit is contained in:
+48
-27
@@ -28,15 +28,13 @@ Classes:
|
||||
run(input_source: PathLike, output_dest: PathLike) -> subprocess.CompletedProcess: Execute backend command.
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
PathLike = Union[str, Path]
|
||||
from typing import Optional, Callable
|
||||
|
||||
from .vendor_utils import build_run_command
|
||||
|
||||
from . import PathLike
|
||||
|
||||
class GenericTTSBackend:
|
||||
"""Generic TTS backend for handling text-to-speech conversion.
|
||||
@@ -46,11 +44,13 @@ class GenericTTSBackend:
|
||||
language (Optional[str]): Language code for TTS output.
|
||||
voice (Optional[str]): Voice name for TTS output.
|
||||
"""
|
||||
|
||||
FLAGS = {}
|
||||
INTERMEDIATE_TXT = False
|
||||
DEFAULT_SPEAKER = None
|
||||
DEFAULT_SAMPLE = None
|
||||
REPO: Optional[str] = None
|
||||
CMD: Optional[str] = None
|
||||
FLAGS: Optional[dict] = {}
|
||||
INTERMEDIATE_TXT: Optional[bool] = False
|
||||
INTERMEDIATE_CALL: Optional[Callable] = None
|
||||
DEFAULT_SPEAKER: Optional[str] = None
|
||||
DEFAULT_SAMPLE: Optional[str] = None
|
||||
SUPPORTED_AUDIO_FORMATS = {
|
||||
# subclasses may override this
|
||||
".m4b": "m4b",
|
||||
@@ -60,11 +60,8 @@ class GenericTTSBackend:
|
||||
".ogg": "ogg",
|
||||
}
|
||||
|
||||
_INPUT_FLAG_MAP = lambda self, is_dir, path: [
|
||||
"--input-dir", path] if is_dir else ["--input-file", path]
|
||||
|
||||
_OUTPUT_FLAG_MAP = lambda self, is_dir, path: [
|
||||
"--output-dir", path] if is_dir else ["--output-file", path]
|
||||
INPUT_FLAG = {True: "--input-dir", False: "--input-file"}
|
||||
OUTPUT_FLAG = {True: "--output-dir", False: "--output-file"}
|
||||
|
||||
def __init__(self,**kwargs):
|
||||
for k,v in kwargs.items():
|
||||
@@ -78,20 +75,23 @@ class GenericTTSBackend:
|
||||
return Path(value).resolve()
|
||||
|
||||
|
||||
def gen_input_flag(self, input_path: Path) -> str:
|
||||
return self._INPUT_FLAG_MAP(
|
||||
self._normalize_path(input_path).is_dir(), input_path)
|
||||
def gen_input_flag(self, input_path: Path) -> list[str]:
|
||||
p = self._normalize_path(input_path)
|
||||
return [self.INPUT_FLAG[p.is_dir()], str(p)]
|
||||
|
||||
|
||||
def gen_output_flag(self, output_path: Path) -> str:
|
||||
return self._OUTPUT_FLAG_MAP(
|
||||
self._normalize_path(output_path).is_dir(), output_path)
|
||||
|
||||
def gen_output_flag(self, output_path: Path) -> list[str]:
|
||||
p = self._normalize_path(output_path)
|
||||
return [self.OUTPUT_FLAG[p.is_dir()], str(p)]
|
||||
|
||||
def _build_command(self, input_source: PathLike, output_dest: PathLike) -> list[str]:
|
||||
command = [self.backend_cmd]
|
||||
if self.REPO is None or self.CMD is None:
|
||||
command = [self.CMD]
|
||||
else:
|
||||
command = build_run_command(self.REPO, CMD=self.CMD)
|
||||
command.extend(self.gen_input_flag(input_source))
|
||||
command.extend(self.gen_output_flag(output_dest))
|
||||
if self.gen_output_flag:
|
||||
command.extend(self.gen_output_flag(output_dest))
|
||||
for flag_name, var_name in self.FLAGS.items():
|
||||
if getattr(self, flag_name, None) is not None:
|
||||
command.extend([
|
||||
@@ -104,9 +104,10 @@ class GenericTTSBackend:
|
||||
output_dest: PathLike,
|
||||
**kwargs
|
||||
) -> subprocess.CompletedProcess:
|
||||
|
||||
|
||||
|
||||
command = self._build_command(input_source, output_dest)
|
||||
print(command)
|
||||
print(f"Running command: {' '.join(command)}")
|
||||
completed = subprocess.run(
|
||||
self._build_command(input_source, output_dest),
|
||||
cwd=str(self._normalize_path(input_source).parent),
|
||||
@@ -115,6 +116,12 @@ class GenericTTSBackend:
|
||||
if self.INTERMEDIATE_TXT:
|
||||
txt_file = self._normalize_path(input_source).with_suffix(".txt")
|
||||
if txt_file.exists():
|
||||
if (self.INTERMEDIATE_CALL is not None and
|
||||
kwargs.get('replace_map', None) is not None):
|
||||
self.INTERMEDIATE_CALL(
|
||||
txt_file,
|
||||
txt_file.with_stem(txt_file.stem + "_replaced"), kwargs.get('replace_map', {}))
|
||||
txt_file = txt_file.with_stem(txt_file.stem + "_replaced")
|
||||
completed = subprocess.run(
|
||||
self._build_command(txt_file, output_dest),
|
||||
cwd=str(self._normalize_path(input_source).parent),
|
||||
@@ -124,4 +131,18 @@ class GenericTTSBackend:
|
||||
|
||||
return completed
|
||||
|
||||
|
||||
|
||||
|
||||
def _replace_map(self,
|
||||
input_path: PathLike,
|
||||
output_path: PathLike,
|
||||
replace_map: dict = None,
|
||||
):
|
||||
"""Run a simple regex substitution for the intermediate text extraction step."""
|
||||
if replace_map is not None:
|
||||
pattern = re.compile("|".join(re.escape(key) for key in replace_map.keys()))
|
||||
|
||||
with open(input_path, 'r') as src, open(output_path, 'w') as dest:
|
||||
for line in src:
|
||||
dest.write(
|
||||
pattern.sub(lambda match: replace_map[match.group(0)], line))
|
||||
Reference in New Issue
Block a user