Persian Sub Tizone — ساخت زیرنویس SRT فارسی
خط لوله: ffmpeg (استخراج صدا) → 9Router /v1/audio/transcriptions (ترنکرایب) → همترازی زمان با بلوکهای همپوشان → خروجی .srt.
روشِ سریع — همین را اجرا کن
یک فرمان، کل کار را میکند (استخراج صدا → متن کاملِ یکباره → بلوکهای همپوشان با کش → همترازی → نوشتن .srt):
python3 pipeline/stt.py "$VIDEO" # → کنارِ ویدیو: video.srt
python3 pipeline/stt.py "$VIDEO" -m groq/whisper-large-v3-turbo # جایگزینِ مدل
خروجی: فایل video.srt کنار فایل اصلی — مستقیم در Premiere قابل Import است (File → Import یا درگ به تایملاین).
رفتاری که باید بدانی:
- کار در پوشهٔ
<video>.pst/کنارِ خود فایل میماند؛ اجرای دوباره از همانجا ادامه میدهد (بلوکهای تمامشده دوباره صدا زده نمیشوند، فقط بلوکِ نیمهکاره تکرار میشود). - ۴۲۹ (quota): پیام را میخواند و همانقدر میخوابد (۳ بار)، بعد اگر باز هم ۴۲۹ بود به
gemini/gemini-2.5-flash-lite(سهمیهٔ جدا) فالبک میزند. فاصلهٔ ۳–۵ ثانیه بین فراخوانیها و timeout هر کدام ۶۰ ثانیه هم داخل اسکریپت است. - مدل پیشفرض
gemini/gemini-2.5-flashاست (بهترین متن فارسی). - بدون کلید خاموش نمیشود:
NINEROUTER_KEY نیستمیگوید و میایستد — کلید را از کاربر بگیر، حدس نزن.
چکها (بدون کلید و بدون شبکه):
python3 pipeline/stt.py --selftest # chunking + multipart + پارسِ 429
python3 pipeline/test_e2e.py # کل خط لوله روی سرور STTِ جعلیِ محلی
پیشنیاز (یکبار)
export NINEROUTER_URL="https://9router.peditx.ir" # یا هاست 9Router کاربر
export NINEROUTER_KEY="sk-..."
curl -s "$NINEROUTER_URL/api/health" # باید {"ok":true} بدهد
اگر key نبود از کاربر بگیر؛ حدس نزن.
جزئیات خط لوله (فقط برای عیبیابی/توسعه)
۱) استخراج صدا
DUR=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$VIDEO")
ffmpeg -y -i "$VIDEO" -vn -ac 1 -ar 16000 -b:a 64k /tmp/audio.mp3
۲) ترنکرایب — بلوکهای همپوشان ۶ ثانیهای (hop=4s)
# هر کلمه در ≥ یک بلوک قرار میگیرد
ffmpeg -i audio.mp3 -ss <t> -t 6 -c copy ch/NN_t.mp3
# هر بلوک: POST /v1/audio/transcriptions model=gemini/gemini-2.5-flash response_format=json
- ۴۲۹ را جدی بگیر: پیام را بخوان،
reset after Xmرا همانقدر بخواب، دوباره بزن. - پاسخهای خراب/ناقص را با
try/exceptرد کن و حداکثر ۳ بار retry بزن. - خروجیها را در
chunks.jsonذخیره کن تا resume کار کند.
۳) همترازی زمان (کلید کیفیت)
متن کامل را یکبار از روی کل ویدیو بگیر، بعد کلمات را روی بلوکها با difflib.SequenceMatcher همتراز کن و به هر کلمه یک زمان interpolate کن:
import difflib, re
W = lambda s: re.findall(r"[^\s]+", s)
norm = lambda w: re.sub(r"[^\w-ۿ]", "", w.lower())
gw = W(full_text)
# برای هر بلوک: بهترین جایگاه start در gw را با SequenceMatcher پیدا کن
# word j ← time = start + 6 * i/(n-1) ؛ خلأها را interpolate کن
اگر ratio < 0.45 بود بلوک را رد کن و از زمانهای segments همان بلوک بهعنوان fallback استفاده کن.
۴) ساختن SRT
MAX_CHARS, MAX_DUR = 84, 7.0
SOFT_CHARS, SOFT_DUR = 72, 6.0
# شکستن: اول پایان جمله (. ؟ !) با طول ≥30 → اولویت؛ وگنه کاما/طول/مدت
# اگر cue زیر 22 کاراکتر بود با cue قبلی ادغامش کن
def ts(x): return f"{int(x//3600):02d}:{int(x%3600//60):02d}:{int(x%60):02d},{int(round((x-int(x))*1000)):03d}"
# شکستن خط: تعادل دو خط در ۴۶ کاراکتر (حداکثر ۲ خط)
پیادهسازی: pipeline/mk_srt.py
python3 pipeline/mk_srt.py -t g.json -c chunks.json --media "$VIDEO" -o "${VIDEO%.*}.srt"
python3 pipeline/mk_srt.py --selftest
۵) صیقلیسازی املای فارسی (اختیاری)
{"model":"claude-sonnet-4-6","temperature":0.1,
"messages":[{"role":"system","content":"ویراستار فارسی. خروجی فقط JSON معتبر."},
{"role":"user","content":"فقط املای فارسی را اصلاح کن؛ معنی/تعداد کلمات/ترتیب را عوض نکن. خروجی: [{\"i\":..,\"t\":\"..\"}]"}]}
خروجی باید دقیقاً همان تعداد cue را برگرداند؛ وگرنه assert کن و به متن خام برگرد.
نرمالسازی امن: ي → ی و ك → ک.
۶) تأیید نهایی
- یک قاب از ویدیو در چند نقطه بخوان (
fps=1/6) و متن زیرنویس روی تصویر را با cueها چک کن. - چند بخش کوتاه جدا (
ffmpeg -ss) را STT بزن و با زمان cue تطبیق بده؛ اگر جابهجایی > ۲ ثانیه بود زمانها را اصلاح کن.
نکات عملی
ffmpeg/ffprobeهمیشه هستند؛whisperمحلی نصب نیست.- اسکریپت را با
python3 - <<'PY'اجرا کن؛ برای payloadهای بزرگ-d @file.jsonبده نه argv. - زمان هر فراخوانی را محدود کن (
-m 60)؛ timeout محیط حدود ۱۷۵ ثانیه است → فراخوانیها را قطعهقطعه کن. - نام فایل نهایی: کنار ویدیو با پسوند
.srt.
فایلهای خروجی قابل استفاده در Premiere:
| فایل | کاربرد |
|---|---|
video.srt | زیرنویس — مستقیم File → Import یا درگ به تایملاین |
video.mp4.pst/chunks.json | کش STT (برای fix دستی بعدی) |
video.mp4.pst/full.json | متن کامل مرجع |