Files
2026-04-03 20:27:09 +08:00

90 lines
3.0 KiB
Python

import os
import time
import json
import math
import random
import numpy as np
import uuid
import torchaudio
import torch
import nodes
import folder_paths
import comfy.utils
import comfy_execution
from server import PromptServer
from . import ASRMapper
MAIN_CATEGORY = "TTS2Whisper/UnionModuleTools/MontrealForcedAligner(MFA)"
class MFASegAlignmentRecovery:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"segments_alignment": ("whisper_alignment", {
"forceInput": True,
}),
"replace_input_str": ("STRING", { "forceInput": True })
},
"hidden": {
"unique_id": "UNIQUE_ID"
}
}
RETURN_TYPES = ("whisper_alignment",)
RETURN_NAMES = ("segments_alignment",)
CATEGORY = f'{MAIN_CATEGORY}'
FUNCTION = "replace_injector"
def replace_injector(self, segments_alignment, replace_input_str, unique_id):
if not segments_alignment or not replace_input_str:
return (segments_alignment, )
mapper = ASRMapper.ASRMappingTextV3() # 確認這裡呼叫到你的類別
# 1. 將所有 MFA 片段拼接成完整的字串,並紀錄每個片段在總字串中的 index 範圍
mfa_full_text = ""
seg_ranges = [] # 儲存格式: (start_idx, end_idx)
for seg in segments_alignment:
start_idx = len(mfa_full_text)
mfa_full_text += seg["value"]
end_idx = len(mfa_full_text)
seg_ranges.append((start_idx, end_idx))
# 2. 進行全局 DP 映射
# 這樣 mapping 陣列的長度會等於 len(replace_input_str)
# mapping[i] 代表 replace_input_str[i] 這個字,對應到 mfa_full_text 的第幾個字元
mapping = mapper.map_text(replace_input_str, mfa_full_text)
# 3. 準備用來裝回填後文字的陣列
new_seg_values = ["" for _ in range(len(segments_alignment))]
# 4. 根據 mapping 結果,把原始文稿的字元分配回各個片段
for i, char in enumerate(replace_input_str):
target_mfa_idx = mapping[i]
# 尋找 target_mfa_idx 屬於哪一個片段 (Segment)
assigned_seg_idx = 0
for seg_idx, (start_idx, end_idx) in enumerate(seg_ranges):
if start_idx <= target_mfa_idx < end_idx:
assigned_seg_idx = seg_idx
break
# 防呆:如果映射剛好超出範圍,歸入最後一個片段
if target_mfa_idx >= seg_ranges[-1][1]:
assigned_seg_idx = len(segments_alignment) - 1
new_seg_values[assigned_seg_idx] += char
# 5. 更新原本的 segments_alignment 並清理空白
for i, seg in enumerate(segments_alignment):
# 去除可能因為標點符號造成的頭尾空白
seg["value"] = new_seg_values[i].strip()
return (segments_alignment, )