fix(stitcher): improve transition naturalness with cosine fade and noise floor
- Replace 5ms linear fade with 30ms cosine fade (user-adjustable via fade_ms) - Use low-level noise floor in speaker gaps instead of dead silence - Increase default padding 50ms→100ms, reduce gap 300ms→250ms - Cosine curve provides smoother energy transition than linear
This commit is contained in:
+18
-10
@@ -24,13 +24,17 @@ class AIIA_Podcast_Stitcher:
|
||||
},
|
||||
"optional": {
|
||||
"gap_duration": ("FLOAT", {
|
||||
"default": 0.3, "min": 0.0, "max": 2.0, "step": 0.05,
|
||||
"tooltip": "说话人交替时插入的静音时长(秒)"
|
||||
"default": 0.25, "min": 0.0, "max": 2.0, "step": 0.05,
|
||||
"tooltip": "说话人交替时插入的过渡时长(秒)"
|
||||
}),
|
||||
"padding": ("FLOAT", {
|
||||
"default": 0.05, "min": 0.0, "max": 0.5, "step": 0.01,
|
||||
"default": 0.10, "min": 0.0, "max": 0.5, "step": 0.01,
|
||||
"tooltip": "每个切片前后保留的呼吸/尾音余量(秒)"
|
||||
}),
|
||||
"fade_ms": ("INT", {
|
||||
"default": 30, "min": 5, "max": 100, "step": 5,
|
||||
"tooltip": "切片首尾的余弦淡入淡出时长(毫秒),越长越平滑"
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,7 +378,7 @@ class AIIA_Podcast_Stitcher:
|
||||
return boundaries
|
||||
|
||||
def stitch(self, split_map, audio_A, audio_B, asr_A, asr_B,
|
||||
gap_duration=0.3, padding=0.10):
|
||||
gap_duration=0.25, padding=0.10, fade_ms=30):
|
||||
log = f"[{self.NODE_NAME}]"
|
||||
|
||||
# 解析 split_map
|
||||
@@ -436,10 +440,12 @@ class AIIA_Podcast_Stitcher:
|
||||
|
||||
speaker = item["speaker"]
|
||||
|
||||
# 说话人切换时插入间隙
|
||||
# 说话人切换时插入过渡间隙(带低频噪声底噪,避免死寂)
|
||||
if prev_speaker is not None and speaker != prev_speaker:
|
||||
gap_samples = int(gap_duration * sr)
|
||||
audio_segments.append(np.zeros(gap_samples, dtype=np.float32))
|
||||
# 生成极低音量的粉噪声代替纯静音,听感更自然
|
||||
noise = np.random.randn(gap_samples).astype(np.float32) * 0.0003
|
||||
audio_segments.append(noise)
|
||||
current_time += gap_duration
|
||||
|
||||
# 获取对应的边界和音频
|
||||
@@ -486,11 +492,13 @@ class AIIA_Podcast_Stitcher:
|
||||
|
||||
seg_duration = len(segment) / sr
|
||||
|
||||
# 对片段首尾施加短淡入淡出,消除拼接爆音
|
||||
fade_samples = min(int(0.005 * sr), len(segment) // 4) # 5ms fade, 不超过片段长度 1/4
|
||||
# 对片段首尾施加余弦淡入淡出,使拼接过渡平滑自然
|
||||
fade_seconds = fade_ms / 1000.0
|
||||
fade_samples = min(int(fade_seconds * sr), len(segment) // 4)
|
||||
if fade_samples > 1:
|
||||
fade_in = np.linspace(0.0, 1.0, fade_samples, dtype=np.float32)
|
||||
fade_out = np.linspace(1.0, 0.0, fade_samples, dtype=np.float32)
|
||||
# 余弦淡入淡出比线性更平滑——能量变化曲线更接近自然衰减
|
||||
fade_in = (0.5 * (1 - np.cos(np.linspace(0, np.pi, fade_samples)))).astype(np.float32)
|
||||
fade_out = (0.5 * (1 + np.cos(np.linspace(0, np.pi, fade_samples)))).astype(np.float32)
|
||||
segment = segment.copy()
|
||||
segment[:fade_samples] *= fade_in
|
||||
segment[-fade_samples:] *= fade_out
|
||||
|
||||
Reference in New Issue
Block a user