AliJabbarpour commited on
Commit
d1df7a1
·
verified ·
1 Parent(s): 9c33bd0

Update pipeline/postprocess.py

Browse files
Files changed (1) hide show
  1. pipeline/postprocess.py +32 -7
pipeline/postprocess.py CHANGED
@@ -1,4 +1,4 @@
1
- # ─── Post-Processing Engine v8 ─────────────────────────────────────────────────
2
 
3
  MIN_DISPLAY = 1.5
4
  MAX_DISPLAY = 7.0
@@ -6,6 +6,7 @@ MERGE_MAX_CHARS = 72
6
  MAX_GAP = 1.5
7
  MAX_LINE_CHARS = 60 # threshold برای split به دو subtitle جداگانه
8
  WRAP_CHARS = 42 # استاندارد Netflix برای wrap به دو خط
 
9
 
10
 
11
  def format_timestamp(seconds: float) -> str:
@@ -30,6 +31,7 @@ def merge_segments(segments: list) -> list:
30
  "start": seg["start"],
31
  "end": seg["end"],
32
  "words": list(seg.get("words", [])),
 
33
  }
34
  continue
35
 
@@ -40,23 +42,37 @@ def merge_segments(segments: list) -> list:
40
  current_duration = current["end"] - current["start"]
41
  is_short = current_duration < 1.5
42
  same_speaker = current.get("speaker") is None or current.get("speaker") == seg.get("speaker")
 
 
 
43
 
44
  should_merge = (
45
  not ends_sentence
46
  and combined_duration <= MAX_DISPLAY
 
47
  and (
48
- same_speaker
49
- and (
50
- is_short
51
- or (len(combined_text) <= MERGE_MAX_CHARS and gap <= MAX_GAP)
52
- )
53
  )
54
  )
55
 
 
 
 
 
 
 
 
 
56
  if should_merge:
57
  current["text"] = combined_text
58
  current["end"] = seg["end"]
59
  current["words"] += list(seg.get("words", []))
 
 
 
 
 
60
  else:
61
  merged.append(current)
62
  current = {
@@ -64,6 +80,7 @@ def merge_segments(segments: list) -> list:
64
  "start": seg["start"],
65
  "end": seg["end"],
66
  "words": list(seg.get("words", [])),
 
67
  }
68
 
69
  if current:
@@ -115,7 +132,11 @@ def split_long_segment(seg: dict) -> list:
115
  """
116
  فقط اگه punctuation نزدیک وسط جمله بود، به دو subtitle جداگانه بشکن.
117
  اگه نقطه مناسبی نبود، نشکن — wrap_text در build_srt دو خطش می‌کنه.
 
118
  """
 
 
 
119
  words = seg.get("words", [])
120
  text = seg["text"].strip()
121
 
@@ -170,7 +191,11 @@ def split_long_segment(seg: dict) -> list:
170
 
171
 
172
  def wrap_text(text: str) -> str:
173
- """اگه متن بیشتر از WRAP_CHARS بود، به دو خط تقسیم کن"""
 
 
 
 
174
  if len(text) <= WRAP_CHARS:
175
  return text
176
 
 
1
+ # ─── Post-Processing Engine v9 ─────────────────────────────────────────────────
2
 
3
  MIN_DISPLAY = 1.5
4
  MAX_DISPLAY = 7.0
 
6
  MAX_GAP = 1.5
7
  MAX_LINE_CHARS = 60 # threshold برای split به دو subtitle جداگانه
8
  WRAP_CHARS = 42 # استاندارد Netflix برای wrap به دو خط
9
+ CPS_LIMIT = 17 # حداکثر کاراکتر قابل‌خواندن در ثانیه - برای تشخیص جمله‌ی «به‌سرعت رد شده»
10
 
11
 
12
  def format_timestamp(seconds: float) -> str:
 
31
  "start": seg["start"],
32
  "end": seg["end"],
33
  "words": list(seg.get("words", [])),
34
+ "speaker": seg.get("speaker"),
35
  }
36
  continue
37
 
 
42
  current_duration = current["end"] - current["start"]
43
  is_short = current_duration < 1.5
44
  same_speaker = current.get("speaker") is None or current.get("speaker") == seg.get("speaker")
45
+ too_fast = (len(current["text"]) / current_duration) > CPS_LIMIT if current_duration > 0 else True
46
+ fits_dialogue = len(current["text"]) <= WRAP_CHARS and len(seg["text"].strip()) <= WRAP_CHARS
47
+ already_dialogue = current.get("is_dialogue_block", False)
48
 
49
  should_merge = (
50
  not ends_sentence
51
  and combined_duration <= MAX_DISPLAY
52
+ and same_speaker
53
  and (
54
+ is_short
55
+ or (len(combined_text) <= MERGE_MAX_CHARS and gap <= MAX_GAP)
 
 
 
56
  )
57
  )
58
 
59
+ should_pair_as_dialogue = (
60
+ not already_dialogue
61
+ and not same_speaker
62
+ and too_fast
63
+ and gap <= MAX_GAP
64
+ and fits_dialogue
65
+ )
66
+
67
  if should_merge:
68
  current["text"] = combined_text
69
  current["end"] = seg["end"]
70
  current["words"] += list(seg.get("words", []))
71
+ elif should_pair_as_dialogue:
72
+ current["text"] = f"- {current['text']}\n- {seg['text'].strip()}"
73
+ current["end"] = seg["end"]
74
+ current["words"] += list(seg.get("words", []))
75
+ current["is_dialogue_block"] = True
76
  else:
77
  merged.append(current)
78
  current = {
 
80
  "start": seg["start"],
81
  "end": seg["end"],
82
  "words": list(seg.get("words", [])),
83
+ "speaker": seg.get("speaker"),
84
  }
85
 
86
  if current:
 
132
  """
133
  فقط اگه punctuation نزدیک وسط جمله بود، به دو subtitle جداگانه بشکن.
134
  اگه نقطه مناسبی نبود، نشکن — wrap_text در build_srt دو خطش می‌کنه.
135
+ بلوک‌های دیالوگِ دو-گوینده‌ای (is_dialogue_block) هیچ‌وقت شکسته نمی‌شن.
136
  """
137
+ if seg.get("is_dialogue_block"):
138
+ return [seg]
139
+
140
  words = seg.get("words", [])
141
  text = seg["text"].strip()
142
 
 
191
 
192
 
193
  def wrap_text(text: str) -> str:
194
+ """اگه متن بیشتر از WRAP_CHARS بود، به دو خط تقسیم کن.
195
+ اگه متن از قبل یه بلوک دیالوگِ دو-گوینده‌ای (با - و خط جدید) بود، دست‌نخورده برگردون."""
196
+ if text.startswith("- ") and "\n" in text:
197
+ return text
198
+
199
  if len(text) <= WRAP_CHARS:
200
  return text
201