Dostępnik o generatorze audiodeskrypcji
Kilka lat temu mówiłem, że to nie będzie możliwe. Dzisiaj zbudowałem aplikację generującą audiodeskrypcję. Nie jest doskonała, ale działa. Przedstawiam AD Creator.
Zbudowałem narzędzie do automatycznej audiodeskrypcji. Zajęło mi to jeden dzień. Nie dlatego że jestem geniuszem programowania — bo nie jestem — ale dlatego że miałem do dyspozycji Claude Code i GitHub Copilot. I to jest właśnie temat tego numeru: co się dzieje, gdy używasz AI do budowania narzędzia dostępnościowego? Spoiler: nie jest różowo. Ale jest interesująco.
Dlaczego w ogóle to robiłem
Audiodeskrypcja to narracja dźwiękowa opisująca to, co dzieje się na ekranie — dla osób niewidomych i słabowidzących. Problem polega na tym, że tworzenie AD jest drogie i czasochłonne. Profesjonalny audiodeskryptor musi obejrzeć film, znaleźć przerwy między dialogami, napisać opisy, nagrać je, a potem zmontować z oryginalną ścieżką dźwiękową.
Inspiracją była dla mnie prezentacja Rafała Charłampowicza podczas 3 Forum bez barier, gdzie pokazywał jak wygląda proces tworzenia AD z wykorzystaniem AI. Rafał opisał to na LinkedINie, ale chciałem to zobaczyć na własne oczy. Z kolei Ania Czapnik podrzuciła mi link do filmu animowanego, w którym główna bohaterka jest głucha. W warstwie dźwiękowej jest dużo, ale mało informacji. Postanowiłem zatem użyć ten właśnie film jako testowy materiał do stworzenia audiodeskrypcji. Czy AI może to zautomatyzować? Chciałem to sprawdzić.
Architektura, którą wymyśliłem
Przepływ działania aplikacji wygląda tak:
Użytkownik podaje link do wideo (YouTube, Vimeo, dowolny plik)
Silero VAD (model neuronowy) wykrywa przerwy między dialogami
Google Gemini 2.5 analizuje wideo i generuje timestampowane opisy wizualne
Algorytm dopasowuje opisy do przerw, skracając je jeśli nie mieszczą się w czasie
Google TTS syntetyzuje mowę z każdego opisu
FFmpeg miesza audiodeskrypcję z oryginalnym wideo
Na papierze brzmi sensownie. W praktyce na każdym z tych kroków coś poszło nie tak.
Ślepa uliczka nr 1: torchaudio i biblioteka, która nie istnieje
Na początku chciałem użyć narzędzia, które wykrywa ciszę. W te miejsca mogłyby się zmieścić opisy. To był pierwszy błąd, bo w filmie prawie nie ma ciszy — jest muzyka, odgłosy tła, efekty dźwiękowe. Potrzebowałem czegoś bardziej inteligentnego. Zamieniłem zatem wykrywanie ciszy na wykrywanie mowy.
Silero VAD to model do wykrywania mowy — odróżnia, kiedy ktoś mówi, a kiedy gra muzyka lub jest cisza. Potrzebuje audio w formacie 16 kHz mono jako tensor PyTorch.
Oryginalny plan: użyć torchaudio do wczytania pliku audio i konwersji. Copilot wygenerował kod, który wyglądał poprawnie:
wav = read_audio(audio_path, sampling_rate=16_000)
Problem pojawił się przy uruchomieniu. torchaudio 2.10.0 wymaga torchcodec, który przy ładowaniu szukał biblioteki libtorchcodec — i jej nie znajdował. Błąd runtime, zero obsługi pliku.
Rozwiązanie które zaproponował Copilot po opisaniu problemu: wyrzucić torchaudio całkowicie i zrobić to FFmpegiem i soundfile. FFmpeg resampleuje audio do WAV przez stdout, soundfile dekoduje z pamięci, numpy konwertuje do tensora PyTorch.
cmd = [”ffmpeg”, “-i”, audio_path, “-ar”, “16000”, “-ac”, “1”, “-f”, “wav”, “-”]
result = subprocess.run(cmd, capture_output=True, timeout=300)
data, _ = sf.read(io.BytesIO(result.stdout), dtype=”float32”, always_2d=False)
return torch.from_numpy(data)
Brzydsze? Tak. Działa? Tak. I usuwa zależność od biblioteki, która nie ładuje się na połowie systemów.
Ślepa uliczka nr 2: dopasowywanie opisów do przerw
To był algorytmicznie najtrudniejszy moment. Pierwsza wersja kodu (Claude Code) działała tak: dla każdej przerwy w dialogu szukaj wszystkich opisów wizualnych Gemini w oknie ±5 sekund i łącz je w jeden tekst.
Logika: jedna przerwa → jeden opis → jedno nagranie TTS.
Problem: w filmach często jest długi fragment muzyczny bez dialogu. Silero VAD zgłasza to jako jedną wielką przerwę — powiedzmy 90 sekund. W tym czasie Gemini wygenerował 15 osobnych opisów. Poprzedni algorytm łączył je wszystkie w jeden blok tekstu, który za cholerę nie synchronizował się z obrazem.
Musiałem też sprawdzić, jak szybki jest język polski. Domyślnie Claude zaproponował 160 słów na minutę, ale to było za szybko. Poszukałem i znalazłem, że w standardowym języku polskim mówimy z prędkością 100-150 słów na minutę, więc krakowskim targiem ustawiłem 120. Teraz teksty łatwiej się mieściły w slotach czasowych.
Przepisałem logikę. Nowe podejście: jeden opis → jeden segment, a duże przerwy są dzielone na podzakresy. Każdy opis dostaje własny slot czasowy wyznaczony przez jego timestamp. Algorytm przesuwa “kursor” przez lukę i przydziela kolejne sloty:
slot_start = max(cursor, T - 1_000) # zacznij sekundę przed wydarzeniem wizualnym
slot_end = min(gap_end, next_T - 300) # skończ przed kolejnym opisem
To zsynchronizowało audiodeskrypcję z obrazem — opis pojawia się tuż przed zdarzeniem wizualnym, które opisuje.
Ślepa uliczka nr 3: skracanie opisu generuje słowa kluczowe
Kiedy opis Gemini jest za długi na dostępną przerwę, aplikacja prosi Gemini o skrócenie go. Pierwsza wersja promptu brzmiała mniej więcej: “skróć do X słów”. Gemini skracał — ale zamiast zdań zwracał listy słów kluczowych. “Kobieta, okno, wieczór, zamyślona.”
To jest bezużyteczne dla audiodeskrypcji, która musi być pełnym, gramatycznym zdaniem.
Poprawka była prosta, ale wymagała precyzji:
Napisz pełne, gramatyczne zdanie — nie słowa kluczowe, nie listę.
Odpowiedz TYLKO skróconym zdaniem, bez żadnych komentarzy.
Jeden akapit różnicy w prompcie. Efekt drastycznie inny.
Audiodeskrypcja jest bardzo podobna do alternatyw tekstowych, o których kilka razy pisałem w Dostępniku. Stąd wiedziałem, że bez dodatkowej wiedzy, AI będzie polegała tylko na obrazie. Dlatego dodałem jeszcze jeden element: kontekst. W tym polu można dodać kilka informacji o filmie, które AI może wykorzystać do lepszego zrozumienia, co jest ważne. Dla tego testowego filmu dodałem informację, że główna bohaterka to głucha dziewczynka, w filmie pojawiają się też mama i tata dziewczynki, a wieloryb ma na imię Blue 52. Posłuchaj efektu, jaki udało się uzyskać.
Co AI robiła dobrze, a co źle
Po dniu pracy z Claude Code i Copilot mam pewne obserwacje.
Dobrze:
· Szybkie generowanie boilerplate — Streamlit UI, dataclassy, moduły pip
· Znajdowanie alternatyw gdy coś nie działa (torchaudio → FFmpeg)
· Pisanie kodu, który “wygląda poprawnie” i jest czytelny
· Rozumienie kontekstu projektu i utrzymywanie spójności nazewnictwa
Źle:
· Nie rozumie dziedziny audiodeskrypcji — nie wie, że opis musi być przed zdarzeniem, nie po
· Generuje kod, który kompiluje się, ale logika jest błędna (pierwsze podejście do script fitting)
· Nie testuje własnych założeń — torchaudio wyglądało poprawnie do momentu uruchomienia
· Promptowanie Gemini wymagało wiedzy dziedzinowej, której AI nie posiada
To ostatnie jest kluczowe. AI świetnie implementuje to, co opisujesz. Ale musisz wiedzieć, co opisujesz. W przypadku audiodeskrypcji ta wiedza dziedzinowa — że opis idzie przed zdarzeniem, że nie może nakładać się na dialog, że trzeba gramatyczne zdania, nie słowa kluczowe — musiała przyjść ode mnie.
Technologiczny ekosystem projektu
Żeby była jasność co to za projekt od strony technicznej:
· Python + Streamlit — UI webowy uruchamiany lokalnie
· Silero VAD — lokalny model neuronowy do wykrywania mowy (PyTorch)
· Google Gemini 2.5 Flash — analiza wideo i generowanie opisów wizualnych. Klucz API dostaniesz bezpłatnie w Google AI Studio — wystarczy konto Google. Bezpłatny tier ma limity (15 zapytań na minutę), ale do testów na pojedynczych filmach w zupełności wystarczy.
· Google Gemini TTS — synteza mowy (głos “Kore”)
· yt-dlp + FFmpeg — pobieranie wideo i obróbka audio
· soundfile — dekodowanie audio bez torchaudio
Gemini 2.5 radzi sobie z analizą wideo naprawdę dobrze. Dla YouTube wystarczy podać URL — Gemini pobiera wideo natywnie. Dla innych źródeł trzeba uploadować przez File API i czekać na aktywację pliku.
Paradoks dostępności
Jest w tym coś ironicznego. Buduję narzędzie dla osób niewidomych, używając modeli AI, które generują opisy wizualne. Sam Gemini “widzi” wideo i opisuje co się na nim dzieje. Potem TTS “czyta” te opisy. Cały potok to: wzrok zamieniamy w słowa, słowa zamieniamy w mowę.
Ale AI nie rozumie kontekstu dostępności. Nie wie, że opis “kobieta patrzy przez okno” jest bezużyteczny, jeśli pojawi się w połowie zdania które ktoś właśnie mówi. To nadal wymaga człowieka który zna zasady audiodeskrypcji i potrafi ocenić output.
programowanie ze wsparciem AI sprawia, że jestem w stanie zbudować taki projekt w jeden dzień zamiast tygodnia. Ale nie sprawia, że jestem w stanie zbudować go dobrze bez wiedzy dziedzinowej.
To chyba główna lekcja z tego eksperymentu.
Co dalej z projektem
AD Creator jest na razie eksperymentem — kodem badawczym, nie gotowym produktem. Brakuje ewaluacji jakości generowanych opisów, testów na różnych typach materiałów, interfejsu dla profesjonalnych audiodeskryptorów.
Ja zresztą już znajduję błędy, które dość łatwo będzie usunąć. Efekt zaś możesz odsłuchać i ocenić, czy AI dobrze sobie radzi. A jeżeliwiesz już, co AD Creator robi źle, napisz w komentarzu lub w issues na GitHub.
Czy automatyczna audiodeskrypcja zastąpi ludzką pracę? Na pewno nie w krótkim czasie. Ale może pomóc w przypadkach, gdy człowiek i tak by jej nie zrobił — bo nie ma budżetu, czasu, albo nie ma nikogo kto by się tym zajął. W Polsce audiodeskrypcja to nadal rzadkość.
Jeśli AI może ją wygenerować na poziomie “wystarczająco dobrym”, może to wystarczy żeby film był choć trochę bardziej dostępny.
Kod projektu AD Creator jest na GitHubie: github.com/JacZad/ad-creator i możesz go przetestować na własnych filmach. Pamiętaj tylko, że potrzebujesz klucza API do Gemini i TTS, a także zainstalowanych FFmpeg i soundfile. A jeśli masz pomysły na ulepszenia, pull requesty są mile widziane!
Wieści o dostępności
Dzisiaj będzie tylko o 1 wydarzeniu - AutomaticA11y 2026. Od dzisiaj możesz zgłosić swój udział przez formularz zgłoszeniowy. Na stronie AutomaticA11y pojawiły się już pierwsze opisy prezentacji i informacje organizacyjne.
Tak dla przypomnienia
Czas: 21 maja 2026 roku w godzinach 11:00-18:00
Miejsce: Budynek S Szkoły Głównej Handlowej w Warszawie, ul. Batorego 8, aula 1 na piętrze.
Aula jest na około 130 osób, a naprzeciwko wejścia są 3 fajne boksy na stoliki tematyczne.
Już wiem o 2 osobach, których nie będzie i zamierzam wspomnieć o nich podczas otwarcia. Ludzie są najważniejsi.
Od strony SGH wspiera nas Justyna Kapturkiewicz. Pomaga poruszać się w meandrach organizacji i administracji uczelni i wciąż dopytuje, co jeszcze może zaoferować.
Ponownie moim ogromnym wsparciem jest Agata Gawska. Pomaga to wszystko ogarnąć, bo ja to raczej jestem od ekscytujących pomysłów, a z organizacją to już radzę sobie gorzej.
Już po raz 3 współorganizatorami są Fundacja Kultury bez barier i Fundacja Kinematograf. FKBB zapewnia dostępność wydarzenia, a Ania Czapnik i Janusz Olszyński wszystko nagrają. No i Agata Chmielewska, która dba o stronę konferencji!
Pamiętaj także, że podczas konferencji ludzie muszą jeść. Dlatego nadal apeluję o zrzutkę na poczęstunek, bo sporo jeszcze brakuje. Jak zawsze - możesz to zrobić przez serwis BuyCoffee.to. I nie wstydź się wpłacić więcej:)
Jeszcze prywata. Uruchomiłem swoją stronę wizytówkową. Takie tam informacje o mnie i za co chciałbym wystawiać faktury. Ale głównie to zapraszam do bloga, gdzie publikuję takie znaleziska z mojej działki. Same krótkie rzeczy, chyba że zajrzysz zbyt głęboko w starsze wpisy. Bo przeniosłem te ze starego bloga, a myślę czy nie przenieść z tego jeszcze starszego. Kiedyś to ja umiałem pisać… A jeżeli znajdziesz jakieś błędy - napisz do mnie, a ja postaram się je poprawić.
I to by było na tyle. Jestem znowu pod wrażeniem niedoszłego laureata pokojowej nagrody Nobla. Ile to on już rozpoczął wojen? Może trzeba wprowadzić wojenną nagrodę Nobla, bo mu się należy. I śmieszno, i straszno. Ale my się nie damy i na AutomaticA11y przybywamy.Dobrego tygodnia Ci życzę. Ja w poniedziałek w sali im. Gęsickiej będę opowiadał o tym, co mi się nie podoba i co mi się podoba.

