Steven
Steven7 minit bacaan

Kesenyapan Itu Menanggung Beban

Dua keluaran terakhir GeekBye v1 membicarakan kebenaran tidak selesa yang sama: transkripsi masa nyata di atas rangkaian sebenar tidaklah tanpa kehilangan, dan langkah jujurnya ialah berhenti berpura-pura seolah-olah begitu. v1.8.20 menyimpan satu salinan setiap chunk audio ke cakera sebelum membuangnya semasa satu reconnect, dan mula menandakan jurang-jurang dalam transkrip secara terbuka. v1.9.0 berhenti menghantar kesenyapan demi menjimatkan lebar jalur — dan mendapati bahawa kesenyapan itu ialah isyarat tepat yang digunakan transkriber untuk tahu bahawa satu ayat telah tamat. Dua keluaran tentang kos membuang sesuatu.

Kejuruteraan
Audio
Kebolehpercayaan
GeekBye Releases
Kesenyapan Itu Menanggung Beban

Dua keluaran terakhir GeekBye v1 — v1.8.20 dan v1.9.0, yang tepat sebelum tonggak versi 2 — berkongsi satu tema yang hanya menjadi jelas apabila anda membacanya bersama-sama. Kedua-duanya tentang perkara-perkara yang dibuang aplikasi secara senyap, dan kedua-duanya tiba pada kesimpulan yang sama: perkara yang anda buang demi kecekapan rupa-rupanya melakukan lebih banyak kerja daripada yang anda sangka. Satu keluaran membuang audio semasa reconnect rangkaian. Satu lagi membuang kesenyapan demi menjimatkan lebar jalur. Dalam kedua-dua kes, perkara yang dibuang rupa-rupanya menanggung beban.

Transkripsi masa nyata tidaklah tanpa kehilangan, dan v1.8.20 mengakuinya

Inilah satu fakta tentang speech-to-text strim di atas satu WebSocket yang mudah dipandang lepas: apabila sambungan terputus dan bersambung semula — atau apabila aplikasi beralih gagal daripada satu pembekal transkripsi ke pembekal lain, Deepgram ke ElevenLabs — klien sengaja membuang chunk audio yang ditangkap semasa jurang itu. Ia terpaksa. Satu pembekal yang baharu bersambung yang tiba-tiba menerima satu longgokan audio basi akan tercekik, atau lebih teruk, mengunci pengesan aktiviti-suaranya pada perkara yang salah. Jadi klien membuang chunk-chunk itu.

Masalahnya bukan pembuangannya. Masalahnya ialah apa yang dahulunya dimaksudkan oleh pembuangan: perkataan-perkataan itu langsung tidak pernah muncul dalam transkrip, dan tiada apa-apa yang memberitahu anda bahawa ia hilang. Rakaman itu kelihatan lengkap. Ia tidak lengkap.

v1.8.20 menyerang itu di dua barisan hadapan, dan tiada satu pun daripadanya ialah "pastikan reconnect tidak pernah kehilangan audio" — kerana anda tidak boleh, tidak dalam masa nyata. Sebaliknya ia menjadikan kehilangan itu boleh dipulihkan dan jujur.

Separuh yang boleh dipulihkan ialah satu tee PCM yang tahan lama. Dalam pengendali tangkapan proses-utama, setiap chunk yang ditangkap kini ditulis ke satu fail pada cakera sebelum ia mencapai pintu pembuangan reconnect dan tempoh-belas-kasihan:

every captured chunk is written to <userData>/sessions/session-<ts>.wav before realtime drop gates so reconnect-lost audio is preserved for a future batch-STT reconciliation pass

Mekanismenya menyenangkan kerana rendah-teknologi: teeChunkToDisk membuka satu WriteStream, menempah di hadapan satu pengepala WAV 44-bait, menambah sampel mono 16-bit mentah sebaik ia tiba, dan menampal pengepala dengan saiz akhir semasa berhenti (fs.openSync(..., 'r+'), tulis 44 bait pada offset 0). Hasilnya ialah satu WAV yang boleh dimainkan bagi audio lengkap — termasuk bahagian-bahagian yang tidak pernah dilihat transkrip masa nyata. Apabila rakaman tamat ia memancarkan satu peristiwa session-audio-saved dengan laluan fail dan bilangan bait.

Dua nota kejujuran penting di sini, kerana mudah untuk melebih-lebihkan ini. Pertama: tee tidak mengisi jurang itu dalam keluaran-keluaran ini. Ia memelihara audio mentah untuk satu laluan penyelarasan kemudian — satu transkripsi-semula kelompok yang menyelaraskan fail dengan transkrip langsung — yang merupakan satu cangkuk yang diletakkan oleh keluaran-keluaran ini, bukan satu ciri yang mereka keluarkan. Commit susulan itu malah menganotasi session-audio-saved dengan satu TODO yang menuding ke isu-isu penyelarasan supaya tiada siapa tersilap menyangkanya sebagai kod mati. Kedua: ini memakan cakera. Pasukan menganggarkan lebih kurang 86 MB per rakaman 30 minit, jadi keluaran yang sama menambah satu StartupCleanupService yang memangkas sesi tersimpan yang lebih lama daripada 7 hari. Satu jaring keselamatan yang membesar tanpa had ialah satu kebocoran; pembersihan itulah yang menjadikan tee boleh dikeluarkan.

Separuh yang jujur pula lebih ringkas lagi. Pada percubaan reconnect pertama, klien menulis satu entri sebenar dan kelihatan ke dalam transkrip:

[reconnecting — audio may be missing]

Satu baris itu ialah keseluruhan falsafah keluaran itu dalam bentuk miniatur. Aplikasi tidak boleh menjamin bahawa ia mendengar segala-galanya, jadi ia berhenti membayangkan bahawa ia begitu. Satu jurang yang boleh anda lihat ialah satu jurang yang boleh anda tangani; satu jurang yang tidak boleh anda lihat ialah satu laporan pepijat yang menunggu untuk berlaku.

v1.9.0: kesenyapan yang anda optimumkan-buang itu ialah isyaratnya

v1.9.0 ialah keluaran v1 terakhir, dan di situlah backend menyerahkan satu set tanggungjawab transkrip-langsung kepada klien — membuang kesenyapan, mengaitkan setiap baris transkrip kepada audio mik atau sistem daripada satu garis masa aktiviti-suara tempatan, memiliki gelung reconnect, menguatkuasakan had rakaman. Kebanyakan daripada itu ialah kerja asas untuk seni bina versi-2 dan telah diceritakan di tempat lain. Tetapi satu bebenang di dalamnya ialah kisah kecil terbaik dalam mana-mana daripada dua keluaran itu, kerana ia satu pembetulan yang terpaksa membatalkan kerosakan daripada satu pengoptimuman yang betul sepenuhnya secara berasingan.

Ia bermula dengan satu perubahan yang jelas-jelas baik: berhenti menghantar kesenyapan. Klien mula menapis keluar chunk yang sumber dominannya ialah kesenyapan sebelum menghantarnya melalui soket — kurang lebar jalur, kurang audio yang tidak berguna untuk backend proses, dan ia menghormati satu kontrak-klien backend yang eksplisit yang berkata "jangan hantar kesenyapan." Setiap sebab untuk melakukannya adalah kukuh.

Dan ia merosakkan pemuktamadan utterance sepenuhnya. Commit yang membetulkannya membentangkan rantai sebab-akibat dengan keterusterangan yang luar biasa:

After the client began filtering silence chunks … ElevenLabs Scribe's VAD-based commit strategy no longer fires — EL needs ~1s of silence in the audio stream to commit a partial, and that silence never reaches it. Result: partials accumulate forever, UI shows trailing "...", utterances never finalize.

Ini ialah bentuk platonik satu abstraksi bocor yang menggigit balik. Pengesan aktiviti-suara si transkriber tidak mempunyai satu input "penutur telah selesai" yang berasingan — ia membuat kesimpulan tentang penghujung satu ayat daripada mendengar lebih kurang satu saat kesenyapan dalam audio. Kesenyapan bukanlah bunyi bising pada talian; ia satu mesej. Dengan menapisnya keluar demi menjimatkan lebar jalur, klien tanpa sengaja berhenti menghantar satu-satunya isyarat yang memberitahu transkriber bahawa satu ayat telah tamat. Jadi setiap transkrip separa terus sahaja membesar, ekornya melarut menjadi satu ... yang tidak pernah selesai.

Anda boleh membetulkan ini dengan meletakkan semula kesenyapannya — tetapi kemudian anda telah membatalkan pengoptimuman itu. Pembetulan sebenar lebih baik: hantar makna kesenyapan tanpa menghantar kesenyapannya. Klien kini menjejaki berapa lama audio telah senyap secara tempatan, dan apabila itu melepasi SILENCE_COMMIT_THRESHOLD_MS = 1000 — sengaja dipadankan dengan ambang kesenyapan VAD milik backend sendiri — ia menembak satu isyarat commit yang eksplisit di luar-jalur: sendMixedChunk menyedari kesenyapan berterusan itu, menghantar satu realtime-audio:commit melalui IPC, proses utama memajukan satu { type: 'commit' } pada soket, dan backend memberitahu ElevenLabs untuk memuktamadkan separa itu. Dua keping kecil keadaan, silenceStartedAt dan silenceCommitFired, menghalangnya daripada menembak berulang kali. Kemenangan lebar jalur terus hidup; pemuktamadan berfungsi semula; ... hujung itu selesai.

Ada juga satu nota kaki kecil yang jujur untuk keluaran ini: logik reconnect tanpa had yang diperkenalkan v1.9.0 mula-mula dibina dalam renderer sebagai satu WsReconnectController, kemudian dipadamkan dalam keluaran yang sama sebaik pelaksanaan sebenar mendarat dalam pengendali proses-utama tempat ia sepatutnya berada. Kisah reconnect itu sendiri — undur tanpa had, pembekal berselang-seli setiap lima kegagalan — diceritakan dalam babnya sendiri; yang ditambah v1.9.0 ialah bahawa di situlah seni bina itu dilahirkan, dan tempat klien pertama kali mengambil pemilikannya.

Tiga perkara yang keluaran ini ajarkan

  1. Apabila anda tidak boleh mencegah kehilangan, jadikan ia boleh dipulihkan dan jadikan ia kelihatan. v1.8.20 tidak menghentikan reconnect daripada membuang audio — itu tidak mungkin secara fizikal dalam masa nyata. Ia menyimpan satu salinan audio mentah untuk kemudian, dan ia melabelkan jurang itu dalam transkrip. Tiada satu pun yang menawan; bersama-sama ia menukarkan kehilangan data yang senyap menjadi satu keadaan yang diketahui, terbatas, dan boleh dipulihkan.
  2. Satu jaring keselamatan memerlukan hadnya sendiri. Tee tahan lama itu akan mengisi cakera secara senyap jika dibiarkan — satu pembetulan yang menjadi satu pepijat gerak-perlahan. Pembersihan 7-hari yang dikeluarkan dalam keluaran yang sama bukanlah fikiran kemudian; ia perkara yang menjadikan tee selamat untuk dikeluarkan sama sekali. Jika anda menambah satu mekanisme yang menimbun, tambah mekanisme yang memangkasnya dalam nafas yang sama.
  3. Perkara yang anda buang demi kecekapan mungkin satu isyarat. Pelajaran paling tajam dalam mana-mana daripada dua keluaran itu: menapis keluar kesenyapan adalah betul pada setiap paksi yang biasanya anda periksa — lebar jalur, beban, pematuhan kontrak — dan ia tetap merosakkan produk, kerana satu sistem hiliran sedang membaca makna ke dalam kesenyapan. Apabila anda mengeluarkan data demi kecekapan, tanya apa yang sedang membuat kesimpulan tentang sesuatu daripada data itu. Kadangkala anda terpaksa menghantar maknanya secara eksplisit justeru kerana anda berhenti menghantar perkara yang dahulunya daripadanya makna itu disimpulkan.

Dan itulah penghujung kisah versi-1 — pengukuhan terakhir sebelum penulisan semula. Untuk bab sebelumnya, tiga kata kerja yang memastikan web audio terus hidup (v1.8.16 + v2.0.2); untuk ke mana semua ini menuju, apa yang sebenarnya diperlukan oleh satu versi 2: 206 commit (v2.0.0); dan untuk keseluruhan lengkungnya, anatomi mengeluarkan perisian hingga ke kesempurnaan.

Artikel Berkaitan

Tiga Kata Kerja yang Memastikan Web Audio Terus Hidup
Steven
Steven8 minit bacaan

Tiga Kata Kerja yang Memastikan Web Audio Terus Hidup

Dua keluaran titik GeekBye, berselang dua bulan dan dalam dua fail berbeza, mengajar kod audio kami pelajaran yang sama daripada hujung yang bertentangan: berhenti memperlakukan AudioContext pelayar sebagai barangan sekali guna. Satu keluaran belajar untuk resume() satu context yang telah macOS gantung secara senyap di tengah rakaman; satu lagi belajar untuk suspend() dan bukan close() supaya sesi berturut-turut berhenti melanggar siling kira-kira enam context milik Chromium. Resume, suspend, close — itulah keseluruhan jalan ceritanya.

Kejuruteraan
Audio
Desktop
Sambungan yang Terputus Tidak Sepatutnya Merosakkan Seluruh Aplikasi Anda — Tetapi Aplikasi Kami Ya
Steven
Steven6 minit bacaan

Sambungan yang Terputus Tidak Sepatutnya Merosakkan Seluruh Aplikasi Anda — Tetapi Aplikasi Kami Ya

Apabila backend kami luar talian di tengah-tengah mesyuarat, ia bukan sekadar menjeda transkripsi — ia merosakkan seluruh aplikasi. Puncanya ialah satu peristiwa yang tidak dikendalikan, dan pembaikannya hanya sepuluh baris. Inilah kelompok keluaran yang membuatkan GeekBye kekal log masuk dan kekal bersambung menerusi perkara-perkara yang dahulunya membunuhnya.

Kejuruteraan
Kebolehpercayaan
Electron
Pemeriksaan Keselamatan yang Menjadikan Aplikasi Kami Mustahil Ditutup
Steven
Steven5 minit bacaan

Pemeriksaan Keselamatan yang Menjadikan Aplikasi Kami Mustahil Ditutup

Kemas kini automatik ialah ciri paling sukar yang pernah kami keluarkan — enam keluaran dalam empat hari untuk menghalangnya daripada merosakkan aplikasi. Pepijat paling teruk ialah yang kami sendiri perkenalkan ketika cuba berhati-hati: pemeriksaan "keselamatan" 500 milisaat yang menukar kemas kini gagal menjadi proses yang benar-benar tidak boleh anda tutup.

Kejuruteraan
Electron
Kebolehpercayaan