Steven
Steven5 dk okuma

5.000 Satır Ses Kodunu Sildik — ve Transkriptler İki Kez Görünmeye Başladı

GeekBye v1.6, cihaz üzerindeki iki Swift transkribeyi söküp yerine tek bir birleşik ardışık düzen koydu — net olarak 5.000'den fazla satır silindi, hem de insanlar uygulamada toplantının tam ortasındayken. Sonra transkriptler iki kez görünmeye başladı, çünkü hata hâlâ iki motor olduğunu sanan tek katmana taşındı.

Mühendislik
Transkripsiyon
Mimari
GeekBye Releases
5.000 Satır Ses Kodunu Sildik — ve Transkriptler İki Kez Görünmeye Başladı

Şu anda çalışan, toplantının tam ortasında olan insanlar için çalışan kodu refactor etmenin kendine özgü bir dehşeti vardır. Özelliği bakım için kapatamazsınız — birileri, tekrarlayamayacağı bir konuşmayı deşifre etmek için ona güveniyor. GeekBye v1.6, uygulamadaki en kritik yola tam da bunu yaptı: ses ardışık düzeni. Bu, sildiğimiz şeyin, bozulanın ve bundan çıkan iki güvenilirlik dersinin hikâyesidir.

İki motor, biri Swift''te

v1.6''dan önce, GeekBye''ın konuşmadan metne dönüşümü cihaz üzerinde Swift ikili dosyalarında çalışıyordu. İki tane vardı: biri Apple''ın Speech çerçevesini saran, diğeri ise ikili ses yakalayan daha büyük olanı (1.500 satırdan fazla) — mikrofonunuz artı sistem sesi — ScreenCaptureKit aracılığıyla ve Deepgram''a akıtmak için doğrudan arka ucumuza kendi WebSocket''ini açan. İki transkribe, iki yakalama yolu, ağla konuşmanın iki yolu, hepsi de her değişikliğin bir ikili dosyayı yeniden derlemeyi gerektirdiği derlenmiş bir dilde.

v1.6.0 bunların hepsini tek bir ardışık düzene indirdi. Tek birleştirici commit, Apple Speech transkribesini (~1.145 satır), Deepgram Swift yakalayıcısını (~1.523 satır), her iki TypeScript köprüsünü, eski orkestratörü ve ikili ses IPC işleyicilerini sildi — net olarak 5.200''den fazla satırlık bir silme. Onların yerine: renderer sesi standart Web APIs aracılığıyla yakalıyor, IPC üzerinden PCM olarak gönderiyor ve Electron ana süreci, sağlayıcının arka uç yapılandırmasıyla seçildiği tek bir WebSocket yoluna sahip. Tek yakalama yolu, tek soket sahibi, üzerinde akıl yürütülecek tek bir yer.

Beş bin satır silmek harika hissettiriyor. Yaklaşık bir gün boyunca.

Hata hâlâ iki olduğunu sanan katmana taşındı

Sonra transkriptler iki kez görünmeye başladı. Söylenen tek bir cümle iki özdeş kayıt olarak kaydediliyordu — bazen daha kötüsü.

Kök neden, bu sürümün tamamındaki en öğretici şey, çünkü bu birleştirmenin genel bir yasasıdır. Sağlayıcıları ana süreçte birleştirmiştik — tek soket, tek işleyici. Ama React katmanı notu almamıştı: hâlâ aynı anda sağlayıcıya özel iki olay kancası takıyordu, biri Deepgram için, diğeri ElevenLabs için yapılmış. İkisi de dinliyordu. İkisi de kaydediyordu. Her transkript, hangi kancalar hayattaysa onlar tarafından kalıcılaştırılıyordu — ve ikisi de hayattaydı.

Ve altında ikinci, daha sinsi bir katlama vardı: ElevenLabs her sonlandırılmış satırı iki kez yayar — bir kez committed olayı, bir kez de committed_with_timestamps olarak. Yani tek bir kancayla bile, bir cümle iki olay olarak gelebilirdi.

Çözüm (v1.6 hattında) iki nedene tam olarak eşlenen düzgün bir ikilidir: her olay kancasını, arka ucun aktif sağlayıcı yapılandırmasının yönlendirdiği bir enabled bayrağının arkasına al, böylece asla birden fazla dinleyici canlı olmasın; ve ElevenLabs''in çift yayınını yutmak için kaynak başına metin tekilleştirmesi ekle (mikrofon ve sistem sesi için en son kaydedilen satırı hatırla).

Ders bu hatadan daha büyük: iki arka ucu tek bir arayüzün arkasında birleştirdiğinizde, yineleme kaybolmaz — hâlâ iki olduğunu varsayan katmana göç eder. Tesisatı ana süreçte çökerttik ve sızıntı iki katman yukarıda, arayüzün olay bağlantısında yüzeye çıktı. Bir ardışık düzeni birleştirmek, üretici birleştirildiğinde bitmez; her tüketici eski şekle inanmayı bıraktığında biter.

İlk yeniden bağlanma: "beş denemeden sonra pes et"

v1.6.0 ayrıca GeekBye''ın üstel geri çekilmeli ilk WebSocket otomatik yeniden bağlanmasını da getirdi — ve bunu göstermeye değer, tam da bugün çalıştırdığımız kurşun geçirmez sürümün ilkel atası olduğu için.

Orijinali sınırlıydı. Beş deneme, 1s, 2s, 4s, 8s, 16s gecikmelerle — ve sonra teslim oldu, ölümcül bir hata yayarak: "Bağlantı kesildi — lütfen transkripsiyonu yeniden başlatın." O zamanlar bu sorumlu görünüyordu: sonsuza kadar deneme, kullanıcıya dürüstçe söyle. Pratikte kılık değiştirmiş bir UX hatasıydı. On altı saniyelik bir ağ kesintisi — bir Wi-Fi geçişi, bir VPN yeniden bağlanması, bir tünel — geçicidir, ama sınırlı bir yeniden deneme onu kalıcı olarak ele alır. Kullanıcı yanlış bir şey yapmadı ve ona canlı bir toplantıyı yeniden başlatması söylendi.

İşte mevcut tasarımın ortadan kaldırdığı tam da bu arızadır. Bugün GeekBye sınırsız geri çekilme ile yeniden bağlanır ve hatta sağlayıcıları döngüye sokar, ve yalnızca gerçekten ölümcül bir neden için durur — auth, kota, faturalandırma. "Beşten sonra pes et"ten "geçici bir hatada asla pes etme"ye tüm yolculuk kötü Wi-Fi''de AI not alıcınız neden durur yazısında anlatılıyor. v1.6, önce var olması gereken naif sürümle bu yolun başladığı yerdir.

Bayat bağlantılar, adları olmadıkça sizi rahatsız eder

Bir güvenilirlik dersi daha v1.6.3''te iniş yaptı ve durum bilgisi tutan bir arka uç üzerinden yeniden bağlanan herkesin er ya da geç karşılaşacağı ince bir hata sınıfını düzeltti.

Yeniden bağlandığınızda — ya da oturumun ortasında transkripsiyon dilini değiştirdiğinizde, ki bu perde arkasında yeniden bağlanır — eski bağlantı her zaman sessizce ölmez. Ölüm hırıltısı mesajları (CONNECTION_LOST, disconnected) yeni bağlantı zaten sağlıklıyken sonra gelebilir ve mükemmel derecede iyi olan yerine geçeni yıkabilir. Çözüm, her bağlantı denemesine bir kimlik verir — WebSocket URL''sine damgalanmış bağlantı başına bir oturum kimliği — artı yeniden bağlanmadan sonra, önceki bir denemeden gelen bayat bağlantı kesme mesajlarının yok sayıldığı kısa bir tolerans penceresi. Ayrıca, arka ucun eski oturumu temiz bir şekilde yıkabilmesi için bir soketi kapatmadan önce açık bir stop mesajı gönderir.

İlke: durum bilgisi tutan bir arka uç üzerindeki herhangi bir yeniden bağlanma mantığının her denemeyi bir kimlikle etiketlemesi ve önceki denemelerden gelen geç mesajları gürültü olarak ele alması gerekir — aksi halde başarılı bir yeniden bağlanma, öncülünün son nefesi tarafından öldürülür.

v1.6''nın öğrettiği üç şey

  1. Birleştirme hataları yeniden konumlandırır; onları silmez. İki motoru bire indirin ve hâlâ iki olduğunu sanan her tüketiciyi denetleyin. Bizimki arayüzdü, tesisat zaten birleştikten sonra iki olay kancası takıyordu.
  2. İlk yeniden bağlanmanız sınırlı olacak ve sınırlı, canlı akışlar için yanlıştır. "N denemeden sonra pes et" geçici bir kesintiyi, kullanıcının suçlandığı kalıcı bir arızaya dönüştürür. En ilk sürümden itibaren ölümcülü (auth, kota) geçiciden (düşen bir soket) ayırt edin.
  3. Yeniden bağlanmaların kimliğe ihtiyacı vardır. Her denemeyi etiketleyin; ölü denemelerden gelen geç mesajları yok sayın. Adı olmayan bir bağlantı, kendi hayaleti tarafından öldürülebilir.

Bu, GeekBye v2''ye dönüşen güvenilirlik hikâyesinin ikinci bölümüdür. İlki için, dört günde altı sürüm süren otomatik güncelleme destanı (v1.5.x); yeniden bağlanma çalışmasının nihayetinde vardığı yer için, kötü Wi-Fi''de AI not alıcınız neden durur; ve tüm yay için, yazılımı mükemmelliğe kadar yayınlamanın anatomisi yazılarına bakın.