Update app.py
Browse files
app.py
CHANGED
|
@@ -83,8 +83,11 @@ def format_time(seconds):
|
|
| 83 |
return f"{h:01d}:{m:02d}:{s:02d}.{cs:02d}"
|
| 84 |
|
| 85 |
def fix_persian_chars(text):
|
|
|
|
| 86 |
if not text: return ""
|
| 87 |
try:
|
|
|
|
|
|
|
| 88 |
return arabic_reshaper.reshape(text)
|
| 89 |
except:
|
| 90 |
return text
|
|
@@ -92,7 +95,7 @@ def fix_persian_chars(text):
|
|
| 92 |
def create_ass(data: ProcessRequest, path: str):
|
| 93 |
s = data.style
|
| 94 |
|
| 95 |
-
# نگاشت نام فونتها (
|
| 96 |
font_map = {
|
| 97 |
"vazir": "Vazirmatn",
|
| 98 |
"lalezar": "Lalezar",
|
|
@@ -101,7 +104,8 @@ def create_ass(data: ProcessRequest, path: str):
|
|
| 101 |
}
|
| 102 |
font_name = font_map.get(s.font, "Vazirmatn")
|
| 103 |
|
| 104 |
-
# تنظیمات Bold:
|
|
|
|
| 105 |
use_bold = 1
|
| 106 |
if font_name in ["Lalezar", "Bangers"]:
|
| 107 |
use_bold = 0
|
|
@@ -138,7 +142,7 @@ def create_ass(data: ProcessRequest, path: str):
|
|
| 138 |
outline_w = int(font_size * 0.04)
|
| 139 |
shadow = 2
|
| 140 |
|
| 141 |
-
# هدر ASS
|
| 142 |
header = f"""[Script Info]
|
| 143 |
ScriptType: v4.00+
|
| 144 |
PlayResX: {data.video_width}
|
|
@@ -163,6 +167,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|
| 163 |
f.write(header)
|
| 164 |
for seg in data.segments:
|
| 165 |
|
|
|
|
| 166 |
if is_purple_mode and seg.words:
|
| 167 |
words_list = seg.words
|
| 168 |
for i in range(len(words_list)):
|
|
@@ -171,7 +176,14 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|
| 171 |
end_t = format_time(current_word_obj.end)
|
| 172 |
|
| 173 |
line_parts = []
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
reversed_indices = range(len(words_list) - 1, -1, -1)
|
| 176 |
|
| 177 |
for j in reversed_indices:
|
|
@@ -186,8 +198,11 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|
| 186 |
final_text = " ".join(line_parts).replace('\n', '\\N')
|
| 187 |
f.write(f"Dialogue: 0,{start_t},{end_t},Default,,0,0,0,,{final_text}\n")
|
| 188 |
|
|
|
|
| 189 |
else:
|
| 190 |
clean_text = seg.text.strip().replace('\u200c', ' ')
|
|
|
|
|
|
|
| 191 |
words = clean_text.split()
|
| 192 |
reversed_words = []
|
| 193 |
for w in reversed(words):
|
|
@@ -199,6 +214,8 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|
| 199 |
end = format_time(seg.end)
|
| 200 |
f.write(f"Dialogue: 0,{start},{end},Default,,0,0,0,,{final_text_fixed}\n")
|
| 201 |
|
|
|
|
|
|
|
| 202 |
@app.get("/")
|
| 203 |
async def index():
|
| 204 |
return FileResponse("index.html")
|
|
|
|
| 83 |
return f"{h:01d}:{m:02d}:{s:02d}.{cs:02d}"
|
| 84 |
|
| 85 |
def fix_persian_chars(text):
|
| 86 |
+
"""حروف فارسی را میچسباند (Reshape)"""
|
| 87 |
if not text: return ""
|
| 88 |
try:
|
| 89 |
+
# فقط حروف را میچسبانیم. جهت (Bidi) را FFmpeg خودش مدیریت میکند اگر تگ نزنیم
|
| 90 |
+
# اما چون ما تگ میزنیم، خودمان کلمات را معکوس میکنیم.
|
| 91 |
return arabic_reshaper.reshape(text)
|
| 92 |
except:
|
| 93 |
return text
|
|
|
|
| 95 |
def create_ass(data: ProcessRequest, path: str):
|
| 96 |
s = data.style
|
| 97 |
|
| 98 |
+
# نگاشت نام فونتها (Family Name)
|
| 99 |
font_map = {
|
| 100 |
"vazir": "Vazirmatn",
|
| 101 |
"lalezar": "Lalezar",
|
|
|
|
| 104 |
}
|
| 105 |
font_name = font_map.get(s.font, "Vazirmatn")
|
| 106 |
|
| 107 |
+
# تنظیمات Bold: اگر فونت Lalezar یا Bangers است، Bold=0 باشد (چون فقط Regular دارند)
|
| 108 |
+
# اگر Bold=1 باشد و فونت بولد نداشته باشد، FFmpeg فونت پیشفرض (Arial) را نشان میدهد.
|
| 109 |
use_bold = 1
|
| 110 |
if font_name in ["Lalezar", "Bangers"]:
|
| 111 |
use_bold = 0
|
|
|
|
| 142 |
outline_w = int(font_size * 0.04)
|
| 143 |
shadow = 2
|
| 144 |
|
| 145 |
+
# هدر فایل ASS
|
| 146 |
header = f"""[Script Info]
|
| 147 |
ScriptType: v4.00+
|
| 148 |
PlayResX: {data.video_width}
|
|
|
|
| 167 |
f.write(header)
|
| 168 |
for seg in data.segments:
|
| 169 |
|
| 170 |
+
# --- حالت کارائوکه ---
|
| 171 |
if is_purple_mode and seg.words:
|
| 172 |
words_list = seg.words
|
| 173 |
for i in range(len(words_list)):
|
|
|
|
| 176 |
end_t = format_time(current_word_obj.end)
|
| 177 |
|
| 178 |
line_parts = []
|
| 179 |
+
|
| 180 |
+
# *** منطق نمایش فارسی در FFmpeg ***
|
| 181 |
+
# چون تگهای ASS وسط جمله میآیند، رندر RTL به هم میریزد.
|
| 182 |
+
# راه حل:
|
| 183 |
+
# 1. کلمات را یکی یکی Reshape میکنیم (حروف بچسبند).
|
| 184 |
+
# 2. لیست کلمات را معکوس میکنیم (کلمه آخر اول بیاید).
|
| 185 |
+
# 3. به صورت LTR رندر میشود اما چون ترتیب عکس است، درست خوانده میشود.
|
| 186 |
+
|
| 187 |
reversed_indices = range(len(words_list) - 1, -1, -1)
|
| 188 |
|
| 189 |
for j in reversed_indices:
|
|
|
|
| 198 |
final_text = " ".join(line_parts).replace('\n', '\\N')
|
| 199 |
f.write(f"Dialogue: 0,{start_t},{end_t},Default,,0,0,0,,{final_text}\n")
|
| 200 |
|
| 201 |
+
# --- حالت ساده ---
|
| 202 |
else:
|
| 203 |
clean_text = seg.text.strip().replace('\u200c', ' ')
|
| 204 |
+
|
| 205 |
+
# برای حالت ساده هم همین منطق معکوسسازی کلمات بهتر جواب میدهد
|
| 206 |
words = clean_text.split()
|
| 207 |
reversed_words = []
|
| 208 |
for w in reversed(words):
|
|
|
|
| 214 |
end = format_time(seg.end)
|
| 215 |
f.write(f"Dialogue: 0,{start},{end},Default,,0,0,0,,{final_text_fixed}\n")
|
| 216 |
|
| 217 |
+
# --- سایر اندپوینتها ---
|
| 218 |
+
|
| 219 |
@app.get("/")
|
| 220 |
async def index():
|
| 221 |
return FileResponse("index.html")
|