Steven
Steven6 minit bacaan

Pepijat fon telinga: apabila orang yang bercakap lenyap daripada transkrip kami

Transkripsi dua saluran berfungsi dengan sempurna pada pembesar suara komputer riba dan fon kepala over-ear. Kemudian seseorang memasang fon telinga, dan orang yang mereka ajak bercakap begitu sahaja lenyap daripada transkrip — kerana Chromium senyap-senyap membisukan audio kami pada saat mereka bercakap. Sebelas pembaikan gagal. Yang kedua belas mengubah keseluruhan seni bina.

Kejuruteraan
Audio
Transkripsi
Keluaran GeekBye
Pepijat fon telinga: apabila orang yang bercakap lenyap daripada transkrip kami

GeekBye mentranskripsi dua belah perbualan: mikrofon anda pada satu saluran, audio peserta lain (apa yang dimainkan komputer anda) pada saluran lain. Ia berfungsi tanpa cela pada pembesar suara komputer riba. Ia berfungsi pada fon kepala over-ear. Kemudian seorang pengguna memasang fon telinga, dan orang yang mereka ajak bercakap lenyap daripada transkrip. Bukan berkecamuk. Bukan salah atribusi. Hilang.

Ini ialah kisah GeekBye v1.6.12, pepijat yang mengambil sebelas pembaikan gagal, dan saat kami sedar bahawa kami sedang melawan pelayar dan bukannya bekerjasama dengannya.

Trek yang hidup dan kosong

Gejalanya menyeramkan. Anda memulakan mesyuarat, semuanya kelihatan baik, anda menyebut satu perkataan — dan sejak saat itu, saluran audio orang lain masuk ke kesenyapan digital tulen. Kami mengukurnya: isyarat audio sistem berada pada paras tenaga normal (RMS sekitar 0.03–0.06), dan pada saat mikrofon menangkap suara anda, ia jatuh ke 0.0000 dan kekal di situ sepanjang baki sesi.

Inilah bahagian yang memakan masa kami berhari-hari. Setiap API pelayar berkeras bahawa trek audio itu sihat sepenuhnya. readyState: live. enabled: true. muted: false. Menurut setiap bendera status yang didedahkan platform, aliran itu baik-baik saja. Yang mati adalah sampel-nya — paip hidup yang tidak membawa apa-apa kecuali sifar. Kami menghabiskan masa yang lama tidak mempercayai meter tenaga kami sendiri, kerana cerita rasminya berkata trek itu berfungsi.

Pencetusnya khusus kepada fon telinga, dan sebabnya bersifat fizikal: sebuah fon telinga ialah satu peranti yang serentak menjadi input mikrofon dan output audio anda. Pembesar suara komputer riba dan fon kepala over-ear memisahkan keduanya — output pergi ke satu tempat, mikrofon di tempat lain. Tetapi apabila input dan output ialah peranti yang sama, anda mempunyai, menurut definisi, satu laluan maklum balas. Kesimpulan kuat kami (ini hidup di dalam perut pelayar, jadi kami tidak boleh memetik bab dan ayatnya) ialah Chromium mengesan bentuk mikrofon-tambah-pembesar suara-pada-satu-peranti itu, memutuskan ia gelung maklum balas yang bakal mengilai, dan secara melindungi membisukan tangkapan — senyap-senyap, tanpa memberitahu aplikasi melalui mana-mana bendera yang boleh dibaca aplikasi.

Sebelas pembaikan, beberapa daripadanya lebih buruk

Kami menyerangnya dahulu dengan cara-cara yang jelas, dan mencatat setiap percubaan. Menyahdayakan pembatalan gema, penindasan hingar, dan auto gain pada kedua-dua aliran. Memulakan kedua-dua aliran secara berjujukan dengan lengah dan bukannya bersama. Memberi setiap aliran sample rate-nya sendiri. Menambah nod gain senyap. Menghalakan semuanya melalui satu konteks audio berkongsi. Beralih ke AudioWorklet. Turun sepenuhnya ke pemproses trek WebCodecs mentah.

Sebelas pendekatan. Bukan sahaja gagal — beberapa memburukkannya. Satu memperkenalkan lengah 30 saat. Satu lagi menyebabkan transkrip mikrofon anda muncul berlabel sebagai orang lain. Kami terbenam jauh di dalam belukar, merawat setiap gejala, dan pepijat itu terus berpindah.

Penembusannya ialah pembingkaian semula: setiap pembaikan setakat itu cuba mengekalkan dua aliran berasingan sihat. Tetapi dua aliran berasingan ialah tepat perkara yang boleh dilihat dan dibisukan oleh heuristik maklum balas Chromium. Bagaimana jika tiada apa-apa untuk dibandingkan?

Pembaikan: beri pelayar satu aliran, bukan dua

v1.6.12 berhenti melawan dan mengubah seni bina. Daripada menghantar mikrofon dan audio sistem sebagai dua aliran bebas, ia mencampurkannya menjadi satu aliran mono pada klien sebelum apa-apa meninggalkan aplikasi. Apabila kedua-dua sumber mengalir melalui satu saluran paip, trek tidak boleh mati secara bebas — tiada lagi bentuk maklum balas dua-peranti untuk pelayar kesan dan bisukan. Keadaan pencetus itu semata-mata berhenti wujud.

Ada bonus yang menyenangkan. Dua aliran bermaksud dua WebSocket klien-ke-backend dan dua sambungan backend-ke-pembekal; satu aliran bercampur meruntuhkannya menjadi satu dan satu. Membaiki pepijat fon telinga memotong separuh kos transkripsi kami sebagai kesan sampingan.

Tetapi campuran mono mempunyai masalah yang jelas: jika anda menyebati kedua-dua orang menjadi satu saluran, bagaimana anda masih tahu siapa berkata apa? Anda telah membuang justru pemisahan yang memberitahu anda hal itu.

Membina semula "siapa yang bercakap" daripada tenaga

Jawapannya ialah mengukur kelantangan setiap sumber sebelum mencampurnya, dan melampirkan petunjuk pada setiap cebisan audio yang menyatakan sumber mana yang mendominasi — mikrofon, sistem, atau senyap. Sumber yang lebih kuat menang. Cukup mudah pada pembesar suara.

Fon telinga memerlukan satu lapisan lagi, dan di sinilah gema kembali ke dalam cerita — menghala ke arah yang bertentangan daripada yang anda jangka. Pada fon telinga, suara orang lain bocor keluar dari fon dan masuk semula ke mikrofon. Jadi tanpa berhati-hati, gema mereka, yang tiba di saluran mikrofon anda, disalah atribusi kepada anda. Pembaikannya ialah satu set ambang sedar-gema: apabila audio sistem berbunyi di atas lantai kecil, paras yang mesti dilepasi mikrofon anda untuk dikira sebagai "anda bercakap" melonjak tinggi — daripada 0.015 biasa kepada 0.1. Dengan kata lain: semasa orang lain bercakap, mikrofon anda mesti jelas, tanpa keraguan lebih kuat daripada gema mereka sebelum kami mengkreditkan kata-kata itu kepada anda. Bingkai yang taksa lalai kepada "sistem", dengan andaian ia gema. Ia ialah pincang tuju yang disengajakan yang menepati atribusi tepat dalam situasi yang dahulu selalu tersalah.

Bukti konsep itu — campuran mono tambah pengesanan suara berasaskan tenaga dan sedar-gema — ialah nenek moyang sistem atribusi yang dijalankan GeekBye hari ini. Perancahnya dicabut dalam keluaran yang sama sebaik ia terbukti, dan matematik tenaganya kemudian mengeras menjadi modul yang diuji dengan betul. Tetapi v1.6.12 ialah tempat idea itu lahir, dalam tekanan, oleh seorang pengguna dengan sepasang fon telinga.

Tiga perkara yang diajar pepijat fon telinga

  1. Pemegang yang sihat boleh membawa data yang mati. Keseluruhan siasatan berkisar pada mempercayai meter tenaga kami mengatasi bendera status platform — live, enabled, unmuted, semuanya menipu sementara sampelnya sifar. Pantau muatan, bukan laporan-kendiri API. Jika satu aliran mendakwa ia baik-baik saja, ukurlah sama ada ia benar-benar begitu.
  2. Apabila platform melawan seni bina anda, ubah seni binanya — bukan platformnya. Kami tidak dapat mengatasi hujah perlindungan maklum balas Chromium, dan setiap percubaan menyahdayakannya di pinggiran gagal atau menjadi bumerang. Membuang keadaan yang boleh dicerap — dua aliran menjadi satu — melenyapkan seluruh masalah. Hampir selalu lebih murah membuang pencetus daripada memenangi pergaduhan dengan pelayar.
  3. Apabila anda meruntuhkan saluran demi keteguhan, anda mesti membina semula apa yang anda musnahkan. Mencampur ke mono membunuh pemisahan saluran yang membawa "siapa yang bercakap". Maklumat itu terpaksa diterbitkan semula daripada tenaga pra-campur dan ambang sedar-gema. Logik pampasan itu bukan renungan lewat kepada pembaikan — ia ialah separuh daripada pembaikan.

Ini ialah bab keempat kisah kebolehpercayaan yang menjadi GeekBye v2. Untuk bab sebelumnya, lihat sambungan terputus tidak sepatutnya meranapkan seluruh aplikasi anda (v1.6.8); untuk penulisan semula saluran paip yang menjadi asas kerja audio ini, kami memadam 5,000 baris kod audio (v1.6.0); dan untuk keseluruhan arka, anatomi menghantar perisian hingga ke kesempurnaan.