Steven
Steven5 min lukuaika

Nappikuulokebugi: kun toinen keskustelija katosi transkriptiostamme

Kaksikanavainen transkriptio toimi moitteettomasti kannettavan kaiuttimilla ja korvat peittävillä kuulokkeilla. Sitten joku laittoi korviin nappikuulokkeet, ja henkilö jonka kanssa hän puhui yksinkertaisesti katosi transkriptiosta — koska Chromium vaimensi äänemme hiljaa sillä hetkellä kun tämä alkoi puhua. Yksitoista korjausta epäonnistui. Kahdestoista muutti koko arkkitehtuurin.

Ohjelmistotuotanto
Ääni
Transkriptio
GeekBye-julkaisut
Nappikuulokebugi: kun toinen keskustelija katosi transkriptiostamme

GeekBye transkriboi keskustelun kaksi puolta: mikrofonisi yhdellä kanavalla, toisen osallistujan äänen (sen mitä tietokoneesi toistaa) toisella. Se toimi moitteettomasti kannettavan kaiuttimilla. Se toimi korvat peittävillä kuulokkeilla. Sitten yksi käyttäjä laittoi korviin nappikuulokkeet, ja henkilö jonka kanssa hän puhui katosi transkriptiosta. Ei sekaisin. Ei väärin kohdistettuna. Poissa.

Tämä on tarina GeekBye v1.6.12:sta, bugista joka vaati yksitoista epäonnistunutta korjausta, ja hetkestä jolloin tajusimme taistelevamme selainta vastaan sen sijaan että työskentelisimme sen kanssa.

Raita joka oli elossa ja tyhjä

Oire oli aavemainen. Aloitit palaverin, kaikki näytti hyvältä, sanoit yhden sanan — ja siitä hetkestä toisen henkilön äänikanava meni puhtaaseen digitaaliseen hiljaisuuteen. Mittasimme sen: järjestelmän äänen signaali pysyi normaalilla energiatasolla (RMS noin 0.03–0.06), ja sillä hetkellä kun mikrofoni poimi äänesi, se putosi arvoon 0.0000 ja pysyi siinä koko lopun istunnon ajan.

Tässä on se osa joka maksoi meille päiviä. Jokainen selaimen API vakuutti itsepintaisesti, että ääniraita oli täysin terve. readyState: live. enabled: true. muted: false. Jokaisen statuslipun mukaan jonka alusta paljasti, virta oli kunnossa. Kuolleita olivat näytteet — elävä putki joka kantoi vain nollia. Emme pitkään uskoneet omaa energiamittariamme, koska virallinen tarina väitti raidan toimivan.

Laukaisija oli erityinen nappikuulokkeille, ja syy on fyysinen: nappikuuloke on yksi laite joka on samanaikaisesti sekä mikrofonisi sisääntulo että äänesi ulostulo. Kannettavan kaiuttimet ja korvat peittävät kuulokkeet erottavat nämä — ulostulo menee yhteen paikkaan, mikrofoni on muualla. Mutta kun sisääntulo ja ulostulo ovat sama laite, sinulla on määritelmän mukaan takaisinkytkentäpolku. Vahva päätelmämme (tämä elää selaimen sisuksissa, joten emme voi lainata lukua ja jaetta) on, että Chromium havaitsee tämän mikrofoni-plus-kaiutin-yhdellä-laitteella-muodon, päättää että se on kohta vinkumaan alkava takaisinkytkentäsilmukka, ja suojaavasti vaimentaa kaappauksen — hiljaa, kertomatta siitä sovellukselle minkään lipun kautta jonka sovellus voi lukea.

Yksitoista korjausta, useat niistä pahempia

Hyökkäsimme siihen ensin ilmeisillä tavoilla ja kirjasimme jokaisen yrityksen ylös. Poistaa kaiunpoisto, kohinanvaimennus ja automaattinen vahvistus molemmista virroista. Käynnistää kaksi virtaa peräkkäin viiveellä yhdessä käynnistämisen sijaan. Antaa jokaiselle virralle oma näytteenottotaajuutensa. Lisätä hiljainen vahvistussolmu. Reitittää kaikki yhden jaetun äänikontekstin läpi. Siirtyä AudioWorkletiin. Pudota aivan raakaan WebCodecs-raidan prosessoriin asti.

Yksitoista lähestymistapaa. Ne eivät vain epäonnistuneet — useat tekivät asiasta pahemman. Yksi toi 30 sekunnin viiveen. Toinen sai mikrofonisi transkription näkymään toisen henkilön nimellä. Olimme syvällä pusikossa, hoidimme jokaista oiretta, ja bugi vain liikkui.

Läpimurto oli uudelleenmuotoilu: jokainen tähänastinen korjaus yritti pitää kaksi erillistä virtaa terveenä. Mutta kaksi erillistä virtaa oli juuri se minkä Chromiumin takaisinkytkentäheuristiikka pystyi näkemään ja vaimentamaan. Entä jos ei olisi mitään verrattavaa?

Korjaus: anna selaimelle yksi virta, ei kahta

v1.6.12 lopetti taistelemisen ja muutti arkkitehtuurin. Sen sijaan että mikrofoni ja järjestelmän ääni lähetettäisiin kahtena itsenäisenä virtana, se miksaa ne yhdeksi monoraidaksi asiakaspäässä ennen kuin mikään lähtee sovelluksesta. Kun molemmat lähteet virtaavat yhden putken läpi, raidat eivät voi kuolla itsenäisesti — ei ole enää kahden laitteen takaisinkytkentämuotoa jonka selain voisi havaita ja vaimentaa. Laukaiseva ehto yksinkertaisesti lakkaa olemasta.

Oli myös ihastuttava bonus. Kaksi virtaa tarkoitti kahta asiakas-taustapalvelin-WebSocketia ja kahta taustapalvelin-palveluntarjoaja-yhteyttä; yksi miksattu virta romahdutti sen yhteen ja yhteen. Nappikuulokebugin korjaaminen puolitti transkriptiokustannuksemme sivuvaikutuksena.

Mutta monomiksauksessa on ilmeinen ongelma: jos sekoitat molemmat ihmiset yhdeksi kanavaksi, mistä yhä tiedät kuka sanoi mitä? Olethan heittänyt pois juuri sen erottelun joka kertoi sen sinulle.

"Kuka puhui" -tiedon rakentaminen energiasta

Vastaus oli mitata kunkin lähteen äänekkyys ennen niiden miksaamista ja liittää jokaiseen äänen palaseen vihje siitä mikä lähde hallitsi — mikrofoni, järjestelmä vai hiljaisuus. Äänekkäämpi lähde voittaa. Riittävän yksinkertaista kaiuttimilla.

Nappikuulokkeet vaativat vielä yhden kerroksen, ja tässä kaiku palaa tarinaan — suunnattuna päinvastoin kuin arvaisit. Nappikuulokkeilla toisen henkilön ääni vuotaa napista ulos ja takaisin mikrofoniin. Joten ilman huolellisuutta hänen kaikunsa, joka saapuu mikrofonikanavallesi, kohdistetaan sinulle. Korjaus on joukko kaikutietoisia kynnyksiä: kun järjestelmän ääni soi pienen pohjan yläpuolella, rima joka mikrofonisi on ylitettävä laskeakseen "sinun puhumiseksesi" hyppää roimasti ylös — normaalista arvosta 0.015 arvoon 0.1. Toisin sanoen: sillä aikaa kun toinen henkilö puhuu, mikrofonisi on oltava selkeästi ja yksiselitteisesti äänekkäämpi kuin hänen kaikunsa ennen kuin luemme sanat sinun ansioksesi. Monitulkintaiset kehykset kohdistetaan oletuksena "järjestelmälle", olettaen että ne ovat kaikua. Se on tarkoituksellinen vinouma joka saa kohdistuksen oikein juuri siinä tilanteessa joka ennen meni väärin.

Tuo konseptitodistus — monomiksaus plus energiapohjainen, kaikutietoinen puheentunnistus — on esi-isä sille kohdistusjärjestelmälle jota GeekBye käyttää tänään. Rakennustelineet revittiin pois samassa julkaisussa heti kun ne olivat todistaneet arvonsa, ja energiamatematiikka koveni myöhemmin kunnolla testatuksi moduuliksi. Mutta v1.6.12 on se paikka jossa idea syntyi — paineen alla, käyttäjän toimesta jolla oli pari nappikuuloketta.

Kolme asiaa jotka nappikuulokebugi opetti

  1. Terve kahva voi kantaa kuollutta dataa. Koko tutkinta kääntyi sen ympärille että luotimme energiamittariimme enemmän kuin alustan statuslippuihin — live, enabled, unmuted, kaikki valehtelivat samalla kun näytteet olivat nollia. Tarkkaile sisältöä, älä API:n omaa raporttia. Jos virta väittää olevansa kunnossa, mittaa onko se sitä todella.
  2. Kun alusta taistelee arkkitehtuuriasi vastaan, muuta arkkitehtuuria — älä alustaa. Emme voineet väittää Chromiumin takaisinkytkentäsuojaa vääräksi, ja jokainen yritys poistaa se reunoilta epäonnistui tai iski takaisin. Havaittavan ehdon poistaminen — kahdesta virrasta tulee yksi — sai koko ongelman katoamaan. On lähes aina halvempaa poistaa laukaisija kuin voittaa taistelu selaimen kanssa.
  3. Kun romautat kanavat kestävyyden vuoksi, sinun on rakennettava uudelleen se minkä tuhosit. Monoksi miksaaminen tappoi kanavaerottelun joka kantoi "kuka puhui" -tiedon. Se tieto oli johdettava uudelleen miksausta edeltävästä energiasta ja kaikutietoisista kynnyksistä. Kompensoiva logiikka ei ole korjauksen jälkiajatus — se on puolet korjauksesta.

Tämä on neljäs luku kestävyystarinassa josta tulee GeekBye v2. Edellisen luvun näet täältä: katkennut yhteys ei saisi kaataa koko sovellustasi (v1.6.8); putken uudelleenkirjoituksesta johon tämä äänityö perustui, poistimme 5000 riviä äänikoodia (v1.6.0); ja koko kaaresta, anatomia täydellisyyteen asti viimeistellyn ohjelmiston toimittamisesta.