termux-tts 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,64 +1,64 @@
1
- """
2
- termux-tts: Production-Grade 4-Tier TTS Framework for Android Termux.
3
- - Tier 1: Parametric DSP Formant Synthesizer Engine (0MB Zero-Dependency)
4
- - Tier 2: Android System Native Voice Engine Bridge (Samsung / Google Voice)
5
- - Tier 3: Authentic C++ Subprocess-Isolated Sherpa-ONNX Neural Vocoder (VITS Deep Learning)
6
- - Tier 4: Pure On-Device Expressive Emotional Synthesizer (Conversational Tags)
7
- """
8
-
9
- from .engine import TTSEngine, load, doctor
10
- from .engine_native import NativeAndroidEngine, NativeResult
11
- from .engine_dsp import ParametricDSPEngine, DSPResult, QUALITY_PRESETS, DSPSynthesizer
12
- from .engine_sherpa import SherpaNeuralEngine, SherpaResult
13
- from .engine_vulkan import VulkanNeuralEngine, VulkanResult
14
- from .engine_expressive import ExpressiveEngine, ExpressiveResult
15
- from .installer import run_installation
16
- from .tokenizer import PhoneticTokenizer, EXPRESSIVE_TAGS
17
- from .g2p_korean import KoreanG2PEngine, korean_text_to_phonemes
18
- from .audio import AudioBuffer
19
- from .exceptions import (
20
- TTSError,
21
- TTSModelLoadError,
22
- TTSInferenceError,
23
- VulkanInitializationError,
24
- TTSAudioEncodingError,
25
- TTSLanguageNotSupportedError
26
- )
27
-
28
- # Backward-compatibility alias
29
- ONNXNeuralEngine = SherpaNeuralEngine
30
- ONNXResult = SherpaResult
31
-
32
- __version__ = "1.4.1"
33
- __all__ = [
34
- "TTSEngine",
35
- "load",
36
- "doctor",
37
- "ParametricDSPEngine",
38
- "DSPSynthesizer",
39
- "DSPResult",
40
- "NativeAndroidEngine",
41
- "NativeResult",
42
- "SherpaNeuralEngine",
43
- "SherpaResult",
44
- "VulkanNeuralEngine",
45
- "VulkanResult",
46
- "ExpressiveEngine",
47
- "ExpressiveResult",
48
- "run_installation",
49
- "ONNXNeuralEngine",
50
- "ONNXResult",
51
- "QUALITY_PRESETS",
52
- "PhoneticTokenizer",
53
- "KoreanG2PEngine",
54
- "korean_text_to_phonemes",
55
- "EXPRESSIVE_TAGS",
56
- "AudioBuffer",
57
- "TTSError",
58
- "TTSModelLoadError",
59
- "TTSInferenceError",
60
- "VulkanInitializationError",
61
- "TTSAudioEncodingError",
62
- "TTSLanguageNotSupportedError"
63
- ]
1
+ """
2
+ termux-tts: Production-Grade 4-Tier TTS Framework for Android Termux.
3
+ - Tier 1: Parametric DSP Formant Synthesizer Engine (0MB Zero-Dependency)
4
+ - Tier 2: Android System Native Voice Engine Bridge (Samsung / Google Voice)
5
+ - Tier 3: Authentic C++ Subprocess-Isolated Sherpa-ONNX Neural Vocoder (VITS Deep Learning)
6
+ - Tier 4: Pure On-Device Expressive Emotional Synthesizer (Conversational Tags)
7
+ """
8
+
9
+ from .engine import TTSEngine, load, doctor
10
+ from .engine_native import NativeAndroidEngine, NativeResult
11
+ from .engine_dsp import ParametricDSPEngine, DSPResult, QUALITY_PRESETS, DSPSynthesizer
12
+ from .engine_sherpa import SherpaNeuralEngine, SherpaResult
13
+ from .engine_vulkan import VulkanNeuralEngine, VulkanResult
14
+ from .engine_expressive import ExpressiveEngine, ExpressiveResult
15
+ from .installer import run_installation
16
+ from .tokenizer import PhoneticTokenizer, EXPRESSIVE_TAGS
17
+ from .g2p_korean import KoreanG2PEngine, korean_text_to_phonemes
18
+ from .audio import AudioBuffer
19
+ from .exceptions import (
20
+ TTSError,
21
+ TTSModelLoadError,
22
+ TTSInferenceError,
23
+ VulkanInitializationError,
24
+ TTSAudioEncodingError,
25
+ TTSLanguageNotSupportedError
26
+ )
27
+
28
+ # Backward-compatibility alias
29
+ ONNXNeuralEngine = SherpaNeuralEngine
30
+ ONNXResult = SherpaResult
31
+
32
+ __version__ = "1.4.3"
33
+ __all__ = [
34
+ "TTSEngine",
35
+ "load",
36
+ "doctor",
37
+ "ParametricDSPEngine",
38
+ "DSPSynthesizer",
39
+ "DSPResult",
40
+ "NativeAndroidEngine",
41
+ "NativeResult",
42
+ "SherpaNeuralEngine",
43
+ "SherpaResult",
44
+ "VulkanNeuralEngine",
45
+ "VulkanResult",
46
+ "ExpressiveEngine",
47
+ "ExpressiveResult",
48
+ "run_installation",
49
+ "ONNXNeuralEngine",
50
+ "ONNXResult",
51
+ "QUALITY_PRESETS",
52
+ "PhoneticTokenizer",
53
+ "KoreanG2PEngine",
54
+ "korean_text_to_phonemes",
55
+ "EXPRESSIVE_TAGS",
56
+ "AudioBuffer",
57
+ "TTSError",
58
+ "TTSModelLoadError",
59
+ "TTSInferenceError",
60
+ "VulkanInitializationError",
61
+ "TTSAudioEncodingError",
62
+ "TTSLanguageNotSupportedError"
63
+ ]
64
64
 
@@ -9,10 +9,37 @@ import urllib.request
9
9
  import shutil
10
10
  from pathlib import Path
11
11
 
12
- VULKAN_BINARY_RELEASE_URL = (
13
- "https://github.com/uno-km/termux-sherpa-ncnn/releases/download/"
14
- "v1.0.0-vulkan/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz"
15
- )
12
+ def get_candidate_vulkan_binary_urls():
13
+ """Generate dynamic candidate endpoints for Vulkan binary provisioner."""
14
+ try:
15
+ from . import __version__
16
+ except Exception:
17
+ __version__ = "1.4.3"
18
+
19
+ urls = []
20
+ custom_tag = os.environ.get("TERMUX_TTS_RELEASE_TAG", "").strip()
21
+ custom_base = os.environ.get("TERMUX_TTS_RELEASE_BASE", "").strip()
22
+
23
+ if custom_base:
24
+ urls.append(f"{custom_base.rstrip('/')}/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz")
25
+ if custom_tag:
26
+ tag = custom_tag if custom_tag.startswith("v") else f"v{custom_tag}"
27
+ urls.append(f"https://github.com/uno-km/termux-tts/releases/download/{tag}/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz")
28
+
29
+ # 1. termux-tts current version SSOT
30
+ current_tag = f"v{__version__}"
31
+ urls.append(f"https://github.com/uno-km/termux-tts/releases/download/{current_tag}/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz")
32
+
33
+ # 2. termux-tts latest release
34
+ urls.append("https://github.com/uno-km/termux-tts/releases/latest/download/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz")
35
+
36
+ # 3. ameva-runtime unified SSOT ecosystem release fallback
37
+ urls.append("https://github.com/uno-km/ameva-runtime/releases/latest/download/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz")
38
+
39
+ # 4. Companion release fallback
40
+ urls.append("https://github.com/uno-km/termux-sherpa-ncnn/releases/download/v1.0.0-vulkan/sherpa-ncnn-offline-tts-vulkan-arm64.tar.gz")
41
+
42
+ return urls
16
43
 
17
44
  MODEL_REGISTRY = {
18
45
  "high": {
@@ -48,8 +75,13 @@ def get_install_paths():
48
75
  return bin_dir, cache_dir
49
76
 
50
77
  def download_with_progress(url: str, dest_path: Path, label: str):
78
+ try:
79
+ from . import __version__
80
+ except Exception:
81
+ __version__ = "1.4.3"
82
+
51
83
  print(f" [DOWNLOADING] {label}...")
52
- req = urllib.request.Request(url, headers={"User-Agent": "termux-tts-installer/1.3.0"})
84
+ req = urllib.request.Request(url, headers={"User-Agent": f"termux-tts-installer/{__version__} (Android; ARM64)"})
53
85
  with urllib.request.urlopen(req) as resp, open(dest_path, "wb") as out_f:
54
86
  total = int(resp.headers.get("Content-Length", 0))
55
87
  downloaded = 0
@@ -69,13 +101,30 @@ def download_with_progress(url: str, dest_path: Path, label: str):
69
101
  def install_vulkan_binary(force: bool = False) -> Path:
70
102
  bin_dir, _ = get_install_paths()
71
103
  binary_path = bin_dir / "sherpa-ncnn-offline-tts"
104
+ prefix_bin = Path(os.environ.get("PREFIX", "/data/data/com.termux/files/usr")) / "bin"
72
105
 
73
106
  if binary_path.exists() and not force:
74
107
  print(f" [OK] Pre-compiled Vulkan binary already exists: {binary_path}")
75
108
  return binary_path
76
109
 
77
110
  tar_path = bin_dir / "sherpa-vulkan.tar.gz"
78
- download_with_progress(VULKAN_BINARY_RELEASE_URL, tar_path, "ARM64 Vulkan Binary (3.9MB)")
111
+ candidate_urls = get_candidate_vulkan_binary_urls()
112
+ download_success = False
113
+
114
+ for url in candidate_urls:
115
+ try:
116
+ download_with_progress(url, tar_path, f"ARM64 Vulkan Binary ({url})")
117
+ if tar_path.exists() and tar_path.stat().st_size > 500 * 1024:
118
+ download_success = True
119
+ break
120
+ except Exception as dl_err:
121
+ print(f" [-] Candidate URL failed ({url}): {dl_err}")
122
+ if tar_path.exists():
123
+ tar_path.unlink(missing_ok=True)
124
+ continue
125
+
126
+ if not download_success:
127
+ raise RuntimeError("Failed to download sherpa-ncnn-offline-tts from any candidate endpoints.")
79
128
 
80
129
  print(" [EXTRACTING] Installing binary to ~/.local/bin...")
81
130
  with tarfile.open(tar_path, "r:gz") as tar:
@@ -83,6 +132,17 @@ def install_vulkan_binary(force: bool = False) -> Path:
83
132
 
84
133
  tar_path.unlink(missing_ok=True)
85
134
  binary_path.chmod(0o755)
135
+
136
+ # Dual-path installation to PREFIX/bin if writable
137
+ try:
138
+ if prefix_bin.exists() and os.access(prefix_bin, os.W_OK):
139
+ target_prefix_bin = prefix_bin / "sherpa-ncnn-offline-tts"
140
+ shutil.copy2(binary_path, target_prefix_bin)
141
+ target_prefix_bin.chmod(0o755)
142
+ print(f" [SYMLINK/COPY] Linked to {target_prefix_bin}")
143
+ except OSError:
144
+ pass
145
+
86
146
  print(f" [SUCCESS] Installed: {binary_path}")
87
147
  return binary_path
88
148