Communitygithub.com

peditx/persian-sub-tizone-skill

Persian SRT from video/audio: ffmpeg extract → 9Router STT → overlapping-block align → polished فارسی .srt. Brand-new 2026-09-26.

persian-sub-tizone-skill란 무엇인가요?

persian-sub-tizone-skill is a Claude Code agent skill that persian SRT from video/audio: ffmpeg extract → 9Router STT → overlapping-block align → polished فارسی .srt. Brand-new 2026-09-26.

지원 대상✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add peditx/persian-sub-tizone-skill

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

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متن کامل مرجع

관련 스킬