קיבלת תמלול ממערכת ASR, אבל הפלט הוא טקסט גולמי ללא חותמות זמן. לתזמן ידנית וידאו של שעה? זה לוקח יותר זמן מהעריכה עצמה. והלקוח דורש SRT ל-YouTube, אבל אתה מספק TXT. מוכר? אנחנו הופכים את השגרה הזו לאוטומטית: ממירים כל תמלול לכתוביות SRT או VTT סטנדרטיות עם תזמון אופטימלי. ללא תיקונים ידניים. הטכנולוגיה שלנו: Faster-Whisper large-v3, מסנן VAD, עיבוד שלאחר עם אילוצי משך. שגיאת סנכרון — לא יותר מ-±0.2 שניות. יצירה אוטומטית של כתוביות SRT ו-VTT מפחיתה עלויות פי 3-5 בהשוואה לסימון ידני. צור קשר לבדיקה על הקובץ שלך.
אילו בעיות אנחנו פותרים
בעיה 1: אי-תאימות פורמטים
SRT ו-VTT הם תקנים שונים: SRT משתמש בפסיק כמפריד אלפיות שנייה (00:01:15,400), VTT משתמש בנקודה (00:01:15.400). בנוסף, VTT דורש כותרת WEBVTT ותומך במיקום. שגיאת פורמט — כתוביות לא יוצגו. הקוד שלנו מטפל בניואנסים אלה אוטומטית.
בעיה 2: כתוביות ארוכות ושינויים מהירים מדי
כתוביות ארוכות מ-42 תווים קשות לקריאה, וקטעים קצרים מ-1.2 שניות בלתי קריאים. המודל עשוי להפיק קטע של 0.5 שניות — אנחנו ממזגים אותם עם קטעים שכנים או אוכפים משך מינימלי.
בעיה 3: חוסר אופטימיזציה לשידור
הסטנדרטים שלנו: מקסימום 7 שניות לכתובית, חלוקה לפי משמעות, לא יותר משתי שורות. בשלב העיבוד שלאחר optimize_subtitles, אנחנו חותכים אוטומטית שורות ארוכות ומתאימים תזמון.
יצירה אוטומטית של כתוביות SRT ו-VTT: איך זה עובד
אנחנו משתמשים ב-faster-whisper (פיצול של Whisper של OpenAI), שרץ פי 4 מהר יותר מהמקור על CUDA. מודל large-v3 משיג שיעור שגיאות מילים של 5-7% לרוסית.
from faster_whisper import WhisperModel
from datetime import timedelta
model = WhisperModel("large-v3", device="cuda")
def format_time_srt(seconds: float) -> str:
td = timedelta(seconds=seconds)
total_seconds = int(td.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
secs = total_seconds % 60
milliseconds = int((seconds % 1) * 1000)
return f"{hours:02d}:{minutes:02d}:{secs:02d},{milliseconds:03d}"
def format_time_vtt(seconds: float) -> str:
# VTT использует точку вместо запятой
return format_time_srt(seconds).replace(",", ".")
def generate_srt(audio_path: str, language: str = "ru") -> str:
segments, _ = model.transcribe(
audio_path,
language=language,
vad_filter=True
)
lines = []
for i, seg in enumerate(segments, 1):
start = format_time_srt(seg.start)
end = format_time_srt(seg.end)
text = seg.text.strip()
lines.append(f"{i}\n{start} --> {end}\n{text}\n")
return "\n".join(lines)
def generate_vtt(audio_path: str, language: str = "ru") -> str:
segments, _ = model.transcribe(
audio_path,
language=language,
vad_filter=True
)
lines = ["WEBVTT\n"]
for seg in segments:
start = format_time_vtt(seg.start)
end = format_time_vtt(seg.end)
text = seg.text.strip()
lines.append(f"{start} --> {end}\n{text}\n")
return "\n".join(lines)
למה אנחנו משתמשים ב-Whisper large-v3?
בהשוואה למודל הבסיס, large-v3 נותן שיעור שגיאות מילים נמוך ב-30% על הקלטות רועשות. אנחנו גם מיישמים from faster_whisper import WhisperModel from datetime import timedelta model = WhisperModel("large-v3", device="cuda") def format_time_srt(seconds: float) -> str: td = timedelta(seconds=seconds) total_seconds = int(td.total_seconds()) hours = total_seconds // 3600 minutes = (total_seconds % 3600) // 60 secs = total_seconds % 60 milliseconds = int((seconds % 1) * 1000) return f"{hours:02d}:{minutes:02d}:{secs:02d},{milliseconds:03d}" def format_time_vtt(seconds: float) -> str: # VTT использует точку вместо запятой return format_time_srt(seconds).replace(",", ".") def generate_srt(audio_path: str, language: str = "ru") -> str: segments, _ = model.transcribe( audio_path, language=language, vad_filter=True ) lines = [] for i, seg in enumerate(segments, 1): start = format_time_srt(seg.start) end = format_time_srt(seg.end) text = seg.text.strip() lines.append(f"{i}\n{start} --> {end}\n{text}\n") return "\n".join(lines) def generate_vtt(audio_path: str, language: str = "ru") -> str: segments, _ = model.transcribe( audio_path, language=language, vad_filter=True ) lines = ["WEBVTT\n"] for seg in segments: start = format_time_vtt(seg.start) end = format_time_vtt(seg.end) text = seg.text.strip() lines.append(f"{start} --> {end}\n{text}\n") return "\n".join(lines) — מסנן זיהוי פעילות קולית שמסיר שקט ורעש. זה מפחית כתוביות ריקות ומשפר את התזמון.
| מודל | WER (רוסית) | מהירות (RTF על A100) | גודל |
|---|---|---|---|
| Whisper base | ~12% | 0.05 | 160 MB |
| Whisper large-v3 | ~6% | 0.12 | 3 GB |
| Faster-Whisper large-v3 | ~6% | 0.03 | 3 GB |
Faster-Whisper משתמש בסביבת הריצה CTranslate2 — הסקת GPU מהירה פי 4. עבור ייצור זה קריטי: עיבוד שידור של שעה ב-2 דקות במקום 8.
איך אנחנו מייעלים כתוביות לשידור
לאחר היצירה, אנחנו מיישמים עיבוד שלאחר:
- אורך שורה מקסימלי — 42 תווים (תקן טלוויזיה).
- משך כתובית מקסימלי — 7 שניות (קריאות).
- משך מינימלי — 1.2 שניות (למניעת הבהובים).
- חלוקה בהפסקות טבעיות — אנחנו מחפשים רווח, לא רק חותכים לפי מונה.
def optimize_subtitles(segments: list, max_line_length: int = 42, max_duration: float = 7.0, min_duration: float = 1.2) -> list:
"""Оптимизируем субтитры под стандарты вещания"""
optimized = []
for seg in segments:
duration = seg.end - seg.start
text = seg.text.strip()
# Ограничиваем длину строки
if len(text) > max_line_length:
mid = text.rfind(" ", 0, max_line_length)
text = text[:mid] + "\n" + text[mid+1:]
# Минимальная длительность
end = max(seg.end, seg.start + min_duration)
optimized.append({**seg.__dict__, "text": text, "end": end})
return optimizedעבור VTT, אנחנו גם מוסיפים מיקום: vad_filter=True — כתוביות מוצגות במרכז התחתון. ניתן להקצות סגנונות שונים לדוברים שונים.
מה זה max_duration ולמה 7 שניות?
לפי מחקרי קריאות, כתוביות ארוכות מ-7 שניות גורמות לאי-נוחות לצופה. אם Whisper מפיק קטע של 10 שניות, אנחנו מפצלים אותו לפי הפסקות. אם אין הפסקות, אנחנו מחלקים לפי תווים באופן שווה.
התקן WebVTT מגדיר חוקים בסיסיים, אבל אנחנו מוסיפים היוריסטיקות לתפיסה אופטימלית.
תהליך העבודה
- ניתוח: אתה שולח דוגמת אודיו/וידאו — אנחנו מעריכים איכות הקלטה, נוכחות רעש, מספר דוברים.
- עיצוב: בחירת מודל (Whisper, Wav2Vec2, או מותאם אישית), הגדרת VAD, קביעת פורמט פלט (SRT/VTT), צורך בעיצוב.
- יישום: כתיבת סקריפט או REST API. כיסוי הקוד בבדיקות. שימוש ב-Docker לבידוד תלויות.
- בדיקות: הרצה על 10-15 קבצים, השוואת תזמון עם ייחוס. שגיאת תזמון לא יותר מ-±0.2 שניות.
- פריסה: פריסה על השרת שלך או בענן (AWS/GCP). מתן תיעוד והדרכת מפעילים.
| שלב | מה אנחנו עושים | תוצר |
|---|---|---|
| ניתוח | הערכת רצועת האודיו, בחירת אסטרטגיה | מפרט טכני |
| פיתוח | כתיבת קוד, אינטגרציה | סקריפט/API, תמונת Docker |
| בדיקות | בדיקת דיוק וביצועים | דוח בדיקות |
| פריסה | פריסה, מסירת גישה | תיעוד, הדרכה |
מה כלול
- קוד מקור של סקריפטים ליצירת SRT/VTT (Python).
- REST API (FastAPI) עם נקודות קצה להעלאת אודיו ולהורדת כתוביות.
- מכל Docker עם כל התלויות (CUDA, Whisper, FFmpeg).
- תיעוד פריסה ותפעול.
- הדרכה למהנדסים שלך על שימוש במערכת.
- 30 ימי תמיכה לאחר המסירה.
דוגמת פקודת ffmpeg לחילוץ אודיו מווידאו
```bash ffmpeg -i video.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 audio.wav ```לוח זמנים ועלות
יצירת סקריפט — מיום אחד. שירות REST API — 2 עד 3 ימים. העלות המדויקת מחושבת לאחר ניתוח הנתונים והדרישות שלך. כתוב לנו — נעריך את הפרויקט שלך. אוטומציה מפחיתה עלויות כתוביות פי 3-5 בהשוואה לסימון ידני.
טעויות נפוצות ביצירה אוטומטית של כתוביות
- השבתת מסנן VAD — רעשי רקע והפסקות נכנסים לכתוביות כמחרוזות ריקות.
- משך קטע שגוי — ללא עיבוד שלאחר, כתוביות קצרות מדי (<1 שנייה) שאי אפשר לקרוא.
- התעלמות מקידודים אזוריים — SRT על Windows דורש UTF-8 עם BOM, אחרת גיבוב תווים.
סיכום
יצירה אוטומטית של כתוביות חוסכת לך שבועות של סימון ידני. אנחנו משתמשים במודלי ASR מודרניים עם פרמטרי תזמון מכוונים. אחריות לדיוק סנכרון ועמידה בתקני שידור. למהנדסים שלנו יש ניסיון של למעלה מ-5 שנים ב-NLP ו-MLOps. קבל ייעוץ: כתוב לנו — נציג הדגמה על הקובץ שלך. צור קשר, ותעריך את החיסכון בזמן ובתקציב.







