Commit ·
15ccbbc
1
Parent(s): 9479558
Update documentation
Browse files- README.md +131 -59
- app.py +9 -9
- scripts/test_llm_brick.py +1 -1
- signspeak/__init__.py +1 -2
- signspeak/pipeline.py +4 -4
README.md
CHANGED
|
@@ -1,47 +1,114 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 🗣️
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
python_version: "3.12"
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
| 12 |
-
|
|
|
|
| 13 |
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
## Pipeline
|
| 17 |
|
| 18 |
```text
|
| 19 |
-
Video upload
|
| 20 |
-
-> ASL
|
| 21 |
-
-> MediaPipe landmarks,
|
| 22 |
-
->
|
| 23 |
-
-> gloss sequence
|
| 24 |
-
-> DeepFace emotion aggregation,
|
| 25 |
-
-> llama.cpp subtitle
|
| 26 |
-> Qwen3-TTS audio
|
| 27 |
```
|
| 28 |
|
| 29 |
-
|
| 30 |
the whole interface at startup.
|
| 31 |
|
| 32 |
-
The demo screen is intentionally
|
| 33 |
|
| 34 |
```text
|
| 35 |
-
1 Analyze ASL -> debug overlay + intent JSON
|
| 36 |
-
2 Generate subtitle -> llama.cpp output
|
| 37 |
-
3 Generate speech -> Qwen3-TTS audio
|
| 38 |
```
|
| 39 |
|
| 40 |
-
When
|
| 41 |
-
ASL words.
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
Run unit tests:
|
| 47 |
|
|
@@ -58,16 +125,17 @@ python3 scripts/test_tts_brick.py
|
|
| 58 |
python3 scripts/test_full_pipeline.py
|
| 59 |
```
|
| 60 |
|
| 61 |
-
`scripts/test_asl_brick.py` creates a tiny temporary
|
| 62 |
-
It also writes a debug overlay video path. To test the transparent
|
|
|
|
| 63 |
|
| 64 |
```bash
|
| 65 |
python3 scripts/test_asl_brick.py --gloss-override "I LOVE YOU"
|
| 66 |
```
|
| 67 |
|
| 68 |
-
## ASL
|
| 69 |
|
| 70 |
-
The ASL classifier assets
|
| 71 |
|
| 72 |
```text
|
| 73 |
data/models/asl/model.tflite
|
|
@@ -75,21 +143,21 @@ data/models/asl/train.csv
|
|
| 75 |
data/models/asl/sign_to_prediction_index_map.json
|
| 76 |
```
|
| 77 |
|
| 78 |
-
They come from
|
|
|
|
| 79 |
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
``
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
|
| 89 |
-
|
| 90 |
-
extracted once, then the ASL model runs over sliding windows. Accepted window predictions are
|
| 91 |
-
collapsed into an ordered gloss sequence before llama.cpp rewrites them as natural speech. Tune it
|
| 92 |
-
with:
|
| 93 |
|
| 94 |
```text
|
| 95 |
ASL_UPLOAD_TARGET_FPS=12
|
|
@@ -99,15 +167,17 @@ ASL_SEQUENCE_STRIDE=15
|
|
| 99 |
ASL_CONFIDENCE_THRESHOLD=0.70
|
| 100 |
```
|
| 101 |
|
| 102 |
-
This is still not full continuous ASL translation, but it lets recorded phrase
|
| 103 |
-
`hello where water`-style gloss sequences instead of one global
|
|
|
|
| 104 |
|
| 105 |
-
An experimental WLASL2000 I3D backend is also available for broader vocabulary
|
| 106 |
-
`raghuhasan/asl2000-i3d` from Hugging Face, downloads the I3D
|
| 107 |
-
falls back to the TFLite detector when
|
|
|
|
| 108 |
|
| 109 |
```text
|
| 110 |
-
ASL_DETECTOR_BACKEND=auto # default:
|
| 111 |
ASL_DETECTOR_BACKEND=tflite # lightweight TFLite-only backend
|
| 112 |
ASL_DETECTOR_BACKEND=wlasl_i3d # WLASL2000 I3D only
|
| 113 |
WLASL_I3D_CONFIDENCE_THRESHOLD=0.20
|
|
@@ -116,15 +186,16 @@ WLASL_I3D_SEQUENCE_STRIDE=32
|
|
| 116 |
WLASL_I3D_FRAME_SIZE=224
|
| 117 |
```
|
| 118 |
|
| 119 |
-
The WLASL backend is heavier and more experimental.
|
| 120 |
-
32.48% top-1, 57.31% top-5, and 66.31% top-10 accuracy, so
|
| 121 |
-
segment diagnostics instead of hiding
|
|
|
|
| 122 |
|
| 123 |
-
Live camera debug prioritizes speed over long temporal batching. It starts
|
| 124 |
-
`LIVE_ASL_MIN_FRAMES=4`, keeps a rolling buffer of
|
| 125 |
-
|
| 126 |
-
`
|
| 127 |
-
|
| 128 |
|
| 129 |
Good first signs to test because they are in the model vocabulary:
|
| 130 |
|
|
@@ -132,7 +203,7 @@ Good first signs to test because they are in the model vocabulary:
|
|
| 132 |
hello, where, who, why, yes, no, thankyou, please, water, happy, sad
|
| 133 |
```
|
| 134 |
|
| 135 |
-
Reference clips
|
| 136 |
|
| 137 |
```text
|
| 138 |
hello https://media.giphy.com/media/3o7TKNKOfKlIhbD3gY/giphy.gif
|
|
@@ -146,20 +217,21 @@ please https://lifeprint.com/asl101/gifs-animated/pleasecloseup.gif
|
|
| 146 |
water https://lifeprint.com/asl101/gifs/w/water-2.gif
|
| 147 |
```
|
| 148 |
|
| 149 |
-
## GPU
|
| 150 |
|
| 151 |
-
`flash-attn` is only useful on a CUDA GPU Space with compatible PyTorch/CUDA
|
| 152 |
-
Keep the default `requirements.txt` for CPU Spaces. If the Space is
|
| 153 |
-
GPU runtime, install the GPU dependency set instead:
|
| 154 |
|
| 155 |
```bash
|
| 156 |
pip install -r requirements-gpu.txt --no-build-isolation
|
| 157 |
```
|
| 158 |
|
| 159 |
-
## Full ASL
|
| 160 |
|
| 161 |
-
The default requirements keep the Space build lighter. For a full local
|
| 162 |
-
MediaPipe landmarks and DeepFace emotion detection,
|
|
|
|
| 163 |
|
| 164 |
```bash
|
| 165 |
pip install -r requirements-asl-full.txt
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Sign2Voice
|
| 3 |
emoji: 🗣️
|
| 4 |
+
colorFrom: green
|
| 5 |
+
colorTo: yellow
|
| 6 |
sdk: gradio
|
| 7 |
python_version: "3.12"
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
| 12 |
+
A local-first AI stack that translates sign language, intent, and expression
|
| 13 |
+
into natural speech.
|
| 14 |
|
| 15 |
+
Sign2Voice is a Gradio demo built for the Hugging Face Build Small Hackathon.
|
| 16 |
+
It takes an uploaded or webcam ASL clip, extracts sign candidates and facial
|
| 17 |
+
expression signals, converts the result into a compact intent JSON, then speaks
|
| 18 |
+
the sentence with a local small-model voice stack.
|
| 19 |
+
|
| 20 |
+
## Scope Note
|
| 21 |
+
|
| 22 |
+
We would have loved to push Sign2Voice further toward open-ended ASL
|
| 23 |
+
conversation during the hackathon. The main constraint was not the app shell or
|
| 24 |
+
the voice stack; it was data. Public ASL resources are still uneven for this
|
| 25 |
+
task: many usable datasets focus on isolated signs, dictionary retrieval, or
|
| 26 |
+
fingerspelling, while fluent ASL needs signer diversity, real-world lighting and
|
| 27 |
+
camera angles, temporal boundaries, facial grammar, body movement, and careful
|
| 28 |
+
expert annotation.
|
| 29 |
+
|
| 30 |
+
That is why this submission is intentionally evidence-first. It exposes top sign
|
| 31 |
+
candidates, confidence thresholds, segment diagnostics, and emotion metadata
|
| 32 |
+
instead of pretending that a small hackathon model can solve full ASL
|
| 33 |
+
translation end to end. Microsoft Research describes sign-language modeling as
|
| 34 |
+
being far behind spoken-language modeling largely because of a lack of
|
| 35 |
+
appropriate training data, and recent SLR survey work calls data acquisition and
|
| 36 |
+
annotation the main bottleneck for systems that work on fluent signing.
|
| 37 |
+
|
| 38 |
+
References:
|
| 39 |
+
|
| 40 |
+
- [ASL Citizen, Microsoft Research](https://www.microsoft.com/en-us/research/project/asl-citizen/)
|
| 41 |
+
- [Trends and Challenges for Sign Language Recognition with Machine Learning, ESANN 2023](https://www.esann.org/sites/default/files/proceedings/2023/ES2023-7.pdf)
|
| 42 |
+
|
| 43 |
+
## Hackathon Fit
|
| 44 |
+
|
| 45 |
+
The project is aimed at the Backyard AI track: a practical communication tool
|
| 46 |
+
for people who need fast sign-to-speech support without sending every clip to a
|
| 47 |
+
cloud API.
|
| 48 |
+
|
| 49 |
+
Build Small constraints covered by this repo:
|
| 50 |
+
|
| 51 |
+
- Gradio app, ready for a Hugging Face Space.
|
| 52 |
+
- Small-model stack under the 32B parameter limit.
|
| 53 |
+
- Local-first runtime: ASL detection, llama.cpp text generation, and Qwen3-TTS
|
| 54 |
+
speech generation run in the app process.
|
| 55 |
+
- Step-by-step demo flow that shows intermediate evidence instead of hiding
|
| 56 |
+
uncertainty.
|
| 57 |
+
|
| 58 |
+
Badges that fit this build:
|
| 59 |
+
|
| 60 |
+
- Off the Grid / Local-first: no cloud inference API is required at runtime.
|
| 61 |
+
- Llama Champion: the intent-to-speech text step uses `llama.cpp`.
|
| 62 |
+
- Off-Brand / Custom UI: the Space uses custom Gradio styling.
|
| 63 |
+
- Field Notes: claim this only after publishing the build write-up.
|
| 64 |
+
|
| 65 |
+
Badges not claimed:
|
| 66 |
+
|
| 67 |
+
- Well-Tuned: this repo uses published models; it does not publish a new
|
| 68 |
+
fine-tuned model.
|
| 69 |
+
- Sharing is Caring: no public agent trace is included yet.
|
| 70 |
|
| 71 |
## Pipeline
|
| 72 |
|
| 73 |
```text
|
| 74 |
+
Video upload or camera capture
|
| 75 |
+
-> Sequential ASL frame sampling
|
| 76 |
+
-> MediaPipe landmarks, when installed
|
| 77 |
+
-> WLASL2000 I3D or TFLite ASL classifier
|
| 78 |
+
-> Ordered gloss sequence with confidence diagnostics
|
| 79 |
+
-> DeepFace emotion aggregation, when installed
|
| 80 |
+
-> llama.cpp subtitle and voice instruction
|
| 81 |
-> Qwen3-TTS audio
|
| 82 |
```
|
| 83 |
|
| 84 |
+
Each brick can fail independently and return diagnostics instead of blocking
|
| 85 |
the whole interface at startup.
|
| 86 |
|
| 87 |
+
The demo screen is intentionally staged:
|
| 88 |
|
| 89 |
```text
|
| 90 |
+
1. Analyze ASL -> debug overlay + intent JSON
|
| 91 |
+
2. Generate subtitle -> llama.cpp output
|
| 92 |
+
3. Generate speech -> Qwen3-TTS audio
|
| 93 |
```
|
| 94 |
|
| 95 |
+
When no ASL classifier is available, Sign2Voice reports `model_missing` and
|
| 96 |
+
does not invent ASL words. The manual gloss override is empty by default and
|
| 97 |
+
lives under advanced debug controls for downstream LLM/TTS testing only.
|
| 98 |
+
|
| 99 |
+
## Run Locally
|
| 100 |
+
|
| 101 |
+
Install the default CPU-friendly dependency set:
|
| 102 |
+
|
| 103 |
+
```bash
|
| 104 |
+
pip install -r requirements.txt
|
| 105 |
+
```
|
| 106 |
|
| 107 |
+
Start the Gradio app:
|
| 108 |
+
|
| 109 |
+
```bash
|
| 110 |
+
python3 app.py
|
| 111 |
+
```
|
| 112 |
|
| 113 |
Run unit tests:
|
| 114 |
|
|
|
|
| 125 |
python3 scripts/test_full_pipeline.py
|
| 126 |
```
|
| 127 |
|
| 128 |
+
`scripts/test_asl_brick.py` creates a tiny temporary clip when no video path is
|
| 129 |
+
supplied. It also writes a debug overlay video path. To test the transparent
|
| 130 |
+
fallback:
|
| 131 |
|
| 132 |
```bash
|
| 133 |
python3 scripts/test_asl_brick.py --gloss-override "I LOVE YOU"
|
| 134 |
```
|
| 135 |
|
| 136 |
+
## ASL Model Files
|
| 137 |
|
| 138 |
+
The ASL classifier assets live under:
|
| 139 |
|
| 140 |
```text
|
| 141 |
data/models/asl/model.tflite
|
|
|
|
| 143 |
data/models/asl/sign_to_prediction_index_map.json
|
| 144 |
```
|
| 145 |
|
| 146 |
+
They come from
|
| 147 |
+
[jamesjbustos/sign-language-recognition](https://github.com/jamesjbustos/sign-language-recognition).
|
| 148 |
|
| 149 |
+
Without these files, the ASL brick still samples frames and emits
|
| 150 |
+
`model_missing` diagnostics. The TFLite model recognizes the isolated signs in
|
| 151 |
+
`sign_to_prediction_index_map.json`; it is not a full sentence or fingerspelling
|
| 152 |
+
recognizer. Predictions below `ASL_CONFIDENCE_THRESHOLD`, defaulting to `0.70`,
|
| 153 |
+
are reported as `low_confidence` and are not forwarded as detected glosses.
|
| 154 |
|
| 155 |
+
Uploaded videos use a phrase-prototype mode: frames are read in temporal order,
|
| 156 |
+
landmarks are extracted once, and the ASL model runs over sliding windows.
|
| 157 |
+
Accepted window predictions are collapsed into an ordered gloss sequence before
|
| 158 |
+
`llama.cpp` rewrites them as natural speech.
|
| 159 |
|
| 160 |
+
Tune it with:
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
```text
|
| 163 |
ASL_UPLOAD_TARGET_FPS=12
|
|
|
|
| 167 |
ASL_CONFIDENCE_THRESHOLD=0.70
|
| 168 |
```
|
| 169 |
|
| 170 |
+
This is still not full continuous ASL translation, but it lets recorded phrase
|
| 171 |
+
clips become `hello where water`-style gloss sequences instead of one global
|
| 172 |
+
class.
|
| 173 |
|
| 174 |
+
An experimental WLASL2000 I3D backend is also available for broader vocabulary
|
| 175 |
+
coverage. It uses `raghuhasan/asl2000-i3d` from Hugging Face, downloads the I3D
|
| 176 |
+
architecture helper if needed, and falls back to the TFLite detector when
|
| 177 |
+
`ASL_DETECTOR_BACKEND=auto` cannot initialize it.
|
| 178 |
|
| 179 |
```text
|
| 180 |
+
ASL_DETECTOR_BACKEND=auto # default: WLASL2000, then TFLite
|
| 181 |
ASL_DETECTOR_BACKEND=tflite # lightweight TFLite-only backend
|
| 182 |
ASL_DETECTOR_BACKEND=wlasl_i3d # WLASL2000 I3D only
|
| 183 |
WLASL_I3D_CONFIDENCE_THRESHOLD=0.20
|
|
|
|
| 186 |
WLASL_I3D_FRAME_SIZE=224
|
| 187 |
```
|
| 188 |
|
| 189 |
+
The WLASL backend is heavier and more experimental. Its model card reports
|
| 190 |
+
2,000 classes with 32.48% top-1, 57.31% top-5, and 66.31% top-10 accuracy, so
|
| 191 |
+
the UI exposes top candidates and segment diagnostics instead of hiding
|
| 192 |
+
uncertainty.
|
| 193 |
|
| 194 |
+
Live camera debug prioritizes speed over long temporal batching. It starts
|
| 195 |
+
predicting after `LIVE_ASL_MIN_FRAMES=4`, keeps a rolling buffer of
|
| 196 |
+
`LIVE_ASL_MAX_FRAMES=12`, and runs ASL prediction every
|
| 197 |
+
`LIVE_ASL_PREDICT_EVERY=1` frame. DeepFace emotion is heavier, so it runs every
|
| 198 |
+
`LIVE_EMOTION_EVERY=45` frames by default.
|
| 199 |
|
| 200 |
Good first signs to test because they are in the model vocabulary:
|
| 201 |
|
|
|
|
| 203 |
hello, where, who, why, yes, no, thankyou, please, water, happy, sad
|
| 204 |
```
|
| 205 |
|
| 206 |
+
Reference clips and GIFs from the upstream demo list:
|
| 207 |
|
| 208 |
```text
|
| 209 |
hello https://media.giphy.com/media/3o7TKNKOfKlIhbD3gY/giphy.gif
|
|
|
|
| 217 |
water https://lifeprint.com/asl101/gifs/w/water-2.gif
|
| 218 |
```
|
| 219 |
|
| 220 |
+
## GPU Dependencies
|
| 221 |
|
| 222 |
+
`flash-attn` is only useful on a CUDA GPU Space with compatible PyTorch/CUDA
|
| 223 |
+
versions. Keep the default `requirements.txt` for CPU Spaces. If the Space is
|
| 224 |
+
moved to a compatible GPU runtime, install the GPU dependency set instead:
|
| 225 |
|
| 226 |
```bash
|
| 227 |
pip install -r requirements-gpu.txt --no-build-isolation
|
| 228 |
```
|
| 229 |
|
| 230 |
+
## Full ASL Dependencies
|
| 231 |
|
| 232 |
+
The default requirements keep the Space build lighter. For a full local
|
| 233 |
+
ASL/emotion runtime with MediaPipe landmarks and DeepFace emotion detection,
|
| 234 |
+
install:
|
| 235 |
|
| 236 |
```bash
|
| 237 |
pip install -r requirements-asl-full.txt
|
app.py
CHANGED
|
@@ -71,34 +71,34 @@ def build_video_input(label: str) -> gr.Video:
|
|
| 71 |
)
|
| 72 |
|
| 73 |
|
| 74 |
-
with gr.Blocks(title="
|
| 75 |
gr.HTML(
|
| 76 |
"""
|
| 77 |
<main id="hero">
|
| 78 |
<div class="brand-lockup">
|
| 79 |
<span class="brand-mark" aria-hidden="true"></span>
|
| 80 |
<div>
|
| 81 |
-
<p class="eyebrow">Local
|
| 82 |
-
<h1>
|
| 83 |
</div>
|
| 84 |
</div>
|
| 85 |
<div class="hero-grid">
|
| 86 |
<div>
|
| 87 |
<p class="hero-copy">
|
| 88 |
-
Translate camera or uploaded
|
| 89 |
-
|
| 90 |
</p>
|
| 91 |
<div class="pipeline-rail" aria-label="Pipeline stages">
|
| 92 |
<span>Capture</span>
|
| 93 |
-
<span>
|
| 94 |
<span>Intent</span>
|
| 95 |
<span>Voice</span>
|
| 96 |
</div>
|
| 97 |
</div>
|
| 98 |
<div class="system-strip" aria-label="System capabilities">
|
| 99 |
<span>Camera ready</span>
|
| 100 |
-
<span>
|
| 101 |
-
<span>Expressive
|
| 102 |
</div>
|
| 103 |
</div>
|
| 104 |
</main>
|
|
@@ -223,7 +223,7 @@ with gr.Blocks(title="SignSpeak Local") as demo:
|
|
| 223 |
gr.HTML(
|
| 224 |
"""
|
| 225 |
<p class="footer-note">
|
| 226 |
-
|
| 227 |
</p>
|
| 228 |
"""
|
| 229 |
)
|
|
|
|
| 71 |
)
|
| 72 |
|
| 73 |
|
| 74 |
+
with gr.Blocks(title="Sign2Voice") as demo:
|
| 75 |
gr.HTML(
|
| 76 |
"""
|
| 77 |
<main id="hero">
|
| 78 |
<div class="brand-lockup">
|
| 79 |
<span class="brand-mark" aria-hidden="true"></span>
|
| 80 |
<div>
|
| 81 |
+
<p class="eyebrow">Local-first sign-to-speech console</p>
|
| 82 |
+
<h1>Sign2Voice</h1>
|
| 83 |
</div>
|
| 84 |
</div>
|
| 85 |
<div class="hero-grid">
|
| 86 |
<div>
|
| 87 |
<p class="hero-copy">
|
| 88 |
+
Translate camera or uploaded signing clips into natural speech with
|
| 89 |
+
visible intent, expression, and confidence diagnostics.
|
| 90 |
</p>
|
| 91 |
<div class="pipeline-rail" aria-label="Pipeline stages">
|
| 92 |
<span>Capture</span>
|
| 93 |
+
<span>Signs</span>
|
| 94 |
<span>Intent</span>
|
| 95 |
<span>Voice</span>
|
| 96 |
</div>
|
| 97 |
</div>
|
| 98 |
<div class="system-strip" aria-label="System capabilities">
|
| 99 |
<span>Camera ready</span>
|
| 100 |
+
<span>llama.cpp local</span>
|
| 101 |
+
<span>Expressive voice</span>
|
| 102 |
</div>
|
| 103 |
</div>
|
| 104 |
</main>
|
|
|
|
| 223 |
gr.HTML(
|
| 224 |
"""
|
| 225 |
<p class="footer-note">
|
| 226 |
+
Build Small badges targeted: Off the Grid, Llama Champion, Off-Brand.
|
| 227 |
</p>
|
| 228 |
"""
|
| 229 |
)
|
scripts/test_llm_brick.py
CHANGED
|
@@ -11,7 +11,7 @@ from signspeak.pipeline import DEFAULT_INTENT, json_text
|
|
| 11 |
|
| 12 |
def main() -> None:
|
| 13 |
parser = argparse.ArgumentParser(description="Run only the llama.cpp intent-to-text brick.")
|
| 14 |
-
parser.add_argument("--intent", help="Path to an intent JSON file. Uses
|
| 15 |
args = parser.parse_args()
|
| 16 |
|
| 17 |
intent_json = Path(args.intent).read_text(encoding="utf-8") if args.intent else json_text(DEFAULT_INTENT)
|
|
|
|
| 11 |
|
| 12 |
def main() -> None:
|
| 13 |
parser = argparse.ArgumentParser(description="Run only the llama.cpp intent-to-text brick.")
|
| 14 |
+
parser.add_argument("--intent", help="Path to an intent JSON file. Uses the sample intent if omitted.")
|
| 15 |
args = parser.parse_args()
|
| 16 |
|
| 17 |
intent_json = Path(args.intent).read_text(encoding="utf-8") if args.intent else json_text(DEFAULT_INTENT)
|
signspeak/__init__.py
CHANGED
|
@@ -1,2 +1 @@
|
|
| 1 |
-
"""
|
| 2 |
-
|
|
|
|
| 1 |
+
"""Sign2Voice local sign-to-speech pipeline package."""
|
|
|
signspeak/pipeline.py
CHANGED
|
@@ -19,7 +19,7 @@ DEFAULT_INTENT = {
|
|
| 19 |
"confidence": 0.83,
|
| 20 |
},
|
| 21 |
"communication_intent": "friendly_greeting",
|
| 22 |
-
"pipeline_stage": "
|
| 23 |
}
|
| 24 |
|
| 25 |
DEFAULT_VIDEO_PATH = Path(__file__).resolve().parents[1] / "data" / "examples" / "videoplayback.mp4"
|
|
@@ -52,7 +52,7 @@ def apply_gloss_override(result: dict[str, Any], gloss_override: str | None) ->
|
|
| 52 |
asl["top_prediction"] = " ".join(glosses)
|
| 53 |
asl["status"] = f"{asl.get('status', 'unknown')}_with_manual_override"
|
| 54 |
intent["detected_glosses"] = glosses
|
| 55 |
-
intent["communication_intent"] = "
|
| 56 |
intent.setdefault("diagnostics", {})["manual_gloss_override"] = True
|
| 57 |
intent["diagnostics"]["override_reason"] = "ASL classifier is missing or uncertain; user supplied visible glosses."
|
| 58 |
return result
|
|
@@ -88,7 +88,7 @@ def create_synthetic_demo_video() -> Path:
|
|
| 88 |
except Exception as exc:
|
| 89 |
raise RuntimeError("OpenCV is required to create the fallback demo video.") from exc
|
| 90 |
|
| 91 |
-
output_path = Path(tempfile.gettempdir()) / "
|
| 92 |
if output_path.exists():
|
| 93 |
return output_path
|
| 94 |
|
|
@@ -111,7 +111,7 @@ def create_synthetic_demo_video() -> Path:
|
|
| 111 |
cv2.circle(frame, (width - center_x, 144), 18, (129, 140, 248), -1)
|
| 112 |
cv2.putText(
|
| 113 |
frame,
|
| 114 |
-
"
|
| 115 |
(36, 214),
|
| 116 |
cv2.FONT_HERSHEY_SIMPLEX,
|
| 117 |
0.62,
|
|
|
|
| 19 |
"confidence": 0.83,
|
| 20 |
},
|
| 21 |
"communication_intent": "friendly_greeting",
|
| 22 |
+
"pipeline_stage": "sample_asl_intent_for_llama_cpp_check",
|
| 23 |
}
|
| 24 |
|
| 25 |
DEFAULT_VIDEO_PATH = Path(__file__).resolve().parents[1] / "data" / "examples" / "videoplayback.mp4"
|
|
|
|
| 52 |
asl["top_prediction"] = " ".join(glosses)
|
| 53 |
asl["status"] = f"{asl.get('status', 'unknown')}_with_manual_override"
|
| 54 |
intent["detected_glosses"] = glosses
|
| 55 |
+
intent["communication_intent"] = "manual_gloss_override_for_pipeline_check"
|
| 56 |
intent.setdefault("diagnostics", {})["manual_gloss_override"] = True
|
| 57 |
intent["diagnostics"]["override_reason"] = "ASL classifier is missing or uncertain; user supplied visible glosses."
|
| 58 |
return result
|
|
|
|
| 88 |
except Exception as exc:
|
| 89 |
raise RuntimeError("OpenCV is required to create the fallback demo video.") from exc
|
| 90 |
|
| 91 |
+
output_path = Path(tempfile.gettempdir()) / "sign2voice_demo_input.mp4"
|
| 92 |
if output_path.exists():
|
| 93 |
return output_path
|
| 94 |
|
|
|
|
| 111 |
cv2.circle(frame, (width - center_x, 144), 18, (129, 140, 248), -1)
|
| 112 |
cv2.putText(
|
| 113 |
frame,
|
| 114 |
+
"Sign2Voice demo",
|
| 115 |
(36, 214),
|
| 116 |
cv2.FONT_HERSHEY_SIMPLEX,
|
| 117 |
0.62,
|