continue fixing
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Tuple
|
||||
from typing import Optional, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -11,6 +11,8 @@ FRAME_SAMPLES = 480
|
||||
# speech_frame_mask bridges gaps of up to 5 frames, so use 6 frames (~180 ms).
|
||||
MIN_PAUSE_FRAMES = 6
|
||||
ONSET_MARGIN_MS = 50
|
||||
START_LOOKBACK_MS = 300
|
||||
START_LOOKAHEAD_MS = 400
|
||||
|
||||
|
||||
class AudioAnalysisError(RuntimeError):
|
||||
@@ -150,6 +152,57 @@ def refine_sentence_end_ms(
|
||||
return padded_end_ms
|
||||
|
||||
|
||||
def refine_sentence_start_ms(
|
||||
samples: np.ndarray,
|
||||
sample_rate: int = SAMPLE_RATE,
|
||||
*,
|
||||
raw_start_ms: int,
|
||||
previous_end_ms: int,
|
||||
) -> int:
|
||||
"""Pull a sentence start forward to the actual speech onset.
|
||||
|
||||
Whisper's segment start can be earlier than the real speech onset (the tail
|
||||
of the previous sentence is still audible at the beginning of the next
|
||||
sentence). When the raw start lands inside continuous speech, this looks for
|
||||
the last pause of at least MIN_PAUSE_FRAMES before the next speech run and
|
||||
moves the start to that onset, so adjacent sentences share no audio.
|
||||
"""
|
||||
if raw_start_ms <= previous_end_ms:
|
||||
return max(previous_end_ms, raw_start_ms)
|
||||
frame_ms = 1000 * max(1, int(round(sample_rate * 0.03))) / sample_rate
|
||||
total_ms = samples.size / sample_rate * 1000
|
||||
window_start_ms = max(0, raw_start_ms - START_LOOKBACK_MS)
|
||||
window_end_ms = min(int(total_ms), raw_start_ms + START_LOOKAHEAD_MS)
|
||||
start_sample = int(window_start_ms / 1000 * sample_rate)
|
||||
end_sample = min(samples.size, int(window_end_ms / 1000 * sample_rate))
|
||||
if end_sample - start_sample < max(1, int(round(sample_rate * 0.03))):
|
||||
return raw_start_ms
|
||||
try:
|
||||
speech = speech_frame_mask(samples[start_sample:end_sample], sample_rate)
|
||||
except AudioAnalysisError:
|
||||
return raw_start_ms
|
||||
onset_frame = int(round((raw_start_ms - window_start_ms) / frame_ms))
|
||||
if (
|
||||
0 <= onset_frame < len(speech)
|
||||
and speech[onset_frame]
|
||||
and (onset_frame == 0 or not speech[onset_frame - 1])
|
||||
):
|
||||
return raw_start_ms # already at a speech onset
|
||||
boundary_ms: Optional[float] = None
|
||||
silence_frames = 0
|
||||
for index, is_speech in enumerate(speech):
|
||||
if not is_speech:
|
||||
silence_frames += 1
|
||||
continue
|
||||
if silence_frames >= MIN_PAUSE_FRAMES:
|
||||
boundary_ms = window_start_ms + index * frame_ms
|
||||
silence_frames = 0
|
||||
if boundary_ms is None:
|
||||
return raw_start_ms
|
||||
boundary_ms = min(boundary_ms, raw_start_ms + START_LOOKAHEAD_MS)
|
||||
return max(previous_end_ms, int(boundary_ms))
|
||||
|
||||
|
||||
def _bridge_false_runs(values: np.ndarray, max_frames: int) -> None:
|
||||
start = None
|
||||
for index, value in enumerate(values):
|
||||
|
||||
Reference in New Issue
Block a user