Spaces:
Running on Zero
Running on Zero
Catch weak stop signals near sentence end
Browse files- README.md +2 -2
- app.py +4 -4
- tests/test_production.py +22 -8
README.md
CHANGED
|
@@ -38,7 +38,7 @@ Demo 預設採用目前通過長文穩定性評估的推論設定:
|
|
| 38 |
| Target pace | 4.0 speech units/sec |
|
| 39 |
| Generation safety pace | 5.2 CJK / 4.6 ASCII-mixed units/sec + 1 latent step |
|
| 40 |
| Short-text guidance | minimum CFG 3.0 below 6 speech units |
|
| 41 |
-
| Stop policy | 0.50 → 0.
|
| 42 |
| Endpoint cue | append terminal punctuation for model input when missing, except very short text |
|
| 43 |
| Hard stop | native-pace target steps, independent of playback pace |
|
| 44 |
| Pace correction | pitch-preserving stretch after completion; onset split only at punctuation |
|
|
@@ -54,7 +54,7 @@ Demo 預設採用目前通過長文穩定性評估的推論設定:
|
|
| 54 |
|
| 55 |
自然 stop 在目前 checkpoint 上仍可能過快或錯過句尾。Demo 不再用播放目標語速決定生成長度;
|
| 56 |
模型使用原生語速的安全上限,完成後才做保音高語速校正。缺少句末標點時只在模型輸入補上句號,
|
| 57 |
-
少於 6 個 speech units 的短句會使用最低 CFG 3.0
|
| 58 |
首段不會在無標點處硬切。進階參數可供研究比較,但 release
|
| 59 |
profile 是 CFG 2.0、NFE 10、後處理語速 1.0。
|
| 60 |
|
|
|
|
| 38 |
| Target pace | 4.0 speech units/sec |
|
| 39 |
| Generation safety pace | 5.2 CJK / 4.6 ASCII-mixed units/sec + 1 latent step |
|
| 40 |
| Short-text guidance | minimum CFG 3.0 below 6 speech units |
|
| 41 |
+
| Stop policy | 0.50 → 0.05 from 75% to 95% predicted progress, 1 hit |
|
| 42 |
| Endpoint cue | append terminal punctuation for model input when missing, except very short text |
|
| 43 |
| Hard stop | native-pace target steps, independent of playback pace |
|
| 44 |
| Pace correction | pitch-preserving stretch after completion; onset split only at punctuation |
|
|
|
|
| 54 |
|
| 55 |
自然 stop 在目前 checkpoint 上仍可能過快或錯過句尾。Demo 不再用播放目標語速決定生成長度;
|
| 56 |
模型使用原生語速的安全上限,完成後才做保音高語速校正。缺少句末標點時只在模型輸入補上句號,
|
| 57 |
+
少於 6 個 speech units 的短句會使用最低 CFG 3.0;stop threshold 只在預估進度 75% 後逐步降低,並於 95% 進度降至 0.05,以捕捉句末弱 stop 訊號而不影響前段內容。
|
| 58 |
首段不會在無標點處硬切。進階參數可供研究比較,但 release
|
| 59 |
profile 是 CFG 2.0、NFE 10、後處理語速 1.0。
|
| 60 |
|
app.py
CHANGED
|
@@ -66,9 +66,9 @@ CROSSFADE_MS = 80.0
|
|
| 66 |
CHUNK_EDGE_FADE_MS = 80.0
|
| 67 |
CHUNK_RMS_MATCH_DB = 4.0
|
| 68 |
STOP_THRESHOLD = 0.50
|
| 69 |
-
STOP_LATE_THRESHOLD = 0.
|
| 70 |
-
STOP_LATE_START_RATIO = 0.
|
| 71 |
-
STOP_LATE_FULL_RATIO = 0.
|
| 72 |
STOP_CONSECUTIVE = 1
|
| 73 |
HARD_STOP_MARGIN_STEPS = 1
|
| 74 |
MIN_PACE_SPEED = 0.80
|
|
@@ -377,7 +377,7 @@ HEADER = f"""
|
|
| 377 |
台灣華語與中英混合文字轉語音。模型版本:`{CHECKPOINT}`。
|
| 378 |
|
| 379 |
目前預設採用穩定推論設定:`CFG 2.0`(極短句最低 `3.0`)、`NFE 10`、目標語速 `4.0 字/秒`、
|
| 380 |
-
生成上限依模型原生語速計算、生成完成後校正至目標語速、補齊句末提示、
|
| 381 |
只在自然標點切開首段、每 80 字切段,且不使用 retry 或 rerank。
|
| 382 |
"""
|
| 383 |
|
|
|
|
| 66 |
CHUNK_EDGE_FADE_MS = 80.0
|
| 67 |
CHUNK_RMS_MATCH_DB = 4.0
|
| 68 |
STOP_THRESHOLD = 0.50
|
| 69 |
+
STOP_LATE_THRESHOLD = 0.05
|
| 70 |
+
STOP_LATE_START_RATIO = 0.75
|
| 71 |
+
STOP_LATE_FULL_RATIO = 0.95
|
| 72 |
STOP_CONSECUTIVE = 1
|
| 73 |
HARD_STOP_MARGIN_STEPS = 1
|
| 74 |
MIN_PACE_SPEED = 0.80
|
|
|
|
| 377 |
台灣華語與中英混合文字轉語音。模型版本:`{CHECKPOINT}`。
|
| 378 |
|
| 379 |
目前預設採用穩定推論設定:`CFG 2.0`(極短句最低 `3.0`)、`NFE 10`、目標語速 `4.0 字/秒`、
|
| 380 |
+
生成上限依模型原生語速計算、生成完成後校正至目標語速、補齊句末提示、尾端 weak-stop 保護、
|
| 381 |
只在自然標點切開首段、每 80 字切段,且不使用 retry 或 rerank。
|
| 382 |
"""
|
| 383 |
|
tests/test_production.py
CHANGED
|
@@ -81,16 +81,30 @@ def test_stop_controller_relaxes_near_endpoint_and_enforces_hard_stop():
|
|
| 81 |
|
| 82 |
def test_stop_controller_can_relax_before_the_text_pace_cap():
|
| 83 |
controller = StopHysteresisController(
|
| 84 |
-
_SequenceStopHead([0.
|
| 85 |
-
threshold=0.
|
| 86 |
-
late_threshold=0.
|
| 87 |
-
consecutive=
|
| 88 |
-
late_start_ratio=0.
|
| 89 |
-
late_full_ratio=0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
)
|
| 91 |
controller.begin(min_len=2, expected_steps=10, hard_stop_steps=11)
|
| 92 |
-
decisions = [controller(torch.zeros(1, 2)).argmax(dim=-1).item() for _ in range(
|
| 93 |
-
assert decisions == [0, 0, 0, 0, 0, 0, 0, 0
|
| 94 |
|
| 95 |
|
| 96 |
def test_split_preserves_punctuation_and_minimum_chunk_size():
|
|
|
|
| 81 |
|
| 82 |
def test_stop_controller_can_relax_before_the_text_pace_cap():
|
| 83 |
controller = StopHysteresisController(
|
| 84 |
+
_SequenceStopHead([0.04] * 9 + [0.06]),
|
| 85 |
+
threshold=0.50,
|
| 86 |
+
late_threshold=0.05,
|
| 87 |
+
consecutive=1,
|
| 88 |
+
late_start_ratio=0.75,
|
| 89 |
+
late_full_ratio=0.95,
|
| 90 |
+
)
|
| 91 |
+
controller.begin(min_len=2, expected_steps=10, hard_stop_steps=11)
|
| 92 |
+
decisions = [controller(torch.zeros(1, 2)).argmax(dim=-1).item() for _ in range(10)]
|
| 93 |
+
assert decisions == [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def test_stop_controller_does_not_accept_weak_signal_before_late_window():
|
| 97 |
+
controller = StopHysteresisController(
|
| 98 |
+
_SequenceStopHead([0.10] * 8),
|
| 99 |
+
threshold=0.50,
|
| 100 |
+
late_threshold=0.05,
|
| 101 |
+
consecutive=1,
|
| 102 |
+
late_start_ratio=0.75,
|
| 103 |
+
late_full_ratio=0.95,
|
| 104 |
)
|
| 105 |
controller.begin(min_len=2, expected_steps=10, hard_stop_steps=11)
|
| 106 |
+
decisions = [controller(torch.zeros(1, 2)).argmax(dim=-1).item() for _ in range(8)]
|
| 107 |
+
assert decisions == [0, 0, 0, 0, 0, 0, 0, 0]
|
| 108 |
|
| 109 |
|
| 110 |
def test_split_preserves_punctuation_and_minimum_chunk_size():
|