AliJabbarpour commited on
Commit
0a096dd
·
verified ·
1 Parent(s): 9e7707f

Update pipeline/postprocess.py

Browse files
Files changed (1) hide show
  1. pipeline/postprocess.py +10 -28
pipeline/postprocess.py CHANGED
@@ -1,10 +1,10 @@
1
- # ─── Post-Processing Engine v5 ─────────────────────────────────────────────────
2
 
3
- MIN_DISPLAY = 2.5 # حداقل زمان نمایش هر subtitle (ثانیه)
4
- MAX_DISPLAY = 7.0 # حداکثر زمان نمایش
5
- MERGE_MAX_CHARS = 72 # حداکثر کاراکتر برای merge (با فاصله)
6
- SPLIT_MAX_CHARS = 60 # حداکثر کاراکتر قبل از split (با فاصله)
7
- MAX_GAP = 1.5 # حداکثر فاصله بین دو segment برای merge
8
 
9
 
10
  def format_timestamp(seconds: float) -> str:
@@ -16,7 +16,6 @@ def format_timestamp(seconds: float) -> str:
16
 
17
 
18
  def merge_segments(segments: list) -> list:
19
- """ادغام segment‌های کوتاه به جملات کامل"""
20
  if not segments:
21
  return []
22
 
@@ -38,7 +37,7 @@ def merge_segments(segments: list) -> list:
38
  combined_duration = seg["end"] - current["start"]
39
  ends_sentence = current["text"].rstrip().endswith((".", "!", "?"))
40
 
41
- # segment کوتاه — همیشه merge کن
42
  current_words = current.get("words", [])
43
  is_short = len(current_words) <= 2 or (current["end"] - current["start"]) < 0.8
44
 
@@ -46,10 +45,10 @@ def merge_segments(segments: list) -> list:
46
  not ends_sentence
47
  and combined_duration <= MAX_DISPLAY
48
  and (
49
- is_short # segment کوتاه رو همیشه merge کن
50
  or (len(combined_text) <= MERGE_MAX_CHARS and gap <= MAX_GAP)
51
  )
52
- )
53
 
54
  if should_merge:
55
  current["text"] = combined_text
@@ -71,7 +70,6 @@ def merge_segments(segments: list) -> list:
71
 
72
 
73
  def remove_duplicates(segments: list) -> list:
74
- """حذف subtitle‌های تکراری متوالی"""
75
  if not segments:
76
  return []
77
  result = [segments[0]]
@@ -82,7 +80,6 @@ def remove_duplicates(segments: list) -> list:
82
 
83
 
84
  def fix_overlaps(segments: list) -> list:
85
- """رفع timestamp‌های overlapping"""
86
  fixed = []
87
  for seg in segments:
88
  seg = dict(seg)
@@ -95,35 +92,29 @@ def fix_overlaps(segments: list) -> list:
95
 
96
 
97
  def apply_min_display(segments: list) -> list:
98
- """اعمال حداقل زمان نمایش"""
99
  result = []
100
  for i, seg in enumerate(segments):
101
  seg = dict(seg)
102
  duration = seg["end"] - seg["start"]
103
-
104
  if duration < MIN_DISPLAY:
105
  if i + 1 < len(segments):
106
  next_start = segments[i + 1]["start"]
107
  max_end = next_start - 0.080
108
  else:
109
  max_end = seg["end"] + MAX_DISPLAY
110
-
111
  new_end = seg["start"] + MIN_DISPLAY
112
  seg["end"] = min(new_end, max(max_end, seg["end"]))
113
-
114
  result.append(seg)
115
  return result
116
 
117
 
118
  def split_long_segment(seg: dict) -> list:
119
- """شکستن segment‌های خیلی طولانی"""
120
  words = seg.get("words", [])
121
  text = seg["text"].strip()
122
 
123
  if len(text) <= SPLIT_MAX_CHARS or len(words) < 3:
124
  return [seg]
125
 
126
- # پیدا کردن بهترین نقطه split (بزرگ‌ترین gap)
127
  best_idx = len(words) // 2
128
  best_gap = -1
129
  for i in range(1, len(words)):
@@ -175,24 +166,15 @@ def process(segments: list) -> str:
175
  if not segments:
176
  return ""
177
 
178
- # ۱ — ادغام segment‌های کوتاه
179
  merged = merge_segments(segments)
180
-
181
- # ۲ — حذف duplicate
182
  merged = remove_duplicates(merged)
 
183
 
184
- # ۳ — رفع overlap
185
- fixed = fix_overlaps(merged)
186
-
187
- # ۴ — شکستن segment‌های خیلی طولانی
188
  split = []
189
  for seg in fixed:
190
  split.extend(split_long_segment(seg))
191
 
192
- # ۵ — رفع overlap بعد از split
193
  split = fix_overlaps(split)
194
-
195
- # ۶ — اعمال حداقل زمان نمایش
196
  final = apply_min_display(split)
197
 
198
  return build_srt(final)
 
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 = 60
7
+ MAX_GAP = 1.5
8
 
9
 
10
  def format_timestamp(seconds: float) -> str:
 
16
 
17
 
18
  def merge_segments(segments: list) -> list:
 
19
  if not segments:
20
  return []
21
 
 
37
  combined_duration = seg["end"] - current["start"]
38
  ends_sentence = current["text"].rstrip().endswith((".", "!", "?"))
39
 
40
+ # segment کوتاه (کمتر از ۳ کلمه یا کمتر از ۰.۸ ثانیه) → همیشه merge کن
41
  current_words = current.get("words", [])
42
  is_short = len(current_words) <= 2 or (current["end"] - current["start"]) < 0.8
43
 
 
45
  not ends_sentence
46
  and combined_duration <= MAX_DISPLAY
47
  and (
48
+ is_short
49
  or (len(combined_text) <= MERGE_MAX_CHARS and gap <= MAX_GAP)
50
  )
51
+ )
52
 
53
  if should_merge:
54
  current["text"] = combined_text
 
70
 
71
 
72
  def remove_duplicates(segments: list) -> list:
 
73
  if not segments:
74
  return []
75
  result = [segments[0]]
 
80
 
81
 
82
  def fix_overlaps(segments: list) -> list:
 
83
  fixed = []
84
  for seg in segments:
85
  seg = dict(seg)
 
92
 
93
 
94
  def apply_min_display(segments: list) -> list:
 
95
  result = []
96
  for i, seg in enumerate(segments):
97
  seg = dict(seg)
98
  duration = seg["end"] - seg["start"]
 
99
  if duration < MIN_DISPLAY:
100
  if i + 1 < len(segments):
101
  next_start = segments[i + 1]["start"]
102
  max_end = next_start - 0.080
103
  else:
104
  max_end = seg["end"] + MAX_DISPLAY
 
105
  new_end = seg["start"] + MIN_DISPLAY
106
  seg["end"] = min(new_end, max(max_end, seg["end"]))
 
107
  result.append(seg)
108
  return result
109
 
110
 
111
  def split_long_segment(seg: dict) -> list:
 
112
  words = seg.get("words", [])
113
  text = seg["text"].strip()
114
 
115
  if len(text) <= SPLIT_MAX_CHARS or len(words) < 3:
116
  return [seg]
117
 
 
118
  best_idx = len(words) // 2
119
  best_gap = -1
120
  for i in range(1, len(words)):
 
166
  if not segments:
167
  return ""
168
 
 
169
  merged = merge_segments(segments)
 
 
170
  merged = remove_duplicates(merged)
171
+ fixed = fix_overlaps(merged)
172
 
 
 
 
 
173
  split = []
174
  for seg in fixed:
175
  split.extend(split_long_segment(seg))
176
 
 
177
  split = fix_overlaps(split)
 
 
178
  final = apply_min_display(split)
179
 
180
  return build_srt(final)