
Austiņu kļūda: kad otrs sarunbiedrs pazuda no mūsu transkripta
Divkanālu transkripcija nevainojami strādāja ar klēpjdatora skaļruņiem un lielajām austiņām. Tad kāds iesprauda ausī ieliekamās austiņas, un cilvēks, ar kuru viņš runāja, vienkārši pazuda no transkripta — jo Chromium klusi apklusināja mūsu audio tajā pašā mirklī, kad viņš ierunājās. Vienpadsmit labojumi neizdevās. Divpadsmitais mainīja visu arhitektūru.
GeekBye transkribē divas sarunas puses: tavu mikrofonu vienā kanālā, otra dalībnieka audio (to, ko atskaņo tavs dators) — otrā. Tas nevainojami strādāja ar klēpjdatora skaļruņiem. Tas strādāja ar lielajām austiņām. Tad kāds lietotājs iesprauda ausī ieliekamās austiņas, un cilvēks, ar kuru viņš runāja, pazuda no transkripta. Ne izkropļots. Ne nepareizi piedēvēts. Pazudis.
Šis ir stāsts par GeekBye v1.6.12, kļūdu, kuras dēļ bija vajadzīgi vienpadsmit neveiksmīgi labojumi, un brīdi, kad sapratām, ka cīnāmies pret pārlūku, nevis strādājam ar to.
Celiņš, kas bija dzīvs un tukšs
Simptoms bija dīvains. Tu sāc sapulci, viss izskatās kārtībā, tu pasaki vienu vārdu — un no tā mirkļa otra cilvēka audio kanāls pāriet tīrā digitālā klusumā. Mēs to izmērījām: sistēmas audio signāls turējās normālā enerģijas līmenī (RMS ap 0.03–0.06), un tajā mirklī, kad mikrofons uztvēra tavu balsi, tas nokrita līdz 0.0000 un tāds palika visu pārējo sesijas laiku.
Lūk, tā daļa, kas mums izmaksāja dienas. Katrs pārlūka API neatlaidīgi apgalvoja, ka audio celiņš ir pilnīgi vesels. readyState: live. enabled: true. muted: false. Pēc katra statusa karodziņa, ko platforma atklāj, plūsma bija kārtībā. Miruši bija paraugi — dzīva caurule, kas nes tikai nulles. Mēs ilgi neticējām paši savam enerģijas mērītājam, jo oficiālais stāsts vēstīja, ka celiņš strādā.
Izraisītājs bija specifisks ieliekamajām austiņām, un iemesls ir fizisks: ieliekamā austiņa ir viena ierīce, kas vienlaikus ir gan tavs mikrofona ieejas signāls, gan tavs audio izejas signāls. Klēpjdatora skaļruņi un lielās austiņas tos atdala — izeja aiziet vienā vietā, mikrofons ir citur. Bet, kad ieeja un izeja ir viena un tā pati ierīce, tev pēc definīcijas ir atgriezeniskās saites ceļš. Mūsu spēcīgais secinājums (tas mīt pārlūka dziļumos, tāpēc nevaram citēt rindkopu pēc rindkopas) ir tāds, ka Chromium konstatē šo mikrofona-plus-skaļruņa-vienā-ierīcē formu, izlemj, ka tā ir gatava iesvilpties atgriezeniskā saite, un aizsargājoši apklusina uztveršanu — klusi, nepasakot lietotnei ne caur vienu no karodziņiem, ko lietotne var nolasīt.
Vienpadsmit labojumi, vairāki sliktāki
Vispirms uzbrukām tam acīmredzamajos veidos un pierakstījām katru mēģinājumu. Atspējot atbalss dzēšanu, trokšņu slāpēšanu un automātisko pastiprinājumu abās plūsmās. Palaist abas plūsmas secīgi ar aizkavi, nevis kopā. Katrai plūsmai dot savu diskretizācijas frekvenci. Pievienot klusu pastiprinājuma mezglu. Novadīt visu caur vienu kopīgu audio kontekstu. Pāriet uz AudioWorklet. Nokāpt līdz pašam neapstrādātajam WebCodecs celiņa procesoram.
Vienpadsmit pieejas. Tās ne tikai neizdevās — vairākas padarīja lietas sliktākas. Viena ieviesa 30 sekunžu aizkavi. Cita lika tava mikrofona transkriptam parādīties ar otra cilvēka etiķeti. Mēs bijām dziļi biezoknī, ārstējām katru simptomu, un kļūda turpināja kustēties.
Izrāviens bija pārformulējums: katrs līdzšinējais labojums centās uzturēt veselas divas atsevišķas plūsmas. Bet divas atsevišķas plūsmas bija tieši tas, ko Chromium atgriezeniskās saites heiristika varēja ieraudzīt un apklusināt. Ja nu nebūtu ko salīdzināt?
Labojums: iedod pārlūkam vienu plūsmu, nevis divas
v1.6.12 pārstāja cīnīties un mainīja arhitektūru. Tā vietā, lai sūtītu mikrofona un sistēmas audio kā divas neatkarīgas plūsmas, tā sajauc tās vienā mono plūsmā klienta pusē, pirms kaut kas pamet lietotni. Kad abi avoti plūst caur vienu cauruli, celiņi nevar atmirt neatkarīgi — vairs nav divu ierīču atgriezeniskās saites formas, ko pārlūkam konstatēt un apklusināt. Izraisītājnosacījums vienkārši beidz eksistēt.
Bija arī jauks bonuss. Divas plūsmas nozīmēja divus klienta-uz-backend WebSocket savienojumus un divus backend-uz-pakalpojumu sniedzēju savienojumus; viena sajaukta plūsma to sabruka līdz vienam un vienam. Austiņu kļūdas labošana uz pusi samazināja mūsu transkripcijas izmaksas kā blakusefektu.
Bet mono miksēšanai ir acīmredzama problēma: ja sajauc abus cilvēkus vienā kanālā, kā tu joprojām zini, kurš ko teica? Tu esi izmetis prom pašu to atdalīšanu, kas tev to pateica.
Atjaunojot "kurš runāja" no enerģijas
Atbilde bija izmērīt katra avota skaļumu pirms to sajaukšanas un pievienot katram audio gabaliņam mājienu, kurš avots dominēja — mikrofons, sistēma vai klusums. Skaļākais avots uzvar. Ar skaļruņiem pietiekami vienkārši.
Ieliekamajām austiņām bija vajadzīgs vēl viens slānis, un šeit atbalss atgriežas stāstā — vērsta pretējā virzienā tam, ko varētu iedomāties. Ar ieliekamajām austiņām otra cilvēka balss izplūst no austiņas un atpakaļ mikrofonā. Tāpēc bez rūpības viņa atbalss, kas nonāk tavā mikrofona kanālā, tiek piedēvēta tev. Labojums ir atbalsij pielāgotu sliekšņu kopums: kad sistēmas audio atskaņojas virs neliela minimuma, latiņa, kas tavam mikrofonam jāpārvar, lai to ieskaitītu kā "tu runā", strauji paceļas — no normālā 0.015 līdz 0.1. Citiem vārdiem: kamēr otrs cilvēks runā, tavam mikrofonam jābūt skaidri un nepārprotami skaļākam par viņa atbalsi, pirms mēs piedēvēsim vārdus tev. Neskaidri kadri pēc noklusējuma tiek attiecināti uz "sistēmu", pieņemot, ka tie ir atbalss. Tā ir apzināta nosliece, kas iegūst pareizu piedēvēšanu tieši tajā situācijā, kas agrāk to ieguva nepareizi.
Šis koncepcijas pierādījums — mono miksēšana plus uz enerģiju balstīta, atbalsij pielāgota balss noteikšana — ir tās piedēvēšanas sistēmas priekštecis, ko GeekBye izmanto šodien. Sastatnes tika izrautas tajā pašā relīzē, tiklīdz tās sevi pierādīja, un enerģijas matemātika vēlāk nostabilizējās kā pienācīgi testēts modulis. Bet v1.6.12 ir tur, kur šī ideja piedzima — zem spiediena, lietotāja ar ieliekamo austiņu pāri.
Trīs lietas, ko iemācīja austiņu kļūda
- Vesels rokturis var nest mirušus datus. Visa izmeklēšana pagriezās uz to, ka uzticējāmies savam enerģijas mērītājam, nevis platformas statusa karodziņiem —
live,enabled,unmuted, visi meloja, kamēr paraugi bija nulles. Uzraugi saturu, nevis API pašziņojumu. Ja plūsma apgalvo, ka ir kārtībā, izmēri, vai tā tiešām ir. - Kad platforma cīnās pret tavu arhitektūru, maini arhitektūru — nevis platformu. Mēs nespējām pārstrīdēt Chromium atgriezeniskās saites aizsardzību, un katrs mēģinājums to atspējot pa malām neizdevās vai atspēlējās. Novēršot novērojamo nosacījumu — divas plūsmas kļūst par vienu — visa problēma pazuda. Gandrīz vienmēr ir lētāk novērst izraisītāju, nekā uzvarēt cīņā ar pārlūku.
- Kad sabruc kanālus izturības labad, tev jāatjauno tas, ko iznīcināji. Sajaukšana mono iznīcināja kanālu atdalīšanu, kas nesa "kurš runāja". Šī informācija bija jāatvasina no pirms-miksēšanas enerģijas un atbalsij pielāgotiem sliekšņiem. Kompensējošā loģika nav labojuma pēcdoma — tā ir puse no labojuma.
Šī ir ceturtā nodaļa tajā izturības stāstā, kas kļūst par GeekBye v2. Iepriekšējo nodaļu skati nomestam savienojumam nevajadzētu sagraut visu tavu lietotni (v1.6.8); par cauruļvada pārrakstīšanu, uz kuras šis audio darbs balstījās, mēs izdzēsām 5000 rindu audio koda (v1.6.0); un par visu loku anatomija tam, kā piegādāt programmatūru līdz pilnībai.