Spaces:
Paused
Paused
Update float_streamer.py
Browse files- float_streamer.py +46 -13
float_streamer.py
CHANGED
|
@@ -52,6 +52,9 @@ class FloatStreamer:
|
|
| 52 |
|
| 53 |
self.ready = False
|
| 54 |
self.current_dampening = 0.35
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
def initialize(self, model, device, opt, ref_image_tensor, wav2vec_preprocessor):
|
| 57 |
self.model = model
|
|
@@ -112,8 +115,6 @@ class FloatStreamer:
|
|
| 112 |
|
| 113 |
speech_array, sr = librosa.load(audio_path, sr=self.sampling_rate)
|
| 114 |
|
| 115 |
-
# BUG FIX: ONLY pad with silence if this is the very last sentence of the entire response.
|
| 116 |
-
# Otherwise, the avatar's mouth will awkwardly clamp shut between every sentence.
|
| 117 |
if is_last:
|
| 118 |
pad_samples = int(0.5 * self.sampling_rate)
|
| 119 |
speech_array = np.concatenate([speech_array, np.zeros(pad_samples, dtype=speech_array.dtype)])
|
|
@@ -147,7 +148,6 @@ class FloatStreamer:
|
|
| 147 |
}
|
| 148 |
self._speech_queue.put(chunk_data)
|
| 149 |
|
| 150 |
-
# BUG FIX: ONLY tell the streamer to transition back to the Idle phase if this is the final sentence.
|
| 151 |
if is_last:
|
| 152 |
self._speech_queue.put({"type": "speech_end"})
|
| 153 |
|
|
@@ -195,13 +195,25 @@ class FloatStreamer:
|
|
| 195 |
cfg = self._idle_cfg_scale
|
| 196 |
if cfg > 1.0: self._idle_cfg_scale = max(1.0, cfg - 0.35)
|
| 197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
self._generate_chunk(
|
| 199 |
wa=self._silence_wa, we=self._silence_we, actual_frames=self.frames_per_chunk,
|
| 200 |
-
a_cfg_scale=cfg, e_cfg_scale=1.0, is_speech=False, nfe=3,
|
|
|
|
| 201 |
)
|
| 202 |
|
| 203 |
@torch.no_grad()
|
| 204 |
-
def _generate_chunk(self, wa, we, actual_frames=None, a_cfg_scale=None, e_cfg_scale=None, is_speech=False, nfe=None, speech_start_event=None):
|
| 205 |
if actual_frames is None: actual_frames = self.frames_per_chunk
|
| 206 |
if a_cfg_scale is None: a_cfg_scale = self.opt.a_cfg_scale
|
| 207 |
if e_cfg_scale is None: e_cfg_scale = self.opt.e_cfg_scale
|
|
@@ -237,15 +249,36 @@ class FloatStreamer:
|
|
| 237 |
self.prev_x = sample[:, -self.num_prev_frames:].clone()
|
| 238 |
self.prev_wa = wa[:, -self.num_prev_frames:].clone()
|
| 239 |
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
else:
|
| 248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
|
| 250 |
t_dec = time.time()
|
| 251 |
frames_pushed = 0
|
|
|
|
| 52 |
|
| 53 |
self.ready = False
|
| 54 |
self.current_dampening = 0.35
|
| 55 |
+
|
| 56 |
+
# Global counter to keep sine waves continuous across chunks
|
| 57 |
+
self._idle_frame_counter = 0
|
| 58 |
|
| 59 |
def initialize(self, model, device, opt, ref_image_tensor, wav2vec_preprocessor):
|
| 60 |
self.model = model
|
|
|
|
| 115 |
|
| 116 |
speech_array, sr = librosa.load(audio_path, sr=self.sampling_rate)
|
| 117 |
|
|
|
|
|
|
|
| 118 |
if is_last:
|
| 119 |
pad_samples = int(0.5 * self.sampling_rate)
|
| 120 |
speech_array = np.concatenate([speech_array, np.zeros(pad_samples, dtype=speech_array.dtype)])
|
|
|
|
| 148 |
}
|
| 149 |
self._speech_queue.put(chunk_data)
|
| 150 |
|
|
|
|
| 151 |
if is_last:
|
| 152 |
self._speech_queue.put({"type": "speech_end"})
|
| 153 |
|
|
|
|
| 195 |
cfg = self._idle_cfg_scale
|
| 196 |
if cfg > 1.0: self._idle_cfg_scale = max(1.0, cfg - 0.35)
|
| 197 |
|
| 198 |
+
# Ported from batch_idle.py: Recreate the lively "breathing" using a continuous sine wave!
|
| 199 |
+
dampening = torch.zeros(1, self.frames_per_chunk, 1, device=self.device)
|
| 200 |
+
damp_mid = 0.50
|
| 201 |
+
damp_amp = 0.15
|
| 202 |
+
|
| 203 |
+
for t in range(self.frames_per_chunk):
|
| 204 |
+
global_t = self._idle_frame_counter + t
|
| 205 |
+
dampening[0, t, 0] = damp_mid + damp_amp * math.sin(global_t * 0.06)
|
| 206 |
+
|
| 207 |
+
self._idle_frame_counter += self.frames_per_chunk
|
| 208 |
+
|
| 209 |
self._generate_chunk(
|
| 210 |
wa=self._silence_wa, we=self._silence_we, actual_frames=self.frames_per_chunk,
|
| 211 |
+
a_cfg_scale=cfg, e_cfg_scale=1.0, is_speech=False, nfe=3,
|
| 212 |
+
dynamic_dampening=dampening
|
| 213 |
)
|
| 214 |
|
| 215 |
@torch.no_grad()
|
| 216 |
+
def _generate_chunk(self, wa, we, actual_frames=None, a_cfg_scale=None, e_cfg_scale=None, is_speech=False, nfe=None, speech_start_event=None, dynamic_dampening=None):
|
| 217 |
if actual_frames is None: actual_frames = self.frames_per_chunk
|
| 218 |
if a_cfg_scale is None: a_cfg_scale = self.opt.a_cfg_scale
|
| 219 |
if e_cfg_scale is None: e_cfg_scale = self.opt.e_cfg_scale
|
|
|
|
| 249 |
self.prev_x = sample[:, -self.num_prev_frames:].clone()
|
| 250 |
self.prev_wa = wa[:, -self.num_prev_frames:].clone()
|
| 251 |
|
| 252 |
+
# ---- FLUID DAMPENING LOGIC ----
|
| 253 |
+
if is_speech:
|
| 254 |
+
target_dampening = 1.0
|
| 255 |
+
if isinstance(self.current_dampening, torch.Tensor):
|
| 256 |
+
# Transitioning from organic idle wave -> full speech
|
| 257 |
+
start_val = self.current_dampening[0, -1, 0].item()
|
| 258 |
+
damp_curve = torch.linspace(start_val, 1.0, sample.shape[1], device=self.device).view(1, -1, 1)
|
| 259 |
+
sample_display = sample * damp_curve
|
| 260 |
+
elif abs(self.current_dampening - target_dampening) > 0.01:
|
| 261 |
+
# Transitioning from flat float -> float
|
| 262 |
+
damp_curve = torch.linspace(self.current_dampening, target_dampening, sample.shape[1], device=self.device).view(1, -1, 1)
|
| 263 |
+
sample_display = sample * damp_curve
|
| 264 |
+
else:
|
| 265 |
+
sample_display = sample * target_dampening
|
| 266 |
+
self.current_dampening = 1.0
|
| 267 |
else:
|
| 268 |
+
# Applying organic breathing curve from batch_idle.py
|
| 269 |
+
if dynamic_dampening is not None:
|
| 270 |
+
if isinstance(self.current_dampening, float):
|
| 271 |
+
# Transitioning from speech -> down to the organic idle wave
|
| 272 |
+
fade = torch.linspace(1.0, 0.0, sample.shape[1], device=self.device).view(1, -1, 1)
|
| 273 |
+
damp_curve = self.current_dampening * fade + dynamic_dampening * (1.0 - fade)
|
| 274 |
+
sample_display = sample * damp_curve
|
| 275 |
+
else:
|
| 276 |
+
# Continuous organic idle wave
|
| 277 |
+
sample_display = sample * dynamic_dampening
|
| 278 |
+
self.current_dampening = dynamic_dampening
|
| 279 |
+
else:
|
| 280 |
+
sample_display = sample * 0.35
|
| 281 |
+
self.current_dampening = 0.35
|
| 282 |
|
| 283 |
t_dec = time.time()
|
| 284 |
frames_pushed = 0
|