
Transkrypcja na żywo, gdy firewall blokuje WebSockety
Sieci firmowe uwielbiają przepuszczać HTTPS i po cichu zabijać upgrade’y WebSocketa. To niepostrzeżenie psuje transkrypcję w czasie rzeczywistym. GeekBye v2.0.8 automatycznie przełącza się na czysto-HTTPS transport — a jego wydanie ujawniło błąd, który uczyniłby całą funkcję bezużyteczną.
Istnieje pewien konkretny, doprowadzający do szału sposób, w jaki transkrypcja w czasie rzeczywistym potrafi zawieść w sieci firmowej. Twoje Wi-Fi działa. HTTPS działa — możesz otworzyć dowolną stronę. Ale transkrypcja na żywo po prostu... nie startuje, i nic nie mówi ci dlaczego.
Winowajcą jest klasa firmowego proxy, które przepuszcza zwykły ruch HTTPS, ale blokuje upgrade do WebSocketa — handshake, który zamienia połączenie HTTPS w trwały, dwukierunkowy kanał, jakiego potrzebuje transkrypcja w czasie rzeczywistym. Dla proxy WebSocket wygląda jak niemonitorowany tunel na zewnątrz sieci, więc go ubija. Dla ciebie transkrypcja jest po cichu zepsuta.
GeekBye v2.0.8 dodał automatyczny fallback dokładnie na tę sytuację — a jego budowa ujawniła błąd, który sprawiłby, że cała funkcja nie robiłaby nic.
Dlaczego fallback, a nie tylko ponawianie
Radzimy już sobie z niestabilnymi sieciami. Jeśli twoje połączenie zerwie się w trakcie sesji, GeekBye łączy się ponownie z backoffem i buforuje twoje audio, żeby nic nie przepadło — to osobna funkcja opisana w dlaczego Twój notatnik AI zatrzymuje się przy słabym Wi-Fi.
Ale zablokowany WebSocket to nie niestabilne połączenie. Ponawianie tego samego WebSocketa wobec proxy, które odmawia WebSocketów, zawodzi tak samo za każdym razem, w nieskończoność. Jedyna naprawa to inny transport — taki, który wygląda jak zwykły HTTPS, który proxy już przepuszcza.
Więc v2.0.8 przełącza się na czysto-HTTPS transport przez ten sam uwierzytelniony endpoint:
- W dół (transkrypty wracające do ciebie): server-sent events — długo żyjąca odpowiedź HTTPS, którą proxy widzi jako zwykłe strumieniowane pobieranie.
- W górę (twoje audio wychodzące na zewnątrz): zbatchowane żądania POST, każde niosące fragment audio z numerem sekwencyjnym, aby serwer mógł je złożyć w kolejności, nawet jeśli sieć je przestawi.
Żadnego trwałego gniazda, niczego, co wygląda jak tunel — tylko żądania i odpowiedzi HTTPS. Jeśli proxy pozwala ci korzystać ze strony, pozwala i na to.
Błąd, który wypuściłby martwą funkcję
Oto część warta lektury. Fallback ma się uruchomić, gdy połączenie WebSocket wyczerpie swoje próby z sygnaturą zablokowanego transportu — każda próba zawodzi na upgradzie, żadnego problemu z auth ani z limitem, co najmniej jedno odrzucenie o kształcie proxy. Proxy blokujące WebSocketa zwykle odpowiada na upgrade HTTP 403 Forbidden lub 407.
Problem: nasz kod połączeniowy miał już regułę, że 403 oznacza krytyczny błąd uwierzytelnienia — zatrzymaj się, pokaż go użytkownikowi, nie ponawiaj. Co jest poprawne niemal wszędzie. Ale oznaczało to, że 403 od blokującego proxy — dokładnie ten sygnał, który powinien był uruchomić fallback — było zamiast tego rzucane jako błąd krytyczny zanim logika fallbacku w ogóle mogła się uruchomić. Tylko surowe zerwanie połączenia (zamknięcie 1006) przechodziło dalej do fallbacku. Więc funkcja działałaby dla rzadkiego przypadku i po cichu zawodziła dla swojego faktycznego głównego celu: firmowego proxy.
Wychwyciliśmy to podczas hartowania wydania, nie na produkcji. Poprawka: 403/407 na upgrade'owej nodze WebSocketa jest teraz traktowane jako odzyskiwalne, żeby pętla połączeniowa mogła wyczerpać się do fallbacku — podczas gdy prawdziwa awaria uwierzytelnienia (która przychodzi inaczej, po udanym upgradzie) nadal zawodzi szybko, dokładnie jak wcześniej. Test regresji przypina teraz to rozróżnienie: 403 od zablokowanego proxy musi przejść na fallback; prawdziwe 403 auth nie może.
Reszta hartowania poszła tą samą paranoiczną linią: timeout na każdym wychodzącym POST, żeby proxy, które przyjmuje żądanie, ale nigdy nie odpowiada, nie mogło zaciąć strumienia audio, oraz gwarancja, że prawdziwy problem z logowaniem nigdy nie może zostać po cichu zamaskowany przez maszynerię fallbacku.
Przetestowaliśmy to na prawdziwym wrogim proxy
Funkcja, której całym celem jest przetrwanie wrogich sieci, nie może być zwalidowana samymi testami jednostkowymi — testy jednostkowe nie mają proxy. Zanim ją włączyliśmy, przepuściliśmy prawdziwą aplikację przez lokalne reverse proxy skonfigurowane tak, by robić dokładnie to, co robią firmowe proxy: przekazywać HTTPS, odrzucać upgrade'y WebSocketa z 403.
Ślad w logach to dowód: cztery zablokowane próby WebSocketa, rozpoznana sygnatura wyczerpania, automatyczne przełączenie na transport HTTPS, a potem zdrowa 96-sekundowa sesja transkrypcji przez czysty HTTPS — 66 segmentów transkryptu, zero utraconych. Failover działa, bo widzieliśmy, jak się przełącza.
Trzy przenośne lekcje
- „Działa na niestabilnym Wi-Fi" i „działa za wrogim proxy" to różne gwarancje. Jedna potrzebuje ponownego łączenia; druga potrzebuje innego transportu. Mylenie ich zostawia całą populację firmowych użytkowników po cichu zepsutą.
- Twoja klasyfikacja błędów może ukryć twoją własną funkcję przed nią samą. Reguła poprawna w 99% przypadków (403 = krytyczne auth) była dokładnie błędna dla tego 1%, któremu ta funkcja miała służyć. Gdy dodajesz fallback, sprawdź, czy warunek wyzwalający w ogóle może dotrzeć do fallbacku.
- Testuj przeciwnika, nie tylko szczęśliwą ścieżkę. Jedynym uczciwym testem „przetrwa proxy blokujące WebSockety" jest proxy blokujące WebSockety. Zbudowaliśmy je.
GeekBye v2.0.8 wypuścił fallback HTTPS za flagą i zwalidowany. Dla sąsiadującej z nim pracy nad niezawodnością zobacz dlaczego Twój notatnik AI zatrzymuje się przy słabym Wi-Fi, a dla sąsiednich wydań z tej serii dlaczego Twój notatnik AI przerywa nagrywanie w trakcie spotkania (v2.0.9) oraz dlaczego transkrypcja AI przekręca terminy techniczne (v2.0.11).