AliJabbarpour commited on
Commit
ae9db8f
·
verified ·
1 Parent(s): 0c72f39

Update pipeline/postprocess.py

Browse files
Files changed (1) hide show
  1. pipeline/postprocess.py +33 -14
pipeline/postprocess.py CHANGED
@@ -1,10 +1,10 @@
1
- # ─── Post-Processing Engine v6 ─────────────────────────────────────────────────
2
 
3
- MIN_DISPLAY = 2.5
4
- MAX_DISPLAY = 7.0
5
- MERGE_MAX_CHARS = 72
6
- SPLIT_MAX_CHARS = 100
7
- MAX_GAP = 1.5
8
 
9
 
10
  def format_timestamp(seconds: float) -> str:
@@ -16,6 +16,7 @@ def format_timestamp(seconds: float) -> str:
16
 
17
 
18
  def merge_segments(segments: list) -> list:
 
19
  if not segments:
20
  return []
21
 
@@ -36,9 +37,8 @@ def merge_segments(segments: list) -> list:
36
  combined_text = current["text"] + " " + seg["text"].strip()
37
  combined_duration = seg["end"] - current["start"]
38
  ends_sentence = current["text"].rstrip().endswith((".", "!", "?"))
39
-
40
- current_duration = current["end"] - current["start"]
41
- is_short = current_duration < 1.5
42
 
43
  should_merge = (
44
  not ends_sentence
@@ -107,22 +107,34 @@ def apply_min_display(segments: list) -> list:
107
  return result
108
 
109
 
110
- def split_long_segment(seg: dict, depth: int = 0) -> list:
 
 
 
 
111
  words = seg.get("words", [])
112
  text = seg["text"].strip()
113
 
114
- # حداکثر ۲ بار split — جلوگیری از تک کلمه شدن
115
- if depth >= 1 or len(text) <= SPLIT_MAX_CHARS or len(words) < 8:
116
  return [seg]
117
 
118
- best_idx = len(words) // 2
 
 
119
  best_gap = -1
 
 
120
  for i in range(1, len(words)):
121
  gap = words[i]["start"] - words[i - 1]["end"]
122
  if gap > best_gap:
123
  best_gap = gap
124
  best_idx = i
125
 
 
 
 
 
126
  words1 = words[:best_idx]
127
  words2 = words[best_idx:]
128
 
@@ -132,6 +144,12 @@ def split_long_segment(seg: dict, depth: int = 0) -> list:
132
  start2 = words2[0]["start"]
133
  end1 = max(start2 - 0.080, words1[-1]["end"])
134
 
 
 
 
 
 
 
135
  seg1 = {
136
  "text": " ".join(w["word"].strip() for w in words1),
137
  "start": words1[0]["start"],
@@ -145,7 +163,8 @@ def split_long_segment(seg: dict, depth: int = 0) -> list:
145
  "words": words2,
146
  }
147
 
148
- return split_long_segment(seg1, depth + 1) + split_long_segment(seg2, depth + 1)
 
149
 
150
 
151
  def build_srt(segments: list) -> str:
 
1
+ # ─── Post-Processing Engine v7 ─────────────────────────────────────────────────
2
 
3
+ MIN_DISPLAY = 1.5 # حداقل زمان نمایش (ثانیه)
4
+ MAX_DISPLAY = 7.0 # حداکثر زمان نمایش
5
+ MERGE_MAX_CHARS = 72 # حداکثر کاراکتر برای merge
6
+ MAX_GAP = 1.5 # حداکثر فاصله بین دو segment برای merge
7
+ MAX_LINE_CHARS = 42 # استاندارد Netflix — حداکثر کاراکتر در هر خط
8
 
9
 
10
  def format_timestamp(seconds: float) -> str:
 
16
 
17
 
18
  def merge_segments(segments: list) -> list:
19
+ """ادغام segment‌های کوتاه به جملات کامل"""
20
  if not segments:
21
  return []
22
 
 
37
  combined_text = current["text"] + " " + seg["text"].strip()
38
  combined_duration = seg["end"] - current["start"]
39
  ends_sentence = current["text"].rstrip().endswith((".", "!", "?"))
40
+ current_duration = current["end"] - current["start"]
41
+ is_short = current_duration < 1.5
 
42
 
43
  should_merge = (
44
  not ends_sentence
 
107
  return result
108
 
109
 
110
+ def split_long_segment(seg: dict) -> list:
111
+ """
112
+ اگه segment بیشتر از MAX_LINE_CHARS کاراکتر داشت،
113
+ تبدیل میشه به دو subtitle جداگانه با timestamp مجزا.
114
+ """
115
  words = seg.get("words", [])
116
  text = seg["text"].strip()
117
 
118
+ # اگه کوتاهه یا کلمه کافی نداره، نشکن
119
+ if len(text) <= MAX_LINE_CHARS or len(words) < 4:
120
  return [seg]
121
 
122
+ # پیدا کردن بهترین نقطه split
123
+ mid = len(words) // 2
124
+ best_idx = mid
125
  best_gap = -1
126
+
127
+ # اول دنبال بزرگ‌ترین gap بگرد
128
  for i in range(1, len(words)):
129
  gap = words[i]["start"] - words[i - 1]["end"]
130
  if gap > best_gap:
131
  best_gap = gap
132
  best_idx = i
133
 
134
+ # اگه gap خیلی کوچیکه (زیر ۵۰ms)، از وسط بشکن
135
+ if best_gap < 0.050:
136
+ best_idx = mid
137
+
138
  words1 = words[:best_idx]
139
  words2 = words[best_idx:]
140
 
 
144
  start2 = words2[0]["start"]
145
  end1 = max(start2 - 0.080, words1[-1]["end"])
146
 
147
+ # safety: حداقل MIN_DISPLAY برای هر بخش
148
+ if end1 - words1[0]["start"] < MIN_DISPLAY:
149
+ end1 = words1[0]["start"] + MIN_DISPLAY
150
+ if end1 >= start2:
151
+ end1 = start2 - 0.040
152
+
153
  seg1 = {
154
  "text": " ".join(w["word"].strip() for w in words1),
155
  "start": words1[0]["start"],
 
163
  "words": words2,
164
  }
165
 
166
+ # recursive — اگه هنوز طولانیه، دوباره بشکن
167
+ return split_long_segment(seg1) + split_long_segment(seg2)
168
 
169
 
170
  def build_srt(segments: list) -> str: