ZWID_Pierwszy film AI za darmo - 5 kredytów na start, potem od 3 zł. Bez abonamentu.1. film za 0 złZrób film →
✨ Świeża dostawa•nowe kody na kinetyka.pl: Gemini Pro 18 mies. 170 zł•Cursor, ElevenLabs, Lovable i więcej, roczne plany AI w ułamku ceny Zobacz →
Przejdź do treści
Artykuły

Napisy do filmu za darmo: Whisper lokalnie, skrypt i Subtitle Edit

Generator napisów na własnym komputerze: Whisper large-v3 i turbo na 42-minutowym „Latarniku”, 3,3-4,0% błędnych słów, gotowy skrypt napisy.py, klatka i wideo z wynikiem oraz Subtitle Edit dla tych, którzy wolą okienka.

13 min czytania
Napis Napisy do filmu za darmo - Whisper na własnym komputerze: 42 min w 53 s

👁 118 przeczytań

// w skrócie
  • Model Whisper large-v3-turbo zrobił napisy z 42-minutowego "Latarnika" w 53 s z błędem 4,0%, a large-v3 w 173 s z błędem 3,3%.
  • Pułapka instalacyjna: biblioteka PyAV 19 (od 29 września 2026) nie działa z faster-whisper 1.2.1, dlatego trzeba instalować wersję av
  • Whisper automatycznie uwspółcześnia XIX-wieczną polszczyznę, zamieniając np. "tedy" na "wtedy", a liczby słowne na cyfry, co wymaga ręcznej korekty.

Napisy do filmu zrobisz za darmo i bez wysyłania nagrania w sieć: model Whisper rozpozna mowę na Twoim komputerze, a krótki skrypt podzieli tekst na napisy i zapisze plik SRT. Sprawdziłem to na 42-minutowym audiobooku „Latarnika” z Wolnych Lektur: na karcie RTX 4090 model large-v3-turbo zrobił napisy w 53 s z 4,0% błędnych słów, a dokładniejszy large-v3 w 173 s z 3,3% błędów. Poniżej gotowy skrypt, wynik na klatce i wideo oraz lista rzeczy, które i tak trzeba poprawić ręcznie. To część serii o lokalnym AI.

Stan na 17 października 2026

  • Silnik: faster-whisper 1.2.1 (MIT) z modelami Whisper large-v3 i large-v3-turbo (MIT, także komercyjnie). Działa offline po jednorazowym pobraniu modelu (1,6-3 GB).
  • Pułapka: biblioteka PyAV 19 (od 29 września 2026) nie działa z faster-whisper 1.2.1, instaluj "av<19".
  • Bez wiersza poleceń: Subtitle Edit 5.3.0 (14 października 2026, darmowy, MIT) ma wbudowane rozpoznawanie mowy Whisperem.
  • Mój test: 3 i 17 października 2026, 41 min 47 s prozy czytanej przez lektora, dwa modele, czas, pamięć karty i zgodność słów z tekstem książki.
  • Skrypt napisy.py (MIT) dzieli tekst według zasad telewizyjnych: do 42 znaków w wierszu, maks. 2 wiersze, 1-6 s na napis.
53 snapisy do 42 min nagrania (large-v3-turbo, RTX 4090)
3,3%błędnych słów w najlepszym modelu (large-v3)
607napisów SRT z jednego audiobooka
0 złi nagranie nie opuszcza komputera

Czym różnią się napisy od transkrypcji

Transkrypcja to ciągły tekst. Napisy to ten sam tekst pocięty na kawałki z czasem wyświetlania, w formacie, który rozumie odtwarzacz albo serwis (SRT, VTT). Whisper sam podaje czas fragmentów, ale jego fragmenty bywają za długie na ekran: mają po 20-30 słów i po kilkanaście sekund. Dlatego skrypt korzysta z czasu każdego słowa i składa napisy od nowa. O samej transkrypcji i wyborze modelu pisałem w tekście Whisper, a darmowe usługi online porównałem w zestawieniu transkrypcja po polsku za darmo.

Najprościej: Subtitle Edit z Whisperem

Jeśli nie chcesz pracować w wierszu poleceń, darmowy edytor Subtitle Edit (Windows, macOS, Linux) działa jak generator napisów: w menu Video → Speech to text wybierasz silnik, język i model, a program sam pobiera to, czego potrzebuje. Według dokumentacji obsługuje m.in. silniki Whisper CPP, Purfview Faster Whisper XXL, Whisper CTranslate2, Whisper Const-me i WhisperX, z kartą Nvidii albo na procesorze, także seriami plików. Gotowe napisy od razu poprawiasz w tym samym oknie, z podglądem wideo. Tę drogę opisuję według dokumentacji, w moim teście używałem skryptu poniżej, bo daje pełną kontrolę nad podziałem napisów.

Jak zrobić napisy skryptem: krok po kroku

  1. Zainstaluj Pythona 3.12 lub 3.13 z python.org (zaznacz „Add to PATH”) i ffmpeg: winget install Gyan.FFmpeg.
  2. W wierszu poleceń: pip install faster-whisper "av<19". Na karcie Nvidii doinstaluj biblioteki CUDA: pip install nvidia-cublas-cu12 nvidia-cudnn-cu12 (skrypt sam je znajdzie, podobnie jak biblioteki PyTorcha, jeśli go masz).
  3. Zapisz skrypt napisy.py (pełny kod niżej) w folderze z filmem.
  4. Uruchom: python napisy.py film.mp4. Obok filmu pojawi się film.srt. Szybszy model: --model large-v3-turbo.
  5. Nazwiska i trudne słowa podpowiedz modelowi: --slowa "Skawiński, Falconbridge".
  6. Chcesz napisy na stałe w obrazie (np. do rolek)? Dodaj --wypal, a skrypt zrobi film_napisy.mp4.
  7. Przejrzyj SRT w edytorze napisów (np. Subtitle Edit) i popraw to, co opisuję w sekcji o błędach.

Bez karty graficznej dodaj --cpu: model działa wtedy na procesorze w trybie int8, wyraźnie wolniej (liczby w pytaniach na końcu).

Mój test: „Latarnik” z Wolnych Lektur

Nagranie: Henryk Sienkiewicz, „Latarnik”, czyta Jan Peszek, 41 min 47 s, MP3 64 kb/s, Wolne Lektury (tekst w domenie publicznej, nagranie na licencji CC BY-SA 3.0). Wzorcem był tekst książki z tej samej strony, 4695 słów. Ustawienia: język polski, beam 5, VAD włączony, condition_on_previous_text=False, czasy słów włączone, podpowiedź z czterema nazwami własnymi. Pełne przebiegi powtórzyłem 17 października; zgodność słów wyszła identyczna jak 3 października.

large-v3-turbolarge-v3
Błędne słowa (WER)4,0% (189)3,3% (155)
Rozpoznanie 41,8 min (17.10)53 s173 s
Czyste 10 min (3.10)8,0 s27,7 s
Pamięć karty2,2-2,7 GB4,1-4,6 GB
Napisów w pliku SRT610607
Napisy szybsze niż 17 znaków/s3216

Co z tego wynika:

  • Turbo jest ok. 3 razy szybszy i myli się tylko trochę częściej. Do większości filmów to rozsądny wybór, a godzina nagrania to ok. 1,3 minuty czekania.
  • large-v3 wygrywa tam, gdzie liczy się kompletność. Ma mniej błędów, mniej za szybkich napisów i nie zgubił fragmentu, który turbo pominął (opis niżej).
  • Czasy wahają się między przebiegami. 3 października pełny przebieg turbo trwał 34 s, 17 października 53 s, bo na komputerze działały wtedy inne zadania. Pomiar 10 minut z 3 października robiłem bez innych obciążeń.
  • Dysk ma znaczenie przy pierwszym uruchomieniu. Wczytanie large-v3 z wolnego dysku USB trwało 76 s, z dysku NVMe 3,0 s.
  • Format się zgadza: średnio 3,8-3,9 s na napis, 12,8-13,3 znaku na sekundę, tylko 2 wiersze na ponad 600 napisów przekroczyły 42 znaki (o 2 znaki).

Jak wygląda wynik

Fragment pliku SRT z modelu large-v3 (minuta 3:49):

57
00:03:49,880 --> 00:03:54,100
ale sądząc z niebieskich oczu
nie należał do ludzi południa.

58
00:03:54,100 --> 00:03:58,060
Twarz jego była przygnębiona
i smutna, ale uczciwa.

59
00:03:58,440 --> 00:04:01,700
Na pierwszy rzut oka podobał
się Falcon Bridge 'owi.

60
00:04:02,640 --> 00:04:08,000
Pozostało go tylko wyegzaminować, wskutek
czego wywiązała się następująca rozmowa.

61
00:04:08,000 --> 00:04:10,000
- Skąd jesteście?

Ten sam fragment puściłem jako film: tło to 5-sekundowy klip latarni w burzy, który wygenerowałem lokalnie modelem Kandinsky 6 Lite, pod nim nagranie, a napisy wypalił skrypt z opcją --wypal (model turbo).

Klatka z napisami wygenerowanymi przez Whisper: latarnia w burzy, fragment Latarnika
Klatka z filmu z wypalonymi napisami: Arial 22, obrys 2 px, dwa wiersze.
43 s „Latarnika” z napisami zrobionymi lokalnie, 17 października 2026.

Na krótkim fragmencie turbo zapisał „Falconbridgeowi” poprawnie, ale połączył w jeden napis dwie kwestie różnych osób („Jestem Polak. Coście robili dotąd?”) i zgubił myślniki dialogowe. Przy rozmowach to częsty kłopot: Whisper nie wie, kto mówi.

Czego Whisper nie zrobi za Ciebie

Porównałem oba pliki SRT słowo po słowie z tekstem książki. Błędy układają się w kilka powtarzalnych grup:

  • Obce nazwy własne, mimo podpowiedzi. „Falconbridge” large-v3 rozbił na „Falcon Bridge” we wszystkich 6 miejscach, turbo w 3. „Aspinwall” oba modele zapisały 9 razy jako „Espinwall”. Polskie nazwisko Skawiński wyszło bezbłędnie we wszystkich 18 wystąpieniach.
  • Liczby zamieniane na cyfry. „Dwunastu” staje się „12”, „czterysta” - „400”. Gorzej z „w czterdziestym dziewiątym” (chodzi o 1849 rok): turbo wpisał „W 1949 roku”.
  • Uwspółcześnianie języka. Whisper poprawia XIX-wieczną polszczyznę: „tedy” na „wtedy”, „człekiem” na „człowiekiem”. W wywiadzie to zaleta, przy literaturze trzeba to cofnąć.
  • Pominięte fragmenty. Turbo w ogóle nie zapisał inwokacji z „Pana Tadeusza” („Panno święta, co jasnej bronisz Częstochowy…”), którą czyta bohater, large-v3 zapisał ją poprawnie. Dziura w napisach to najgorszy rodzaj błędu, bo nie widać jej w pliku, tylko przy oglądaniu.
  • Zlepione i rozklejone słowa: „mewy kryły” jako „me wykryły” (turbo), „podzwrotnikowym” jako „pod zwrotnikowym”.
  • Za szybkie napisy. Przy szybszej narracji kilka procent napisów przekracza 17 znaków na sekundę, czyli tempo, w którym widz nie nadąża czytać.

Praktyczna rada: przed eksportem przeszukaj plik pod kątem nazw własnych i cyfr. W Subtitle Edit zajmuje to kilka minut na godzinę materiału.

Gotowy skrypt: napisy.py

Skrypt sprawdziłem 3 i 17 października 2026 na Windows 11 z faster-whisper 1.2.1 i RTX 4090; wynik testu powyżej pochodzi właśnie z niego. 17 października uruchomiłem go też w czystym folderze, w nowym środowisku Pythona 3.13 z pakietami z pip: na karcie i na procesorze. Zanim uruchomisz kod z internetu, przeczytaj go. Licencja MIT, możesz go zmieniać i używać w firmie. Pobierz napisy.py.

"""
napisy.py - napisy SRT po polsku z dowolnego nagrania lub filmu, lokalnie (faster-whisper).
Autor: Piotr Olszewski, promptowy.com. Licencja: MIT. Sprawdzone 3.10 i 17.10.2026: faster-whisper 1.2.1, Python 3.13, RTX 4090, Windows 11.

Instalacja (raz):
  pip install faster-whisper "av<19"                     (PyAV 19 z 29.09.2026 psuje faster-whisper 1.2.1)
  pip install nvidia-cublas-cu12 nvidia-cudnn-cu12       (tylko karta Nvidia)
  winget install Gyan.FFmpeg                             (tylko do --wypal)

Użycie:
  python napisy.py film.mp4                      -> film.srt obok pliku
  python napisy.py film.mp4 --model large-v3-turbo
  python napisy.py film.mp4 --wypal              -> dodatkowo film_napisy.mp4 z napisami na obrazie (ffmpeg)
  python napisy.py film.mp4 --cpu                -> bez karty graficznej (wolniej, model int8)

Zasady podziału (jak w telewizji i na Netfliksie): maks. 42 znaki w wierszu, maks. 2 wiersze,
napis od 1 do 6 sekund, cięcie najchętniej po kropce, przecinku albo przed spójnikiem.
"""
import argparse, os, sys, subprocess, time, json

ZN_W_WIERSZU, MAX_WIERSZY, MAX_CZAS, MIN_CZAS = 42, 2, 6.0, 1.0
SPOJNIKI = {'i', 'a', 'ale', 'że', 'bo', 'lecz', 'oraz', 'albo', 'czy', 'gdy', 'kiedy', 'który', 'która', 'które', 'więc', 'jednak'}

def cuda_dll():
    # Na Windowsie faster-whisper potrzebuje cuBLAS i cuDNN. Szukamy ich w pakietach pip nvidia-*-cu12
    # (pip install nvidia-cublas-cu12 nvidia-cudnn-cu12) albo w bibliotekach PyTorcha, jeśli jest zainstalowany.
    import glob, site
    katalogi = []
    for sp in site.getsitepackages() + [site.getusersitepackages()]:
        katalogi += glob.glob(os.path.join(sp, 'nvidia', '*', 'bin'))
        katalogi += glob.glob(os.path.join(sp, 'torch', 'lib'))
    for lib in katalogi:
        if os.path.isdir(lib):
            try:
                os.add_dll_directory(lib)
            except (OSError, AttributeError):
                pass
            os.environ['PATH'] = lib + os.pathsep + os.environ['PATH']

def t_srt(t):
    ms = int(round(t * 1000)); g, ms = divmod(ms, 3600000); m, ms = divmod(ms, 60000); s, ms = divmod(ms, 1000)
    return f'{g:02d}:{m:02d}:{s:02d},{ms:03d}'

def zawin(slowa):
    """Dzieli listę słów na maks. 2 wiersze, najlepiej w połowie i nie przed krótkim słowem."""
    tekst = ' '.join(slowa)
    if len(tekst) <= ZN_W_WIERSZU: return tekst
    best, bi = 1e9, 1
    for i in range(1, len(slowa)):
        a, b = ' '.join(slowa[:i]), ' '.join(slowa[i:])
        # wiersz dłuższy niż 42 znaki to duża kara, ale nie wykluczenie (inaczej przy długim słowie podział się psuje)
        kara = 1000 * max(0, max(len(a), len(b)) - ZN_W_WIERSZU) + abs(len(a) - len(b)) + (15 if len(slowa[i-1]) <= 2 else 0) - (10 if slowa[i-1][-1] in ',.;:?!' else 0)
        if kara < best: best, bi = kara, i
    return ' '.join(slowa[:bi]) + '\n' + ' '.join(slowa[bi:])

def bloki(words):
    """Grupuje słowa (z czasami) w napisy."""
    out, cur = [], []
    def zamknij():
        if cur: out.append([cur[0][0], cur[-1][1], [w for _, _, w in cur]]); cur.clear()
    for (a, b, w) in words:
        if cur:
            tekst = ' '.join(x[2] for x in cur + [(a, b, w)])
            za_dlugo = len(tekst) > ZN_W_WIERSZU * MAX_WIERSZY - 6 or (b - cur[0][0]) > MAX_CZAS
            pauza = a - cur[-1][1] > 0.8
            if za_dlugo or pauza:
                # cofnij się do ostatniego dobrego miejsca cięcia (interpunkcja albo przed spójnikiem)
                cut = None
                for j in range(len(cur) - 1, 0, -1):
                    if cur[j-1][2][-1] in ',.;:?!' or cur[j][2].lower().strip(',.') in SPOJNIKI:
                        cut = j; break
                if za_dlugo and cut and cut >= len(cur) // 2:
                    reszta = cur[cut:]; del cur[cut:]; zamknij(); cur.extend(reszta)
                else:
                    zamknij()
        cur.append((a, b, w))
        if w[-1] in '.?!' and (cur[-1][1] - cur[0][0]) >= 1.5:
            zamknij()
    zamknij()
    # minimalny czas wyświetlania, bez nachodzenia na następny napis
    for i, n in enumerate(out):
        if n[1] - n[0] < MIN_CZAS:
            nast = out[i+1][0] - 0.05 if i + 1 < len(out) else n[0] + MIN_CZAS
            n[1] = max(n[1], min(n[0] + MIN_CZAS, nast))
    return out

def main():
    ap = argparse.ArgumentParser(description='Napisy SRT po polsku lokalnie (faster-whisper)')
    ap.add_argument('plik'); ap.add_argument('--model', default='large-v3')
    ap.add_argument('--jezyk', default='pl'); ap.add_argument('--cpu', action='store_true')
    ap.add_argument('--wypal', action='store_true', help='wypal napisy w obraz (wymaga ffmpeg)')
    ap.add_argument('--slowa', default='', help='podpowiedź: nazwiska i trudne słowa, np. "Falconbridge, Skawiński"')
    x = ap.parse_args()
    if not x.cpu: cuda_dll()
    from faster_whisper import WhisperModel
    t0 = time.time()
    m = WhisperModel(x.model, device='cpu' if x.cpu else 'cuda', compute_type='int8' if x.cpu else 'float16')
    t1 = time.time()
    segs, info = m.transcribe(x.plik, language=x.jezyk, beam_size=5, vad_filter=True, word_timestamps=True,
                              condition_on_previous_text=False, initial_prompt=x.slowa or None)
    words = []
    for s in segs:
        for i, w in enumerate(s.words):
            t = w.word.strip()
            if not t: continue
            if words and i > 0 and not w.word.startswith(' '):
                # kawałek bez spacji (np. „.pl”, „-go”) doklejamy do poprzedniego słowa
                a, _, p = words[-1]; words[-1] = (a, w.end, p + t)
            else:
                words.append((w.start, w.end, t))
    t2 = time.time()
    nap = bloki(words)
    srt = os.path.splitext(x.plik)[0] + '.srt'
    with open(srt, 'w', encoding='utf-8') as f:
        for i, (a, b, sl) in enumerate(nap, 1):
            f.write(f'{i}\n{t_srt(a)} --> {t_srt(b)}\n{zawin(sl)}\n\n')
    print(f'Gotowe: {srt} | {len(nap)} napisów | nagranie {info.duration/60:.1f} min | model {x.model} '
          f'wczytany w {t1-t0:.0f} s | rozpoznawanie {t2-t1:.0f} s')
    if x.wypal:
        wyj = os.path.splitext(x.plik)[0] + '_napisy.mp4'
        styl = 'FontName=Arial,FontSize=22,Outline=2,Shadow=0,MarginV=40'
        sciezka = srt.replace(os.sep, '/').replace(':', r'\:')  # ścieżka w formacie filtra ffmpeg
        subprocess.run(['ffmpeg', '-y', '-loglevel', 'error', '-i', x.plik, '-vf', f"subtitles='{sciezka}':force_style='{styl}'",
                        '-c:a', 'copy', wyj], check=True)
        print('Film z napisami:', wyj)

if __name__ == '__main__':
    main()

Lokalnie czy w usłudze online

Nie przepłacaj za te subskrypcje

Prowadzę sklep z rocznymi dostępami do narzędzi AI - te same konta, o których piszę wyżej, tylko taniej niż w cenniku producenta.

Zobacz, co jest dostępne

Whisper lokalnieUsługi online
Koszt0 zł, tylko prąddarmowe limity, potem abonament
Prywatnośćnagranie zostaje na komputerzeplik idzie na serwer
Limit długościbrakzwykle minuty na plik lub dzień
Wygodainstalacja lub Subtitle Editprzeciągnij plik w przeglądarce

Szybsze w obsłudze są narzędzia z montażem w jednym, np. CapCut. Lokalny Whisper wygrywa przy długich nagraniach, materiałach poufnych i dużej liczbie plików. Cały proces poprawiania napisów opisałem w tekście AI do napisów, a lektora do tego samego filmu zrobisz lokalnie według poradnika syntezator mowy. Obraz i wideo wygenerujesz u siebie w Hangarze (moje narzędzie; napisów ani Whispera w nim nie ma).

Najczęstsze pytania

Jak zrobić napisy do filmu za darmo?

Lokalnie: Whisper przez skrypt z tego tekstu albo program Subtitle Edit z wbudowanym rozpoznawaniem mowy. Online: automatyczne napisy YouTube albo darmowe limity usług. Lokalna droga nie ma limitów i nie wysyła pliku w sieć.

Jaki generator napisów wybrać i który model Whisper?

Do większości filmów large-v3-turbo: w moim teście 4,0% błędnych słów i ok. 3 razy szybciej niż large-v3. Gdy liczy się każde zdanie (literatura, dokument, wywiad do publikacji), weź large-v3: 3,3% błędów i nic nie pominął. Mniejsze modele (small, medium) mają sens tylko na słabym sprzęcie.

Czy Subtitle Edit robi automatyczne napisy?

Tak. Subtitle Edit (wersja 5.3.0 z 14 października 2026, za darmo) ma funkcję rozpoznawania mowy w menu Video, z silnikami opartymi na Whisperze. Modele pobiera sam przy pierwszym użyciu, a wynik od razu ląduje w edytorze z podglądem wideo.

Jak dodać napisy SRT do filmu?

Na YouTube wgrywasz SRT w zakładce Napisy. Do odtwarzacza (VLC, MPC) wystarczy, że plik SRT ma tę samą nazwę co film. Na stałe w obrazie wypalisz je ffmpegiem (opcja --wypal w skrypcie).

Czy Whisper działa bez karty graficznej?

Tak, ale wolno. W czystym folderze na procesorze i9-14900KF large-v3-turbo w trybie int8 rozpoznał 30 s nagrania w 23 s, więc godzina materiału to ok. 45-50 minut. Na karcie RTX 4090 ten sam fragment zajął 4 s.

Czy Whisper rozpoznaje, kto mówi?

Nie. Przy rozmowie kilku osób dostaniesz napisy bez oznaczenia mówców, a czasem dwie kwestie w jednym napisie. Do tego potrzebna jest nakładka z diaryzacją, np. WhisperX (dostępny też w Subtitle Edit).

Ile trwa zrobienie napisów do godzinnego filmu?

Na RTX 4090 w moim teście 17 października: ok. 1,3 minuty z large-v3-turbo i ok. 4 minuty z large-v3, do tego kilka sekund na wczytanie modelu. Najwięcej czasu zajmuje i tak poprawianie: nazw własnych, liczb i pominiętych fragmentów.

Google · Twoje źródłaPromptowy wyżej w Twoim Google - jednym kliknięciemDodaj do preferowanych źródeł →

Źródła i data sprawdzenia

Sprawdzone 17 października 2026.

// Newsletter

Cały tydzień w AI, w jednym mailu

Wybrane premiery, narzędzia i analizy. Raz w tygodniu, prosto do skrzynki.

Zapisz się za darmo →
Za darmo. Wypisujesz się jednym kliknięciem.
// czytaj też

Podobne tematy na Promptowym

Piotr Olszewski

Piotr Olszewski

AUTOR I WYDAWCA

Piotr Olszewski - twórca i autor Promptowego, polskiego serwisu o sztucznej inteligencji. Codziennie śledzi premiery modeli, narzędzia i regulacje AI, i tłumaczy je prostym, konkretnym językiem.

// mapa strony

🛒 Sklep Kinetyka Google AI Gemini Pro 170 zł CapCut Pro 460 zł/rok Lovable Pro 450 zł/rok Zobacz wszystko →
promptowy w liczbach 0tekstów w archiwum0newsów z ostatnich 7 dni0modeli wideo w obserwatorium0zagadek w grach
× ‹ powiększenie ›