termux-stt 1.4.0 → 2.0.0

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.
package/README.md CHANGED
@@ -1,117 +1,84 @@
1
- # Termux-STT
2
-
3
- [![PyPI](https://img.shields.io/pypi/v/termux-stt.svg?style=flat-square&color=0369a1)](https://pypi.org/project/termux-stt/)
4
- [![Python](https://img.shields.io/pypi/pyversions/termux-stt.svg?style=flat-square)](https://pypi.org/project/termux-stt/)
5
- [![npm](https://img.shields.io/npm/v/termux-stt.svg?style=flat-square&color=b91c1c)](https://www.npmjs.com/package/termux-stt)
6
- [![npm downloads](https://img.shields.io/npm/dm/termux-stt.svg?style=flat-square&color=b91c1c)](https://www.npmjs.com/package/termux-stt)
7
- [![License](https://img.shields.io/badge/License-Apache_2.0-004499.svg?style=flat-square)](https://github.com/uno-km/termux-stt)
8
-
9
- > **디바이스 리소스를 활용한 통합 온디바이스 음성인식(STT) 및 순수 Python 128d X-Vector 화자 분리 프레임워크**
10
- > *Unified On-Device Speech-to-Text Utilizing Device Resources & Pure Python 128d X-Vector Speaker Diarization*
11
-
12
- ---
13
-
14
- ## Architecture & Overview
15
-
16
- Whisper.cpp, Vosk, Sherpa-ONNX 3대 네이티브 엔진을 통합하고, 닫힌 형태 순수 Python 128차원 X-Vector 클러스터링을 결합하여 80MB 미만의 초경량 메모리로 100% 온디바이스 실시간 음성인식과 화자 분리를 구현합니다.
17
-
18
- Integrates Whisper.cpp, Vosk, and Sherpa-ONNX with a closed-form pure-Python 128-dimensional X-Vector clustering algorithm that operates in under 80MB RAM with zero cloud egress.
19
-
20
- ---
21
-
22
- ## Installation & Quickstart
23
-
24
- ### Python (PyPI)
25
- ```bash
26
- pip install termux-stt
27
- ```
28
- ```python
29
- from termux_stt import create_engine
30
-
31
- # 1. Initialize Engine with Hybrid GPU-Encoder / CPU-Decoder Acceleration
32
- engine = create_engine("whisper", model="small", lang="en", threads=4, split_mode=True)
33
-
34
- # 2. Transcribe Audio directly into Subtitles
35
- result = engine.transcribe("samples/jfk_1min.wav")
36
- print("Transcript:\n", result.text)
37
- print("SRT Subtitles:\n", result.to_srt())
38
-
39
- # 3. 2-Speaker Diarization without PyTorch
40
- hybrid = create_engine("hybrid", lang="en", num_speakers=2)
41
- diar_result = hybrid.diarize("samples/jfk_1min.wav")
42
- for seg in diar_result.segments:
43
- print(f"[{seg.speaker}] ({seg.start:.1f}s -> {seg.end:.1f}s): {seg.text}")
44
-
45
- ```
46
-
47
- ### Node.js / TypeScript (npm)
48
- ```bash
49
- npm install termux-stt
50
- ```
51
- ```typescript
52
- const { createEngine } = require("termux-stt");
53
-
54
- async function main() {
55
- // 1. Initialize Whisper Engine
56
- const engine = createEngine("whisper", { model: "tiny", lang: "en", threads: 4 });
57
-
58
- // 2. Transcribe Audio
59
- const result = await engine.transcribe("samples/jfk_1min.wav");
60
- console.log("Transcript:", result.text);
61
- console.log("SRT Subtitles:\n", result.toSrt());
62
- }
63
- main();
64
-
65
- ```
66
-
67
- ---
68
-
69
- ## Distributed Clustering & Memory Pooling (AMEVA-Cluster)
70
-
71
- Termux-STT natively integrates with **AMEVA-Cluster** (`pip install ameva-cluster`) for distributed large-model speech recognition (e.g. `whisper-large-v3-turbo`) across interconnected mobile fleets.
72
-
73
- ### 1. Install Cluster Runtime
74
- ```bash
75
- pip install ameva-cluster
76
- # or Node.js:
77
- npm install @ameva/cluster
78
- ```
79
-
80
- ### 2. Launch Worker Node on Remote Phone
81
- ```bash
82
- # On remote worker device (e.g. Galaxy A53):
83
- ameva-cluster worker --port 50052
84
- ```
85
-
86
- ### 3. Distributed Transcription via Master Node
87
- ```bash
88
- # Master node sharding Whisper-Large layers across remote phone RAM:
89
- termux-stt transcribe meeting.wav \
90
- --model whisper-large-v3-turbo.bin \
91
- --rpc 192.0.2.10:50052,192.0.2.11:50052
92
- ```
93
-
94
- ```python
95
- from termux_stt import create_engine
96
-
97
- # Python SDK Distributed STT
98
- engine = create_engine(
99
- "whisper",
100
- model="large-v3-turbo",
101
- cluster_rpc_servers="192.0.2.10:50052,192.0.2.11:50052"
102
- )
103
- result = engine.transcribe("meeting.wav")
104
- print(result.text)
105
- ```
106
-
107
- ---
108
-
109
- ## Official Documentation & Benchmarks
110
- - [Official Architecture & API Reference](https://uno-km.vercel.app/lib/stt/)
111
- - [Ecosystem Metrics & Registry Stats](https://uno-km.vercel.app/foundation/metrics)
112
- - [AMEVA Open-Source Foundation Portal](https://uno-km.vercel.app/foundation/index.html)
113
-
114
- ---
115
-
116
- ## License
117
- Licensed under the Apache-2.0 License. Copyright (c) 2026 Eunho Kim ([@uno-km](https://github.com/uno-km)).
1
+ # Termux-STT
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/termux-stt.svg?style=flat-square&color=0369a1)](https://pypi.org/project/termux-stt/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/termux-stt.svg?style=flat-square)](https://pypi.org/project/termux-stt/)
5
+ [![npm](https://img.shields.io/npm/v/termux-stt.svg?style=flat-square&color=b91c1c)](https://www.npmjs.com/package/termux-stt)
6
+ [![npm downloads](https://img.shields.io/npm/dm/termux-stt.svg?style=flat-square&color=b91c1c)](https://www.npmjs.com/package/termux-stt)
7
+ [![License](https://img.shields.io/badge/License-Apache_2.0-004499.svg?style=flat-square)](https://github.com/uno-km/termux-stt)
8
+
9
+ > **디바이스 리소스를 활용한 통합 온디바이스 음성인식(STT) 및 차세대 신경망 화자 분리(PyAnnote 3.0 + CAM++ 192d + TS-VAD) 프레임워크**
10
+ > *Unified On-Device Speech-to-Text & Neural Multi-Speaker Diarization (PyAnnote 3.0 + CAM++ 192d + TS-VAD Overlap Resolver)*
11
+
12
+ ---
13
+
14
+ ## Architecture & Overview
15
+
16
+ Whisper.cpp(네이티브 Vulkan GPU / NEON CPU) 및 Sherpa-ONNX 듀얼 모던 엔진을 통합하고, PyAnnote 3.0 신경망 세그멘테이션, 3D-Speaker CAM++ 192차원 성문 임베딩, TS-VAD 동시 발화(마이크 물림) 분리기를 결합하여 완전 온디바이스 실시간 다중 화자 음성인식을 구현합니다.
17
+
18
+ Integrates Whisper.cpp (Native Vulkan GPU / NEON CPU) and Sherpa-ONNX with PyAnnote 3.0 neural segmentation, 3D-Speaker CAM++ 192-dim embeddings, and TS-VAD overlapped speech resolution with zero cloud egress.
19
+
20
+ ---
21
+
22
+ ## Installation & Quickstart
23
+
24
+ ### Python (PyPI)
25
+ ```bash
26
+ pip install termux-stt
27
+ ```
28
+ ```python
29
+ from termux_stt import create_engine
30
+
31
+ # 1. Initialize Whisper Engine with Vulkan GPU / CPU Hybrid Acceleration
32
+ engine = create_engine("whisper", model="small", lang="ko", threads=4, split_mode=True)
33
+
34
+ # 2. Transcribe Audio directly into Subtitles
35
+ result = engine.transcribe("samples/jfk_1min.wav")
36
+ print("Transcript:\n", result.text)
37
+ print("SRT Subtitles:\n", result.to_srt())
38
+
39
+ # 3. Multi-Speaker Neural Diarization (PyAnnote 3.0 + CAM++ 192d + TS-VAD)
40
+ hybrid = create_engine("hybrid", lang="ko", num_speakers=2)
41
+ diar_result = hybrid.diarize("samples/kor_영어로화자분리.wav")
42
+ for seg in diar_result.segments:
43
+ print(f"[{seg.speaker}] ({seg.start:.1f}s -> {seg.end:.1f}s): {seg.text}")
44
+
45
+ ```
46
+
47
+ ### Node.js / TypeScript (npm)
48
+ ```bash
49
+ npm install termux-stt
50
+ ```
51
+ ```typescript
52
+ const { createEngine } = require("termux-stt");
53
+
54
+ async function main() {
55
+ // 1. Initialize Whisper Engine
56
+ const engine = createEngine("whisper", { model: "tiny", lang: "ko", threads: 4 });
57
+
58
+ // 2. Transcribe Audio
59
+ const result = await engine.transcribe("samples/jfk_1min.wav");
60
+ console.log("Transcript:", result.text);
61
+ console.log("SRT Subtitles:\n", result.toSrt());
62
+
63
+ // 3. Neural Diarization via Hybrid Engine
64
+ const hybrid = createEngine("hybrid", { lang: "ko", numSpeakers: 2 });
65
+ const diarResult = await hybrid.diarize("samples/kor_영어로화자분리.wav");
66
+ for (const seg of diarResult.segments) {
67
+ console.log(`[${seg.speaker}] (${seg.start.toFixed(1)}s -> ${seg.end.toFixed(1)}s): ${seg.text}`);
68
+ }
69
+ }
70
+ main();
71
+
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Official Documentation & Benchmarks
77
+ - [Official Architecture & API Reference](https://uno-km.vercel.app/lib/stt/)
78
+ - [Ecosystem Metrics & Registry Stats](https://uno-km.vercel.app/foundation/metrics)
79
+ - [AMEVA Open-Source Foundation Portal](https://uno-km.vercel.app/foundation/index.html)
80
+
81
+ ---
82
+
83
+ ## License
84
+ Licensed under the Apache-2.0 License. Copyright (c) 2026 Eunho Kim ([@uno-km](https://github.com/uno-km)).
package/README.pypi.md CHANGED
@@ -1,44 +1,44 @@
1
- # Termux-STT (Python)
2
-
3
- [![PyPI](https://img.shields.io/pypi/v/termux-stt.svg?style=flat-square&color=0369a1)](https://pypi.org/project/termux-stt/)
4
- [![Python](https://img.shields.io/pypi/pyversions/termux-stt.svg?style=flat-square)](https://pypi.org/project/termux-stt/)
5
- [![License](https://img.shields.io/badge/License-Apache_2.0-004499.svg?style=flat-square)](https://github.com/uno-km/termux-stt)
6
-
7
- > Unified On-Device Speech-to-Text Utilizing Device Resources & Pure Python 128d X-Vector Speaker Diarization
8
-
9
- ## Installation
10
-
11
- ```bash
12
- pip install termux-stt
13
- ```
14
-
15
- ## Quickstart
16
-
17
- ```python
18
- from termux_stt import create_engine
19
-
20
- # 1. Initialize Engine with Hybrid GPU-Encoder / CPU-Decoder Acceleration
21
- engine = create_engine("whisper", model="small", lang="en", threads=4, split_mode=True)
22
-
23
- # 2. Transcribe Audio directly into Subtitles
24
- result = engine.transcribe("samples/jfk_1min.wav")
25
- print("Transcript:\n", result.text)
26
- print("SRT Subtitles:\n", result.to_srt())
27
-
28
- # 3. 2-Speaker Diarization without PyTorch
29
- hybrid = create_engine("hybrid", lang="en", num_speakers=2)
30
- diar_result = hybrid.diarize("samples/jfk_1min.wav")
31
- for seg in diar_result.segments:
32
- print(f"[{seg.speaker}] ({seg.start:.1f}s -> {seg.end:.1f}s): {seg.text}")
33
-
34
- ```
35
-
36
- ## Description
37
- Integrates Whisper.cpp, Vosk, and Sherpa-ONNX with a closed-form pure-Python 128-dimensional X-Vector clustering algorithm that operates in under 80MB RAM with zero cloud egress.
38
-
39
- ## Documentation
40
- - [Official Documentation & API Reference](https://uno-km.vercel.app/lib/stt/)
41
- - [GitHub Repository](https://github.com/uno-km/termux-stt)
42
-
43
- ## License
44
- Apache-2.0 License. Copyright (c) 2026 Eunho Kim (@uno-km).
1
+ # Termux-STT (Python)
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/termux-stt.svg?style=flat-square&color=0369a1)](https://pypi.org/project/termux-stt/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/termux-stt.svg?style=flat-square)](https://pypi.org/project/termux-stt/)
5
+ [![License](https://img.shields.io/badge/License-Apache_2.0-004499.svg?style=flat-square)](https://github.com/uno-km/termux-stt)
6
+
7
+ > Unified On-Device Speech-to-Text & Neural Multi-Speaker Diarization (PyAnnote 3.0 + CAM++ 192d + TS-VAD Overlap Resolver)
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install termux-stt
13
+ ```
14
+
15
+ ## Quickstart
16
+
17
+ ```python
18
+ from termux_stt import create_engine
19
+
20
+ # 1. Initialize Whisper Engine with Vulkan GPU / CPU Hybrid Acceleration
21
+ engine = create_engine("whisper", model="small", lang="ko", threads=4, split_mode=True)
22
+
23
+ # 2. Transcribe Audio directly into Subtitles
24
+ result = engine.transcribe("samples/jfk_1min.wav")
25
+ print("Transcript:\n", result.text)
26
+ print("SRT Subtitles:\n", result.to_srt())
27
+
28
+ # 3. Multi-Speaker Neural Diarization (PyAnnote 3.0 + CAM++ 192d + TS-VAD)
29
+ hybrid = create_engine("hybrid", lang="ko", num_speakers=2)
30
+ diar_result = hybrid.diarize("samples/kor_영어로화자분리.wav")
31
+ for seg in diar_result.segments:
32
+ print(f"[{seg.speaker}] ({seg.start:.1f}s -> {seg.end:.1f}s): {seg.text}")
33
+
34
+ ```
35
+
36
+ ## Description
37
+ Integrates Whisper.cpp (Native Vulkan GPU / NEON CPU) and Sherpa-ONNX with PyAnnote 3.0 neural segmentation, 3D-Speaker CAM++ 192-dim embeddings, and TS-VAD overlapped speech resolution with zero cloud egress.
38
+
39
+ ## Documentation
40
+ - [Official Documentation & API Reference](https://uno-km.vercel.app/lib/stt/)
41
+ - [GitHub Repository](https://github.com/uno-km/termux-stt)
42
+
43
+ ## License
44
+ Apache-2.0 License. Copyright (c) 2026 Eunho Kim (@uno-km).
package/bin/cli.js CHANGED
@@ -1,51 +1,51 @@
1
- #!/usr/bin/env node
2
- /**
3
- * AMEVA Standard Node.js CLI Runner for termux_stt.
4
- * Automatically resolves Python 3 environment and dispatches to python -m termux_stt.
5
- */
6
- const fs = require('fs');
7
- const { spawn, execSync } = require('child_process');
8
-
9
- function findPython() {
10
- if (process.env.PYTHON && fs.existsSync(process.env.PYTHON)) {
11
- return process.env.PYTHON;
12
- }
13
- const termuxBin = '/data/data/com.termux/files/usr/bin/python3';
14
- if (fs.existsSync(termuxBin)) {
15
- return termuxBin;
16
- }
17
- const termuxBinAlt = '/data/data/com.termux/files/usr/bin/python';
18
- if (fs.existsSync(termuxBinAlt)) {
19
- return termuxBinAlt;
20
- }
21
- const candidates = ['python3', 'python'];
22
- for (const cmd of candidates) {
23
- try {
24
- const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `command -v ${cmd}`;
25
- const res = execSync(checkCmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
26
- if (res) return cmd;
27
- } catch (_) {}
28
- }
29
- return 'python3';
30
- }
31
-
32
- const pythonBin = findPython();
33
- const args = ['-m', 'termux_stt', ...process.argv.slice(2)];
34
-
35
- const child = spawn(pythonBin, args, {
36
- stdio: 'inherit',
37
- env: process.env
38
- });
39
-
40
- child.on('error', (err) => {
41
- console.error(`[${'termux_stt'}] Failed to spawn python process (${pythonBin}):`, err.message);
42
- process.exit(1);
43
- });
44
-
45
- child.on('exit', (code, signal) => {
46
- if (signal) {
47
- process.kill(process.pid, signal);
48
- } else {
49
- process.exit(code || 0);
50
- }
51
- });
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AMEVA Standard Node.js CLI Runner for termux_stt.
4
+ * Automatically resolves Python 3 environment and dispatches to python -m termux_stt.
5
+ */
6
+ const fs = require('fs');
7
+ const { spawn, execSync } = require('child_process');
8
+
9
+ function findPython() {
10
+ if (process.env.PYTHON && fs.existsSync(process.env.PYTHON)) {
11
+ return process.env.PYTHON;
12
+ }
13
+ const termuxBin = '/data/data/com.termux/files/usr/bin/python3';
14
+ if (fs.existsSync(termuxBin)) {
15
+ return termuxBin;
16
+ }
17
+ const termuxBinAlt = '/data/data/com.termux/files/usr/bin/python';
18
+ if (fs.existsSync(termuxBinAlt)) {
19
+ return termuxBinAlt;
20
+ }
21
+ const candidates = ['python3', 'python'];
22
+ for (const cmd of candidates) {
23
+ try {
24
+ const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `command -v ${cmd}`;
25
+ const res = execSync(checkCmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
26
+ if (res) return cmd;
27
+ } catch (_) {}
28
+ }
29
+ return 'python3';
30
+ }
31
+
32
+ const pythonBin = findPython();
33
+ const args = ['-m', 'termux_stt', ...process.argv.slice(2)];
34
+
35
+ const child = spawn(pythonBin, args, {
36
+ stdio: 'inherit',
37
+ env: process.env
38
+ });
39
+
40
+ child.on('error', (err) => {
41
+ console.error(`[${'termux_stt'}] Failed to spawn python process (${pythonBin}):`, err.message);
42
+ process.exit(1);
43
+ });
44
+
45
+ child.on('exit', (code, signal) => {
46
+ if (signal) {
47
+ process.kill(process.pid, signal);
48
+ } else {
49
+ process.exit(code || 0);
50
+ }
51
+ });
package/bin/termux-stt.js CHANGED
@@ -1,51 +1,51 @@
1
- #!/usr/bin/env node
2
- /**
3
- * AMEVA Standard Node.js CLI Runner for termux_stt.
4
- * Automatically resolves Python 3 environment and dispatches to python -m termux_stt.
5
- */
6
- const fs = require('fs');
7
- const { spawn, execSync } = require('child_process');
8
-
9
- function findPython() {
10
- if (process.env.PYTHON && fs.existsSync(process.env.PYTHON)) {
11
- return process.env.PYTHON;
12
- }
13
- const termuxBin = '/data/data/com.termux/files/usr/bin/python3';
14
- if (fs.existsSync(termuxBin)) {
15
- return termuxBin;
16
- }
17
- const termuxBinAlt = '/data/data/com.termux/files/usr/bin/python';
18
- if (fs.existsSync(termuxBinAlt)) {
19
- return termuxBinAlt;
20
- }
21
- const candidates = ['python3', 'python'];
22
- for (const cmd of candidates) {
23
- try {
24
- const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `command -v ${cmd}`;
25
- const res = execSync(checkCmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
26
- if (res) return cmd;
27
- } catch (_) {}
28
- }
29
- return 'python3';
30
- }
31
-
32
- const pythonBin = findPython();
33
- const args = ['-m', 'termux_stt.platform.installer', ...process.argv.slice(2)];
34
-
35
- const child = spawn(pythonBin, args, {
36
- stdio: 'inherit',
37
- env: process.env
38
- });
39
-
40
- child.on('error', (err) => {
41
- console.error(`[${'termux_stt'}] Failed to spawn python process (${pythonBin}):`, err.message);
42
- process.exit(1);
43
- });
44
-
45
- child.on('exit', (code, signal) => {
46
- if (signal) {
47
- process.kill(process.pid, signal);
48
- } else {
49
- process.exit(code || 0);
50
- }
51
- });
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AMEVA Standard Node.js CLI Runner for termux_stt.
4
+ * Automatically resolves Python 3 environment and dispatches to python -m termux_stt.
5
+ */
6
+ const fs = require('fs');
7
+ const { spawn, execSync } = require('child_process');
8
+
9
+ function findPython() {
10
+ if (process.env.PYTHON && fs.existsSync(process.env.PYTHON)) {
11
+ return process.env.PYTHON;
12
+ }
13
+ const termuxBin = '/data/data/com.termux/files/usr/bin/python3';
14
+ if (fs.existsSync(termuxBin)) {
15
+ return termuxBin;
16
+ }
17
+ const termuxBinAlt = '/data/data/com.termux/files/usr/bin/python';
18
+ if (fs.existsSync(termuxBinAlt)) {
19
+ return termuxBinAlt;
20
+ }
21
+ const candidates = ['python3', 'python'];
22
+ for (const cmd of candidates) {
23
+ try {
24
+ const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `command -v ${cmd}`;
25
+ const res = execSync(checkCmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
26
+ if (res) return cmd;
27
+ } catch (_) {}
28
+ }
29
+ return 'python3';
30
+ }
31
+
32
+ const pythonBin = findPython();
33
+ const args = ['-m', 'termux_stt.platform.installer', ...process.argv.slice(2)];
34
+
35
+ const child = spawn(pythonBin, args, {
36
+ stdio: 'inherit',
37
+ env: process.env
38
+ });
39
+
40
+ child.on('error', (err) => {
41
+ console.error(`[${'termux_stt'}] Failed to spawn python process (${pythonBin}):`, err.message);
42
+ process.exit(1);
43
+ });
44
+
45
+ child.on('exit', (code, signal) => {
46
+ if (signal) {
47
+ process.kill(process.pid, signal);
48
+ } else {
49
+ process.exit(code || 0);
50
+ }
51
+ });
package/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export class WhisperEngine extends Engine {
45
45
  diarize(audioPath: string, numSpeakers?: number): Promise<TranscriptResult>;
46
46
  }
47
47
 
48
- export class VoskEngine extends Engine {
48
+ export class SherpaEngine extends Engine {
49
49
  transcribe(audioPath: string, options?: any): Promise<TranscriptResult>;
50
50
  diarize(audioPath: string, numSpeakers?: number): Promise<TranscriptResult>;
51
51
  }
@@ -56,8 +56,13 @@ export class HybridEngine extends Engine {
56
56
  }
57
57
 
58
58
  export function createEngine(
59
- engineName?: 'whisper' | 'vosk' | 'hybrid' | string,
59
+ engineName?: 'whisper' | 'sherpa' | 'hybrid' | string,
60
60
  options?: EngineOptions
61
61
  ): Engine;
62
62
 
63
- export function formatTime(seconds: number, separator?: string): string;
63
+ export class TermuxSTT {
64
+ engine: Engine;
65
+ constructor(options?: EngineOptions & { engine?: string });
66
+ transcribe(filePath: string, options?: any): Promise<TranscriptResult>;
67
+ diarize(filePath: string, options?: any): Promise<TranscriptResult>;
68
+ }
package/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
- * termux-stt Node.js entry point
2
+ * termux-stt Node.js entry point (v2.0.0)
3
3
  */
4
4
 
5
5
  const { Engine, TranscriptResult, Segment, formatTime } = require('./lib/engine');
6
6
  const { WhisperEngine } = require('./lib/whisper');
7
- const { VoskEngine } = require('./lib/vosk');
7
+ const { SherpaEngine } = require('./lib/sherpa');
8
8
  const { HybridEngine } = require('./lib/hybrid');
9
9
 
10
10
  function createEngine(engineName = 'whisper', options = {}) {
@@ -12,12 +12,14 @@ function createEngine(engineName = 'whisper', options = {}) {
12
12
  switch (name) {
13
13
  case 'whisper':
14
14
  return new WhisperEngine(options);
15
- case 'vosk':
16
- return new VoskEngine(options);
15
+ case 'sherpa':
16
+ return new SherpaEngine(options);
17
17
  case 'hybrid':
18
18
  return new HybridEngine(options);
19
+ case 'vosk':
20
+ throw new Error("Vosk has been deprecated and completely removed in v2.0.0. Please use 'sherpa' (SenseVoice) or 'whisper'.");
19
21
  default:
20
- throw new Error(`Unknown engine: ${engineName}. Available: whisper, vosk, hybrid`);
22
+ throw new Error(`Unknown engine: ${engineName}. Available: whisper, sherpa, hybrid`);
21
23
  }
22
24
  }
23
25
 
@@ -41,7 +43,7 @@ module.exports = {
41
43
  TranscriptResult,
42
44
  Segment,
43
45
  WhisperEngine,
44
- VoskEngine,
46
+ SherpaEngine,
45
47
  HybridEngine,
46
48
  formatTime
47
49
  };
package/lib/hybrid.js CHANGED
@@ -53,7 +53,7 @@ class HybridEngine extends Engine {
53
53
 
54
54
  getInfo() {
55
55
  return {
56
- name: 'Hybrid Vosk+Whisper (Node.js)',
56
+ name: 'Hybrid Neural Diarizer + Whisper (Node.js)',
57
57
  model: this.model,
58
58
  language: this.lang,
59
59
  numSpeakers: this.numSpeakers
package/lib/sherpa.js ADDED
@@ -0,0 +1,97 @@
1
+ /**
2
+ * SherpaEngine for Node.js - Non-Autoregressive SenseVoice STT & Neural Diarization
3
+ */
4
+
5
+ const { spawn } = require('child_process');
6
+ const { Engine, TranscriptResult, Segment } = require('./engine');
7
+
8
+ class SherpaEngine extends Engine {
9
+ constructor(config = {}) {
10
+ super(config);
11
+ this.model = config.model || 'sensevoice-small-int8';
12
+ this.lang = config.lang || 'ko';
13
+ this.threads = config.threads || 4;
14
+ }
15
+
16
+ async transcribe(audioPath, options = {}) {
17
+ return new Promise((resolve, reject) => {
18
+ const args = [
19
+ '-m', 'termux_stt.cli.main',
20
+ 'transcribe',
21
+ '--engine', 'sherpa',
22
+ '--model', this.model,
23
+ '--lang', this.lang,
24
+ '--format', 'json',
25
+ audioPath
26
+ ];
27
+
28
+ const proc = spawn('python', args, { env: process.env });
29
+ let stdout = '';
30
+ let stderr = '';
31
+
32
+ proc.stdout.on('data', (d) => { stdout += d.toString(); });
33
+ proc.stderr.on('data', (d) => { stderr += d.toString(); });
34
+
35
+ proc.on('close', (code) => {
36
+ if (code !== 0) {
37
+ return reject(new Error(`Sherpa transcription failed (code ${code}): ${stderr}`));
38
+ }
39
+ try {
40
+ const parsed = JSON.parse(stdout);
41
+ const segments = (parsed.segments || []).map(
42
+ s => new Segment(s.start, s.end, s.text, s.speaker, s.confidence)
43
+ );
44
+ resolve(new TranscriptResult(parsed.text, segments, parsed.language || this.lang, parsed.duration));
45
+ } catch (e) {
46
+ resolve(new TranscriptResult(stdout.trim(), [new Segment(0, 0, stdout.trim())], this.lang));
47
+ }
48
+ });
49
+ });
50
+ }
51
+
52
+ async diarize(audioPath, numSpeakers = 2) {
53
+ return new Promise((resolve, reject) => {
54
+ const args = [
55
+ '-m', 'termux_stt.cli.main',
56
+ 'diarize',
57
+ '--engine', 'sherpa',
58
+ '--speakers', String(numSpeakers),
59
+ '--format', 'json',
60
+ audioPath
61
+ ];
62
+
63
+ const proc = spawn('python', args, { env: process.env });
64
+ let stdout = '';
65
+ let stderr = '';
66
+
67
+ proc.stdout.on('data', (d) => { stdout += d.toString(); });
68
+ proc.stderr.on('data', (d) => { stderr += d.toString(); });
69
+
70
+ proc.on('close', (code) => {
71
+ if (code !== 0) {
72
+ return reject(new Error(`Sherpa diarization failed (code ${code}): ${stderr}`));
73
+ }
74
+ try {
75
+ const parsed = JSON.parse(stdout);
76
+ const segments = (parsed.segments || []).map(
77
+ s => new Segment(s.start, s.end, s.text, s.speaker, s.confidence)
78
+ );
79
+ resolve(new TranscriptResult(parsed.text, segments, parsed.language || this.lang, parsed.duration));
80
+ } catch (e) {
81
+ resolve(new TranscriptResult(stdout.trim(), [new Segment(0, 0, stdout.trim())], this.lang));
82
+ }
83
+ });
84
+ });
85
+ }
86
+
87
+ getInfo() {
88
+ return {
89
+ name: 'Sherpa-ONNX (Node.js)',
90
+ model: this.model,
91
+ language: this.lang,
92
+ threads: this.threads
93
+ };
94
+ }
95
+ }
96
+
97
+ module.exports = { SherpaEngine };
package/package.json CHANGED
@@ -1,87 +1,87 @@
1
- {
2
- "name": "termux-stt",
3
- "version": "1.4.0",
4
- "description": "On-device Speech-to-Text & speaker diarization framework utilizing device resources for Android Termux",
5
- "main": "index.js",
6
- "types": "index.d.ts",
7
- "bin": {
8
- "termux-stt": "bin/cli.js",
9
- "termux-stt-install": "bin/termux-stt.js"
10
- },
11
- "files": [
12
- "index.js",
13
- "index.d.ts",
14
- "lib",
15
- "bin",
16
- "README.md",
17
- "LICENSE"
18
- ],
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/uno-km/termux-stt.git"
22
- },
23
- "keywords": [
24
- "termux",
25
- "stt",
26
- "speech-to-text",
27
- "whisper",
28
- "whisper-cpp",
29
- "vosk",
30
- "sherpa-onnx",
31
- "diarization",
32
- "speaker-diarization",
33
- "voice-recognition",
34
- "audio-transcription",
35
- "on-device-ai",
36
- "edge-ai",
37
- "mobile-ai",
38
- "vulkan",
39
- "vulkan-compute",
40
- "gpu-acceleration",
41
- "real-time-factor",
42
- "low-latency",
43
- "arm64",
44
- "android",
45
- "snapdragon",
46
- "adreno",
47
- "exynos",
48
- "arm-mali",
49
- "zero-compilation",
50
- "vad",
51
- "voice-activity-detection",
52
- "silero-vad",
53
- "x-vector",
54
- "k-means",
55
- "clustering",
56
- "srt-export",
57
- "vtt-export",
58
- "rttm",
59
- "microphone-streaming",
60
- "headless-audio",
61
- "pulseaudio",
62
- "offline-speech",
63
- "privacy-first",
64
- "termux-aichain",
65
- "termux-tts",
66
- "termux-llamacpp",
67
- "termux-diffusion",
68
- "ameva-runtime",
69
- "ggml",
70
- "quantization",
71
- "bionic-libc",
72
- "autonomous-agents",
73
- "voice-assistant"
74
- ],
75
- "author": "uno-km (AMEVA Foundation) <dev@ameva.org>",
76
- "license": "MIT",
77
- "bugs": {
78
- "url": "https://github.com/uno-km/termux-stt/issues"
79
- },
80
- "homepage": "https://uno-km.github.io/termux-stt/",
81
- "dependencies": {
82
- "@ameva/runtime": ">=2.0.0"
83
- },
84
- "engines": {
85
- "node": ">=16.0.0"
86
- }
87
- }
1
+ {
2
+ "name": "termux-stt",
3
+ "version": "2.0.0",
4
+ "description": "On-device Speech-to-Text & neural speaker diarization framework for Android Termux (Whisper Vulkan GPU & Sherpa-ONNX)",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "bin": {
8
+ "termux-stt": "bin/cli.js",
9
+ "termux-stt-install": "bin/termux-stt.js"
10
+ },
11
+ "files": [
12
+ "index.js",
13
+ "index.d.ts",
14
+ "lib",
15
+ "bin",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/uno-km/termux-stt.git"
22
+ },
23
+ "keywords": [
24
+ "termux",
25
+ "stt",
26
+ "speech-to-text",
27
+ "whisper",
28
+ "whisper-cpp",
29
+ "vosk",
30
+ "sherpa-onnx",
31
+ "diarization",
32
+ "speaker-diarization",
33
+ "voice-recognition",
34
+ "audio-transcription",
35
+ "on-device-ai",
36
+ "edge-ai",
37
+ "mobile-ai",
38
+ "vulkan",
39
+ "vulkan-compute",
40
+ "gpu-acceleration",
41
+ "real-time-factor",
42
+ "low-latency",
43
+ "arm64",
44
+ "android",
45
+ "snapdragon",
46
+ "adreno",
47
+ "exynos",
48
+ "arm-mali",
49
+ "zero-compilation",
50
+ "vad",
51
+ "voice-activity-detection",
52
+ "silero-vad",
53
+ "x-vector",
54
+ "k-means",
55
+ "clustering",
56
+ "srt-export",
57
+ "vtt-export",
58
+ "rttm",
59
+ "microphone-streaming",
60
+ "headless-audio",
61
+ "pulseaudio",
62
+ "offline-speech",
63
+ "privacy-first",
64
+ "termux-aichain",
65
+ "termux-tts",
66
+ "termux-llamacpp",
67
+ "termux-diffusion",
68
+ "ameva-runtime",
69
+ "ggml",
70
+ "quantization",
71
+ "bionic-libc",
72
+ "autonomous-agents",
73
+ "voice-assistant"
74
+ ],
75
+ "author": "uno-km (AMEVA Foundation) <dev@ameva.org>",
76
+ "license": "MIT",
77
+ "bugs": {
78
+ "url": "https://github.com/uno-km/termux-stt/issues"
79
+ },
80
+ "homepage": "https://uno-km.github.io/termux-stt/",
81
+ "dependencies": {
82
+ "@ameva/runtime": ">=2.0.0"
83
+ },
84
+ "engines": {
85
+ "node": ">=16.0.0"
86
+ }
87
+ }
package/lib/vosk.js DELETED
@@ -1,60 +0,0 @@
1
- /**
2
- * VoskEngine for Node.js
3
- */
4
-
5
- const { spawn } = require('child_process');
6
- const { Engine, TranscriptResult, Segment } = require('./engine');
7
-
8
- class VoskEngine extends Engine {
9
- constructor(config = {}) {
10
- super(config);
11
- this.model = config.model || 'small-ko-0.22';
12
- this.lang = config.lang || 'ko';
13
- }
14
-
15
- async transcribe(audioPath, options = {}) {
16
- return new Promise((resolve, reject) => {
17
- const args = [
18
- '-m', 'termux_stt.cli.main',
19
- 'transcribe',
20
- '--engine', 'vosk',
21
- '--model', this.model,
22
- '--lang', this.lang,
23
- '--format', 'json',
24
- audioPath
25
- ];
26
-
27
- const proc = spawn('python', args, { env: process.env });
28
- let stdout = '';
29
- let stderr = '';
30
-
31
- proc.stdout.on('data', (d) => { stdout += d.toString(); });
32
- proc.stderr.on('data', (d) => { stderr += d.toString(); });
33
-
34
- proc.on('close', (code) => {
35
- if (code !== 0) {
36
- return reject(new Error(`Vosk transcription failed (code ${code}): ${stderr}`));
37
- }
38
- try {
39
- const parsed = JSON.parse(stdout);
40
- const segments = (parsed.segments || []).map(
41
- s => new Segment(s.start, s.end, s.text, s.speaker, s.confidence)
42
- );
43
- resolve(new TranscriptResult(parsed.text, segments, parsed.language || this.lang, parsed.duration));
44
- } catch (e) {
45
- resolve(new TranscriptResult(stdout.trim(), [new Segment(0, 0, stdout.trim())], this.lang));
46
- }
47
- });
48
- });
49
- }
50
-
51
- getInfo() {
52
- return {
53
- name: 'Vosk (Node.js)',
54
- model: this.model,
55
- language: this.lang
56
- };
57
- }
58
- }
59
-
60
- module.exports = { VoskEngine };