Steven
Steven5 dk okuma

Kulaklık hatası: Karşıdaki kişi transkriptimizden kaybolduğunda

Çift kanallı transkripsiyon, dizüstü hoparlörlerinde ve kulak üstü kulaklıklarda kusursuz çalışıyordu. Sonra biri kulak içi kulaklık taktı ve konuştuğu kişi transkriptten öylece kayboldu — çünkü Chromium, o kişi konuştuğu anda sesimizi sessizce susturuyordu. On bir düzeltme başarısız oldu. On ikincisi tüm mimariyi değiştirdi.

Mühendislik
Ses
Transkripsiyon
GeekBye Sürümleri
Kulaklık hatası: Karşıdaki kişi transkriptimizden kaybolduğunda

GeekBye bir konuşmanın iki tarafını transkribe eder: bir kanalda mikrofonunuz, diğer kanalda karşıdaki katılımcının sesi (bilgisayarınızın çaldığı şey). Dizüstü hoparlörlerinde kusursuz çalıştı. Kulak üstü kulaklıklarda çalıştı. Sonra bir kullanıcı kulak içi kulaklık taktı ve konuştuğu kişi transkriptten kayboldu. Bozulmadı. Yanlış atfedilmedi. Yok oldu.

Bu, GeekBye v1.6.12'nin, on bir başarısız düzeltmeye mal olan hatanın ve tarayıcıyla çalışmak yerine ona karşı savaştığımızı fark ettiğimiz anın hikâyesi.

Canlı ve boş olan parça

Belirti ürperticiydi. Bir toplantı başlatıyordunuz, her şey iyi görünüyordu, bir kelime söylüyordunuz — ve o andan itibaren karşıdaki kişinin ses kanalı saf dijital sessizliğe gidiyordu. Bunu ölçtük: sistem sesi sinyali normal bir enerji seviyesindeydi (yaklaşık 0.03–0.06 civarında bir RMS) ve mikrofon sesinizi yakaladığı anda 0.0000'a düşüyor ve oturumun geri kalanında orada kalıyordu.

İşte bize günlere mal olan kısım. Her tarayıcı API'si ses parçasının kusursuz derecede sağlıklı olduğunda ısrar ediyordu. readyState: live. enabled: true. muted: false. Platformun açığa çıkardığı her durum bayrağına göre akış iyiydi. Ölü olanlar örneklerdi — sıfırdan başka bir şey taşımayan canlı bir boru. Uzun süre kendi enerji ölçerimize inanmayarak geçirdik, çünkü resmi anlatı parçanın çalıştığını söylüyordu.

Tetikleyici kulak içi kulaklıklara özgüydü ve nedeni fiziksel: bir kulak içi kulaklık, aynı anda hem mikrofon girişiniz hem de ses çıkışınız olan tek bir cihazdır. Dizüstü hoparlörleri ve kulak üstü kulaklıklar bunları ayırır — çıkış bir yere gider, mikrofon başka bir yerdedir. Ama giriş ve çıkış aynı cihaz olduğunda, tanımı gereği bir geri besleme yolunuz vardır. Güçlü çıkarımımız (bu, tarayıcının derinliklerinde yaşadığı için tam kaynak gösteremeyiz), Chromium'un bu mikrofon-artı-hoparlör-tek-cihazda biçimini algıladığı, bunun cıyaklamak üzere olan bir geri besleme döngüsü olduğuna karar verdiği ve yakalamayı koruyucu bir şekilde susturduğu — sessizce, bunu bir uygulamanın okuyabileceği bayrakların hiçbiri aracılığıyla uygulamaya söylemeden.

On bir düzeltme, birkaçı daha kötü

İlk önce bariz yollarla saldırdık ve her denemeyi yazdık. Her iki akışta da yankı iptalini, gürültü bastırmayı ve auto gain'i devre dışı bırakmak. İki akışı birlikte değil, gecikmeyle sırayla başlatmak. Her akışa kendi sample rate'ini vermek. Sessiz bir gain düğümü eklemek. Her şeyi tek bir paylaşılan ses bağlamı üzerinden yönlendirmek. Bir AudioWorklet'e geçmek. En dibe, ham WebCodecs parça işlemcisine kadar inmek.

On bir yaklaşım. Sadece başarısız olmakla kalmadılar — birkaçı işi daha da kötüleştirdi. Biri 30 saniyelik bir gecikme getirdi. Bir diğeri mikrofonunuzun transkriptinin diğer kişi olarak etiketlenmesine neden oldu. Ayrık otların içine gömülmüştük, her belirtiyi tedavi ediyorduk ve hata durmadan yer değiştiriyordu.

Atılım bir yeniden çerçeveleme oldu: o ana kadarki her düzeltme iki ayrı akışı sağlıklı tutmaya çalışıyordu. Ama iki ayrı akış, Chromium'un geri besleme sezgisinin görebildiği ve susturabildiği tam olarak o şeydi. Ya karşılaştıracak hiçbir şey olmasaydı?

Düzeltme: tarayıcıya iki değil, tek akış ver

v1.6.12 mücadeleyi bıraktı ve mimariyi değiştirdi. Mikrofon ve sistem sesini iki bağımsız akış olarak göndermek yerine, herhangi bir şey uygulamadan çıkmadan önce bunları istemcide tek bir mono akışta karıştırıyor. Her iki kaynak tek bir boru hattından aktığında, parçalar birbirinden bağımsız ölemez — artık tarayıcının algılayıp susturacağı iki cihazlı bir geri besleme biçimi yoktur. Tetikleme koşulu basitçe var olmaktan çıkar.

Keyifli bir bonus vardı. İki akış, iki istemci-arka uç WebSocket'i ve iki arka uç-sağlayıcı bağlantısı demekti; tek bir karışık akış bunu bire bir indirdi. Kulaklık hatasını düzeltmek, yan etki olarak transkripsiyon maliyetimizi yarıya indirdi.

Ama mono karıştırmanın bariz bir sorunu var: her iki kişiyi tek bir kanalda harmanlarsanız, kimin ne söylediğini hâlâ nasıl bilirsiniz? Size bunu söyleyen ayrımı tam da atmış oldunuz.

"Kim konuştu" bilgisini enerjiden yeniden inşa etmek

Cevap, her kaynağın ses yüksekliğini karıştırmadan önce ölçmek ve her ses parçasına hangi kaynağın baskın olduğunu söyleyen bir ipucu iliştirmekti — mikrofon, sistem veya sessizlik. Daha yüksek olan kaynak kazanır. Hoparlörlerde yeterince basit.

Kulak içi kulaklıklar bir katman daha gerektirdi ve yankının hikâyeye geri döndüğü yer burası — tahmin edeceğinizin tam tersi yöne işaret ederek. Kulak içi kulaklıklarda, diğer kişinin sesi kulaklıktan sızar ve mikrofona geri girer. Yani dikkat edilmezse, mikrofon kanalınıza gelen onların yankısı size atfedilir. Düzeltme, bir dizi yankı bilinçli eşiktir: sistem sesi küçük bir tabanın üzerinde çalarken, mikrofonunuzun "sizin konuşmanız" olarak sayılmak için aşması gereken çıta çok yükselir — normal bir 0.015'ten 0.1'e. Başka bir deyişle: diğer kişi konuşurken, sözleri size atfetmeden önce mikrofonunuz onların yankısından açıkça, kesinlikle daha yüksek olmalıdır. Belirsiz kareler, yankı oldukları varsayımıyla varsayılan olarak "sistem"e döner. Bu, eskiden yanlış yaptığı tam durumda atfı doğru yapan kasıtlı bir önyargıdır.

O kavram kanıtı — mono karıştırma artı enerji tabanlı, yankı bilinçli ses algılama — GeekBye'ın bugün çalıştırdığı atıf sisteminin atasıdır. İskele, kendini kanıtladıktan sonra aynı sürümde söküldü ve enerji matematiği daha sonra düzgün test edilmiş bir modüle dönüştü. Ama v1.6.12, fikrin baskı altında, bir çift kulak içi kulaklığı olan bir kullanıcı tarafından doğduğu yerdir.

Kulaklık hatasının öğrettiği üç şey

  1. Sağlıklı bir tutamaç ölü veri taşıyabilir. Tüm araştırma, enerji ölçerimize platformun durum bayraklarından — live, enabled, unmuted, örnekler sıfırken hepsi yalan söylerken — daha çok güvenmeye dayanıyordu. API'nin öz raporunu değil, yükü izleyin. Bir akış iyi olduğunu iddia ediyorsa, gerçekten öyle olup olmadığını ölçün.
  2. Platform mimarinize karşı savaştığında, mimariyi değiştirin — platformu değil. Chromium'un geri besleme korumasıyla tartışmayı kazanamadık ve onu kenarlarından devre dışı bırakma girişimlerinin her biri başarısız oldu ya da ters tepti. Gözlemlenebilir koşulu — iki akışın bire dönüşmesi — kaldırmak tüm sorunu ortadan kaldırdı. Tetikleyiciyi kaldırmak, neredeyse her zaman tarayıcıyla bir kavgayı kazanmaktan daha ucuzdur.
  3. Sağlamlık için kanalları çökerttiğinizde, yok ettiğinizi yeniden inşa etmelisiniz. Mono'ya karıştırmak, "kim konuştu" bilgisini taşıyan kanal ayrımını öldürdü. O bilginin karıştırma öncesi enerjiden ve yankı bilinçli eşiklerden yeniden türetilmesi gerekiyordu. Telafi edici mantık, düzeltmeye sonradan eklenen bir şey değildir — düzeltmenin yarısıdır.

Bu, GeekBye v2'ye dönüşen güvenilirlik hikâyesinin dördüncü bölümü. Önceki bölüm için bkz. düşen bir bağlantı tüm uygulamanızı çökertmemeli (v1.6.8); bu ses çalışmasının üzerine kurulduğu boru hattı yeniden yazımı için, 5.000 satır ses kodunu sildik (v1.6.0); ve tüm yay için, yazılımı kusursuzluğa kadar yayınlamanın anatomisi.

İlgili Makaleler