Bloga dön
19 Ekim 2026Sergei Solod18 dk okuma

Whisper ve WebAssembly ile Web Sitesine Gizliliği Koruyan Sesli Yazma Nasıl Eklenir?

Whisper, Transformers.js, ONNX Runtime Web, AudioWorklet ve WebAssembly ile tamamen istemci tarafında sesli yazma oluşturun. Mobil performansı iyileştirmeyi ve konuşma tanımayı engelleyen yürütme ortamı, worker ve tokenizer hatalarını gidermeyi öğrenin.

Konuşmadan Metne DönüştürmeWhisperWebAssemblyAudioWorkletJavaScript

Bir web sitesine mikrofon düğmesi eklemek kolay görünür: kullanıcının sesini kaydetmek, söylenenleri tanımak ve metni bir giriş alanına yerleştirmek. Ancak bunu masaüstü ve mobil tarayıcılarda güvenilir biçimde çalıştırmak çok daha zordur; özellikle de ses tanımanın tamamı, mikrofon sesi sunucuya yüklenmeden yerel olarak gerçekleştirilmek zorundaysa.

Asıl güçlük yalnızca bir konuşma tanıma modeli seçmek değildir. Çalışan bir uygulamanın mikrofon izinlerini, ses yakalamayı, yeniden örneklemeyi, tarayıcı worker'larını, WebAssembly'yi, ONNX modelinin başlatılmasını, tokenleştirmeyi, önbelleğe almayı ve uygulamanın metin alanıyla bütünleşmeyi doğru yönetmesi gerekir.

Bu yazı, OpenAI Whisper, Transformers.js, ONNX Runtime Web, AudioWorklet ve özel bir Web Worker kullanarak gizliliği koruyan, pratik bir konuşmadan metne dönüştürme özelliğinin nasıl oluşturulacağını anlatıyor. Model dosyaları başarıyla indirilmiş olsa bile mikrofon düğmesinin yükleniyor durumunda takılı kalmasına neden olabilen gerçek entegrasyon hatalarını da ele alıyor.

Hedef basit: Ziyaretçi mikrofon düğmesine basar, doğal biçimde konuşur ve tanınan metnin mevcut giriş alanında belirdiğini görür. Göndermeden önce sonucu inceleyip düzenleyebilir. Mikrofon kaydının tarayıcıdan çıkması gerekmez.

Tamamen istemci tarafında konuşma tanıma ne demektir?

Bir web sitesine sesli giriş eklemenin temelde iki farklı yolu vardır.

İlk yöntemde bir konuşma tanıma hizmeti kullanılır. Tarayıcı sesi kaydeder, uzak bir hizmete gönderir ve tanınan metni alır. Uygulamayı kolaylaştırabilir ancak ağ bağımlılığı, gizlilikle ilgili konular, hizmet sağlayıcının erişilebilirliği ve kullanıma bağlı olası maliyetler doğurur.

İkinci yöntemde çıkarım doğrudan tarayıcıda yapılır. Site, konuşma tanıma modelini ve onu çalıştırmak için gereken yürütme ortamını indirir. Tarayıcı mikrofon sesini alır, sayısal örneklere dönüştürür, modeli yerel olarak çalıştırır ve bir konuşma tanıma sunucusu olmadan dökümü üretir.

Bu yazı yalnızca ikinci yönteme odaklanıyor.

Tarayıcının standart konuşma tanıma işlevini, yerel olarak çalıştığı garanti edilen tanımayla karıştırmamak gerekir. Web Speech API sunucu destekli bir tanıma motoru kullanabilir. Bazı yeni uygulamalar processLocally seçeneğini sunsa da destek tarayıcıya ve işletim sistemine göre değişir. Kesinlikle yerel işleme gerekiyorsa genel SpeechRecognition otomatik yedek yöntem olarak kullanılmamalıdır.

Bunun yerine uygulama, çıkarım hattının tamamını kendi denetimi altında tutar.

Microphone
    |
    v
AudioWorklet
    |
    v
Float32 PCM audio
    |
    v
Dedicated Web Worker
    |
    v
16 kHz resampling
    |
    v
Whisper + ONNX Runtime Web
    |
    v
Tokenizer and text decoding
    |
    v
React input state

Site yine de JavaScript, WebAssembly, yapılandırma dosyaları ve model ağırlıklarını sunar. Bunlar normal statik indirmelerdir. Önemli fark, mikrofon sesinin tanıma amacıyla yüklenmek yerine yerel olarak işlenmesidir. Kullanıcı daha sonra ortaya çıkan metni normal bir formla gönderirse bu, uygulamanın ayrı bir işlemidir.

Pratik bir model seçmek: Whisper Tiny mi, Base mi?

Whisper, çok dilli bir konuşma tanıma model ailesidir. Tek modelle birçok dili tanıyabilmesi, onu çok dilli web siteleri için özellikle kullanışlı kılar.

Kısa sesli mesajlarda iki model, tanıma kalitesi ile tarayıcı kaynak tüketimi arasında yararlı bir denge sunar: Whisper Tiny ve Whisper Base.

ModelSeçilen Q8 ONNX ağırlıklarının yaklaşık boyutuÖnerilen kullanım
Whisper Tiny41 MBMobil ve kaynakları kısıtlı cihazlar için temkinli seçenek
Whisper Base77 MBTest edilmiş, yeterli güce sahip cihazlarda daha yüksek kalite

Bu boyutlar, incelenen dışa aktarımlardaki seçili kodlayıcı ve kod çözücü ONNX dosyalarını ifade eder. Tüm yardımcı dosyaları içermez ve tarayıcının en yüksek bellek kullanımıyla karıştırılmamalıdır.

Whisper Tiny daha hızlı indirilir, genellikle daha az işlem kaynağı gerektirir ve özellikleri belirsiz mobil ortamlara daha uygundur. Whisper Base ise, özellikle küçük modellerin daha çok hata yaptığı bazı dillerde, genel olarak daha iyi tanıma kalitesi sunar.

Model seçimini yalnızca cihazın fiziksel RAM miktarına dayandırmamak gerekir. Tarayıcının kullanabildiği bellek, cihaz özelliklerinin düşündürdüğünden çok daha az olabilir. Sayfanın mevcut bellek tüketimi, WebAssembly ayırmaları, geçici tensörler ve işletim sisteminin bellek baskısı da önemlidir.

Temkinli bir yaklaşım, özellikleri bilinmeyen mobil cihazlarda Tiny ile başlamak, Base'i yeterliliği doğrulanmış cihaz sınıflarına ayırmak ve model başlatılamazsa Base'den Tiny'a geçmektir.

Başlatılamayan Base örneği, Tiny yüklenmeden önce serbest bırakılmalıdır. İki modeli aynı anda bellekte tutmak yedek modele geçmenin amacını boşa çıkarır.

WebAssembly neden üretim ortamı için mantıklı bir varsayılandır?

ONNX Runtime Web, sinir ağlarının tarayıcıda çalıştırılmasını destekler. Bu iş yükünde WebAssembly, başlıca masaüstü ve mobil tarayıcılarda CPU üzerinden çıkarım için pratik bir yol sağlar.

WebGPU uygun donanımlarda desteklenen modelleri hızlandırabilir; ancak kullanılabilir olması, çalışan bir konuşma tanıma hattı bulunduğu anlamına gelmez. Tarayıcının navigator.gpu sunması, ONNX Runtime'ın platformu desteklediğini, belirli Whisper grafiğinin doğru başladığını veya tekrarlanan çıkarımların kaynak sorunları yaratmadığını garanti etmez.

Bu nedenle temkinli bir uygulama, üretimde WASM'ı arka uç olarak kullanabilir ve WebGPU'yu uyumluluk, doğruluk, bellek ve tekrarlanan oturum testlerinden sonra ayrıca değerlendirebilir.

İlk sürümde tek iş parçacıklı WASM kullanmak, sitenin tamamını farklı kaynaklar arasında yalıtıma ve SharedArrayBuffer'a bağımlı kılmaktan da kaçınır.

env.backends.onnx.wasm.numThreads = 1;
env.backends.onnx.wasm.proxy = false;

Çıkarımı özel bir worker içinde çalıştırmak, ağır hesaplamayı ana JavaScript iş parçacığından uzak tutar. Model sesi işlerken metin alanı, sanal klavye, kaydırma ve uygulama arayüzü yanıt vermeye devam eder.

Konuşma tanımayı ilk sayfa yüklemesinden tamamen uzak tutun

Mikrofon özelliği, onu hiç kullanmayan ziyaretçilere önemli bir ağ ve bellek yükü getirmemelidir.

Transformers.js'yi uygulamanın ilk paketine önceden dahil etmeyin. Sayfa açıldığında ONNX Runtime'ı başlatmayın ve boşta kalma sırasında model ağırlıklarını otomatik olarak indirmeyin.

Bunun yerine tanıma bileşenlerini ancak kullanıcı mikrofon düğmesine açıkça tıkladıktan sonra yükleyin.

İlk kullanımda izlenebilecek uygun sıra şöyledir:

  1. Mikrofon düğmesine tıklanmasını alın.
  2. getUserMedia() ile mikrofon izni isteyin.
  3. İzin reddedilirse modeli indirmeden hata gösterin.
  4. İzin verilirse model hazırlanırken geçici mikrofon akışını serbest bırakın.
  5. Özel worker'ı dinamik olarak başlatın ve seçilen yerel modeli yükleyin.
  6. Worker'ın tanıma hattının hazır olduğunu onaylamasını bekleyin.
  7. Kullanıcı işlemi iptal etmemişse kaydı otomatik başlatın.
  8. Anlaşılır bir dinleme durumu gösterin.

İzin isteği kullanıcının etkileşimiyle bağlantılı olmalıdır. Uygulama, kaydın her zaman sessizce yeniden başlatılabileceğini varsaymak yerine iptalleri ve tarayıcıya özgü ses yakalama kısıtlarını da ele almalıdır.

Model hazırlanırken Sesli giriş hazırlanıyor gibi görünür bir durum gösterilmelidir. Anlamlı bir durum değişikliği olmadan dönen bir yükleme simgesi, model başarıyla indirilse bile mikrofon bozulmuş izlenimi yaratabilir.

Başlatılan worker, sonraki bir dikte için kısa süre hazır tutulabilir. Yaklaşık bir dakikalık boşta kalma zaman aşımı makul bir başlangıç noktasıdır. Sonrasında worker'ı sonlandırın ve bellekteki modelini serbest bırakın. Tarayıcının önbelleğine alınan model dosyaları sonraki ziyaretlerde kullanılabilir.

AudioWorklet ile ham ses yakalama

Whisper sayısal ses örnekleri gerektirir. MediaRecorder ses dosyaları kaydetmek için çok iyi olsa da yerel konuşma tanımada kullanılması gereksiz bir kodlama ve kod çözme döngüsü ekleyebilir.

Daha basit işleme yolu şöyledir:

getUserMedia()
    |
    v
AudioContext
    |
    v
AudioWorklet
    |
    v
Float32 PCM buffers
    |
    v
Dedicated Worker

AudioWorklet, ses işleme kodunu uygulamanın ana JavaScript iş parçacığı dışında çalıştırır. PCM örneklerini yakalayabilir, çok kanallı girdiyi tek kanala indirebilir, basit ses düzeyi ölçümleri hesaplayabilir ve biriktirilen tamponları worker'a aktarabilir.

Basitleştirilmiş bir mikrofon başlatma örneği:

const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    channelCount: { ideal: 1 },
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true,
  },
});

const context = new AudioContext();

await context.audioWorklet.addModule(
  '/assets/speech/pcm-worklet.js'
);

const source = context.createMediaStreamSource(stream);
const processor = new AudioWorkletNode(
  context,
  'pcm-capture'
);

source.connect(processor);

// Connect the worklet through an inaudible output path
// if required to keep the audio processing graph active.

Mikrofon kısıtları garanti değil, tercih belirtir. Tarayıcılar yankı giderme, gürültü bastırma ve otomatik kazanç denetimi için farklı algoritmalar uygulayabilir.

Önemli bir ayrıntı: Mikrofonun örnekleme hızı mutlaka 16 kHz değildir. Birçok ses bağlamı 44.1 kHz veya 48 kHz kullanır. Whisper 16 kHz giriş beklediği için yakalanan örneklerin doğru biçimde yeniden örneklenmesi gerekir.

Her ikinci ya da üçüncü örneği atmak genel olarak doğru bir çözüm değildir. Pencereli sinc yöntemi gibi uygun bir alçak geçiren yeniden örnekleyici, örnekleme hızını düşürürken örtüşmeyi azaltır ve konuşmanın yararlı frekanslarını korur.

Yeniden örnekleme işlemini gerçek zamanlı AudioWorklet geri çağrısında değil, özel worker'da tutun.

Tarayıcı iş parçacıkları arasında sesi verimli aktarma

AudioWorklet çok sayıda küçük ses parçası üretebilir. Her ses işleme kuantumunu ayrı bir mesaj olarak iletmek gereksiz ek yüke neden olabilir.

Pratik bir yöntem, kısa PCM parçalarını biriktirip her grubu ArrayBuffer olarak aktarmaktır.

worker.postMessage(
  {
    type: 'audio-chunk',
    buffer,
  },
  [buffer]
);

Aktarım listesi önemlidir: ArrayBuffer'ın tamamını gereksiz yere kopyalamak yerine sahipliğini aktarır.

Worker bu parçaları bir ses biriktiricisinde toplayabilir ve kayıt durduğunda birleştirebilir.

Gerçek yakalama örnekleme hızını, toplanan örnek sayısını ve kayıt süresini izlemek de yararlıdır. Bu üstveriler, hassas ses verilerini günlüğe yazmadan sessiz kayıtları teşhis etmeye yardımcı olur.

Başka bir sinir ağı eklemeden duraklamaları algılama

Kısa metin mesajlarını dikte etmek için mutlaka sinir ağı tabanlı bir ses etkinliği algılayıcısı gerekmez.

Uyarlanabilir bir RMS algılayıcısı, konuşma etkinliğini düşük maliyetle yaklaşık olarak belirleyebilir. RMS sinyal genliğini ölçer; böylece uygulama, daha önce konuşan bir kişinin ne zaman sessizleştiğini tahmin edebilir.

Arayüz, mikrofon düğmesine ikinci kez basarak kaydı elle durdurmayı her zaman desteklemelidir. Sessizliğin otomatik algılanması kullanışlı bir ek özelliktir; başarılı tanıma için zorunlu değildir.

Kısa dikte için makul başlangıç değerleri şunlardır:

ParametreBaşlangıç değeri
Analiz aralığı20 ms
Gürültü kalibrasyonu300 ms
Konuşma doğrulaması140 ms
Otomatik durdurmadan önceki sessizlik1.4 saniye
Konuşma olmadan zaman aşımı8 saniye
En uzun kayıt süresi30 saniye

Bunlar evrensel olarak en iyi eşikler değil, yapılandırma için başlangıç değerleridir. Kısık sesle konuşma, arka plan müziği ve mikrofonun gürültü işleme biçimi RMS ölçümlerini etkileyebilir.

Cümlenin son sözcüklerini otomatik olarak kesmektense kullanıcının kaydı elle durdurmasına öncelik verin.

Sıradan kısa metin girişlerinde tek seferlik döküm oluşturmak, ara sonuçlar için Whisper'ı tekrar tekrar çalıştırmaktan genellikle daha basittir. Konuşmayı kaydedin, kaydı durdurun, modeli bir kez çalıştırın ve nihai dökümü yerleştirin.

Eksiksiz bir Whisper hattı için ONNX modelinden fazlası gerekir

Bu, uygulamadaki en önemli ayrıntılardan biridir.

Whisper ile çıkarım, yalnızca bir ONNX kodlayıcısını ardından bir ONNX kod çözücüsünü çağırmaktan ibaret değildir. Eksiksiz bir otomatik konuşma tanıma hattı; ses özelliklerinin çıkarılmasını, tokenleştirmeyi, üretim yapılandırmasını ve tahmin edilen token'ların okunabilir metne dönüştürülmesini de gerektirir.

İşlemlerin tamamı şu sırayla gerçekleşir:

Raw microphone PCM
        |
        v
Resampling to 16 kHz
        |
        v
Whisper feature extractor
        |
        v
ONNX encoder
        |
        v
ONNX decoder and token generation
        |
        v
Whisper tokenizer
        |
        v
Recognized text

ONNX oturumunun başarıyla başlatılması yalnızca model grafiğinin yüklenebildiğini gösterir. Tanıma hattının tamamının çalıştığını kanıtlamaz.

Test edilen bir Transformers.js entegrasyonunda model oturumları başlatılabiliyordu; ancak yerel olarak oluşturulan hatta gerekli işlemci ve tokenizer doğru yapılandırılmadığından döküm üretimi yine başarısız oluyordu.

Uyumlu uygulama, bu bileşenleri yerel model üstverilerini kullanarak açıkça başlattı.

Aşağıdaki örnek, sürüme özgü yaklaşımın kısaltılmış gösterimidir; tek başına çalışacak eksiksiz bir worker değildir:

import {
  WhisperTokenizer,
  WhisperFeatureExtractor,
  WhisperProcessor,
} from '@huggingface/transformers';

// These values come from local model configuration files.
const tokenizer = new WhisperTokenizer(
  tokenizerJson,
  tokenizerConfig
);

const featureExtractor = new WhisperFeatureExtractor(
  preprocessorConfig
);

const processor = new WhisperProcessor(
  {},
  {
    tokenizer,
    feature_extractor: featureExtractor,
  },
  ''
);

// In the affected version-specific integration:
recognizer.tokenizer = tokenizer;
recognizer.processor = processor;

Kurucu işlevlerin tam imzaları ve bütünleştirme yöntemi, kurulu Transformers.js sürümüne göre doğrulanmalıdır. Bazı sürümler ve model dışa aktarımları bu bileşenleri otomatik olarak oluşturabilir; elle oluşturma her durumda zorunlu kabul edilmemelidir.

Eksiksiz hat hazır olduğunda, kısa kayıtların dökümü dil ve görev açıkça belirtilerek alınabilir:

const result = await recognizer(audio16k, {
  language: 'en',
  task: 'transcribe',
  return_timestamps: false,
});

Uygulama kullanıcının dilini zaten biliyorsa bunu açıkça geçirmek gereksiz dil algılamasını önler ve kısa kayıtların daha öngörülebilir işlenmesini sağlayabilir.

Uyumlu Transformers.js ve ONNX Runtime sürümlerini sabitleyin

İkinci önemli hata türü, Transformers.js ile ONNX Runtime Web arasındaki ilişkiyle ilgilidir.

Transformers.js üst düzey tanıma hattını sağlarken ONNX Runtime Web sinir ağı grafiklerini çalıştırır. Bu paketlerin hem birbiriyle hem de kullanılan belirli ONNX model dışa aktarımlarıyla uyumlu olması gerekir.

İncelenen uygulamada ONNX Runtime Web'in bir geliştirme sürümü Whisper kodlayıcısını başlatıyor, ancak nicemlenmiş kod çözücü oturumunu oluştururken hata veriyordu. Hata, DequantizeLinear işleminde eksik bir nicemleme ölçeğiyle ilgiliydi.

Sorun mikrofon izni, indirme ya da ses biçimiyle ilgili değildi. Tarayıcı model dosyalarını alabiliyor, ancak yürütme ortamı gerekli model grafiklerinden birini başlatamıyordu.

Hem kodlayıcıyı hem de kod çözücüyü sabitlenmiş kararlı bir ONNX Runtime Web sürümüyle doğrudan test etmek, bu belirli uyumsuzluğu giderdi.

Uyumluluk kontrolü özellikle değerliydi; çünkü iki ayrı iddiayı birbirinden ayırdı:

  • Model dosyası başarıyla indirildi.
  • Yürütme ortamı model dosyasından kullanılabilir bir çıkarım oturumunu başarıyla oluşturdu.

Bunlar aynı şey değildir.

Test edilen model dışa aktarımlarında Transformers.js 4.2.0 ile ONNX Runtime Web 1.24.3 uyumlu bir ikili oluşturdu. Daha yeni bir geliştirme sürümü, nicemlenmiş kod çözücü grafiğinde başarısız oldu. Bu gözlem söz konusu sürümlere özgüdür; eski sürümlerin her zaman daha iyi olduğunu göstermez.

Dolaylı bir yürütme bağımlılığının sürümünü geçersiz kılıyorsanız tam sürümü paket kilit dosyasında sabitleyin ve nedenini belgeleyin. Yürütme ortamını yükseltmek yalnızca paket kurulumunun başarılı olmasına değil, tarayıcıda uçtan uca çıkarım regresyon testinin geçmesine bağlı olmalıdır.

Whisper'da hata ayıklamadan önce worker paketinin biçimini kontrol edin

Bir JavaScript Web Worker farklı modül biçimleriyle oluşturulabilir.

Entegrasyon hatalarından biri, uygulamanın worker'ı ES modülü olarak başlatmasına karşın üretilen worker paketinin klasik worker mekanizması olan importScripts() kullanmasından kaynaklandı.

Bu yürütme modelleri birbirinin yerine kullanılamaz. Modül worker'ı yalnızca klasik worker'a uygun kodu doğrudan çalıştıramaz.

Pratik ders, genel bir öğreticiden kurucu seçeneği kopyalamak yerine Worker kurucusunu gerçekten üretilen paketle eşleştirmektir.

Örneğin aşağıdaki seçenekler kendiliğinden eşdeğer değildir:

// Module worker: requires a compatible module bundle.
new Worker(workerUrl, { type: 'module' });

// Classic worker: requires a compatible classic bundle.
new Worker(workerUrl);

Doğru seçim, paketleyiciye ve üretilen JavaScript'e bağlıdır.

Bir worker başlatma hatasını incelerken tarayıcının Console bölümünü, oluşturulmuş worker dosyasını ve Network panelini kontrol edin. Hatanın ONNX Runtime başlatılmaya bile başlamadan önce oluşup oluşmadığını belirleyin.

Paketlenmiş bazı tarayıcı kütüphaneleri URL'leri kendi modül konumlarına göre de hesaplar. Bunları worker içine paketlerken özgün pakete göreli URL'lerin hâlâ doğru çözümleneceğini varsaymak yerine ortaya çıkan yürütme varlığı yollarını test edin.

WASM ve JavaScript modüllerini doğru MIME türleriyle sunun

JavaScript ve ONNX model dosyaları birbirleriyle tamamen uyumlu olsa bile web sunucusu yanlış yanıt başlıkları döndürürse çalışmayabilirler.

Somut bir hatada .mjs uzantılı bir JavaScript modülü application/octet-stream olarak sunuluyordu. Tarayıcı, yanıt türü JavaScript modülü çalıştırmaya uygun olmadığı için modülü reddetti.

Genellikle beklenen yanıt türleri şunlardır:

Dosya uzantısıContent-Type
.mjsapplication/javascript
.wasmapplication/wasm

Yalnızca sunucu yapılandırma dosyasını değil, üretimde dönen gerçek yanıtı kontrol edin.

curl -I https://example.com/runtime/speech/v2/runtime.mjs
curl -I https://example.com/runtime/speech/v2/runtime.wasm

Yukarıdaki URL'ler örnektir. Seçilen yürütme derlemesindeki gerçek, sürümlendirilmiş varlık dosyası adlarını kullanın.

Doğru bir HTTP durumu tek başına yeterli değildir. Tarayıcı; MIME türü, Content Security Policy, modül yürütme biçimi veya yanlış varlık URL'si nedeniyle dosyayı yine de reddedebilir.

Aynı istek, tarayıcı sekmesinde doğrudan açıldığında başarılı olabilir; ancak çalıştırılabilir bir modül veya WebAssembly bağımlılığı olarak yüklendiğinde başarısız olabilir.

Kullanıcıları bozuk yürütme dosyalarına mahkûm etmeden değişmez varlık URL'leri kullanın

Whisper model dosyaları, tarayıcı önbelleğini önemli kılacak kadar büyüktür.

Sürümlendirilmiş, değişmez varlık yolları sayesinde tarayıcı, kullanıcı her konuştuğunda yeniden indirmeden değişmemiş model ve yürütme dosyalarını kullanabilir.

Tipik bir önbellek politikası şöyledir:

Cache-Control: public, max-age=31536000, immutable

Ancak bu, dağıtım için bir zorunluluk getirir: Bir URL değişmez olarak ilan edildikten sonra içeriği sessizce değiştirilmemelidir.

Yürütme ikili dosyasının değişmesi gerekiyorsa onu yeni, sürümlendirilmiş bir URL altında yayımlayın.

/models/speech/v1/
/runtime/speech/v1/
/runtime/speech/v2/

Yürütme yolunu değiştirmek kozmetik bir işlem değildir. Uygulama içeriği değiştirdiği hâlde değişmez URL'yi yeniden kullanırsa tarayıcı daha önce önbelleğe aldığı uyumsuz WebAssembly ikili dosyasını kullanmayı sürdürebilir.

JavaScript bağlayıcı kodunu ve WebAssembly dosyalarını aynı yürütme dağıtımından almak da yararlıdır. Farklı sürümlerin yürütme dosyalarını karıştırmak teşhisi zor başlatma hatalarına yol açabilir.

Beklenen dosyaları, boyutlarını ve kriptografik sağlama toplamlarını içeren derleme zamanı manifestosu, dağıtımdan önce eksik veya uyuşmayan varlıkları tespit edebilir.

Tanıma kütüphanesini birinci taraf varlıklarını kullanacak şekilde yapılandırın ve uzaktan model yüklemeyi kapatın. Böylece yerel model bulunamadığında harici bir model sunucusundan beklenmedik bir indirme başlatmak yerine açık bir hata oluşur.

Hiçbir şey çalışmazken mikrofon neden yükleniyor gösterebilir?

Geliştirme sırasında sık rastlanan bir belirti, mikrofon düğmesinin izin istemesi, yükleme animasyonu göstermesi ve sonunda metin eklemeden hata durumuna dönmesidir.

Tarayıcı, mikrofonun kullanıldığını bile gösterebilir.

Bu, konuşma tanıyıcının çalıştığını kanıtlamaz. Yalnızca mikrofon yakalamaya izin verildiğini veya bir noktada mikrofonun etkin olduğunu gösterir.

Birbirinden bağımsız birkaç hata neredeyse aynı belirtileri doğurabilir:

  1. Yanlış JavaScript modülü MIME türü. Tarayıcı yürütme modülünü indirir ama çalıştırmayı reddeder.
  2. Worker yürütme biçimi uyuşmazlığı. Derlenmiş worker klasik worker API'lerini kullanırken modül worker'ı olarak başlatılır veya bunun tersi olur.
  3. ONNX kod çözücü uyumsuzluğu. Yürütme ortamı kodlayıcı oturumunu oluşturur, ancak nicemlenmiş kod çözücü grafiğinde hata verir.
  4. Eksik tanıma hattı. ONNX oturumları vardır, ancak tokenizer veya ses işlemcisi doğru başlatılmamıştır.

Bu sorunları birbirinden bağımsız olarak teşhis etmek gerekir. Birinin düzeltilmesi diğerini görünür hâle getirebilir.

Hata ayıklamanın en önemli ilkesi şudur: HTTP 200, modelin başarıyla başlatıldığı anlamına gelmez; modelin başarıyla başlatılması da konuşmanın başarıyla metne dönüştürüldüğü anlamına gelmez.

Dökümün başarıyla oluşturulması bile sonucun uygulamanın gerçek metin alanına ulaştığını kanıtlamaz.

Her aşama sınırında anlamlı bir tanılama sinyali bulunmalıdır.

Özel konuşmaları toplamadan gözlemlenebilirlik ekleyin

Yararlı tanılama günlükleri tutmak için kullanıcının söylediklerini kaydetmek gerekmez.

Uygulama şu teknik durumları izleyebilir:

permission-granted
worker-created
runtime-loading
runtime-ready
encoder-ready
decoder-ready
recording-started
pcm-received
recording-stopped
inference-started
inference-completed
result-inserted

Hata durumunda aşamayı, sabit bir teknik hata kodunu ve hassas verilerden arındırılmış hata üstverilerini ekleyin.

Model başlatma hatası, mikrofon izninin reddedilmesinden veya boş bir kayıttan ayırt edilebilmelidir. Worker hatası, genel bir hata işleyicisinde kaybolmak yerine geliştirme sırasında görünür olmalıdır.

Mikrofon örneklerini, tanınan cümleleri, token dizilerini veya konuşmanın başka herhangi bir içeriğini günlüğe yazmayın. Performans telemetrisi; süre aralıklarını, seçilen model düzeyini, başlatma süresini, çıkarım süresini ve hata kategorilerini kullanabilir.

Bu yaklaşım, gizlilik gereksinimlerini zayıflatmadan çalışmayan bir mikrofonun teşhisini çok daha kolaylaştırır.

Dökümü React durumu üzerinden metin alanına ekleyin

Konuşma tanıma, ancak son döküm mevcut form alanına ulaştığında işe yarar.

React uygulamasında bu alan genellikle bileşen durumu tarafından denetlenir. Doğrudan input.value değerini atamak, çatının yeniden işleme davranışıyla çakışabilir.

Bunun yerine tanınan metin, normal yazmada kullanılan aynı durum güncelleme yolundan geçmelidir.

Bütünleştirme, eşzamansız davranışı da hesaba katmalıdır. Kullanıcı yeni karakterler yazdıktan veya imleci taşıdıktan sonra tanıma işlemi tamamlanabilir.

Kayıt başında alınmış eski bir giriş değerini kullanmak, kullanıcının sonraki düzenlemelerini yanlışlıkla üzerine yazabilir.

Basitleştirilmiş bütünleştirme kalıbı şöyledir:

const insertion = insertTranscript({
  currentValue: latestValue,
  transcript: recognizedText,
  selection: currentSelection,
  maxLength: inputLimit,
});

setMessage(insertion.value);
restoreCaret(insertion.caret);

Ekleme yardımcı işlevi mevcut metni korumalı, gerekirse seçili aralığı değiştirmeli, uygun boşlukları eklemeli ve alanın en yüksek uzunluk sınırına uymalıdır.

Unicode'a dikkat edilmelidir; çünkü JavaScript dizge uzunluğu UTF-16 kod birimlerini sayar. Bir dizgeyi rastgele bir konumdan kesmek bir vekil çiftini bölebilir.

En önemlisi, konuşma tanıma işlemi formu asla otomatik göndermemelidir. Kullanıcı, metni göndermeden önce inceleyip düzeltme olanağına sahip olmalıdır.

Normal metin girişini bozmadan hataları yönetin

Konuşma alt sistemi isteğe bağlı olmalıdır.

Mikrofon izni reddedilirse, tarayıcı model için bellek ayıramazsa, worker çökerse veya kayıt sırasında konuşma algılanmazsa normal metin alanı çalışmayı sürdürmelidir.

Mikrofonun yaşam döngüsünü şu açık durumlarla temsil edin:

idle
preparing
listening
recognizing
error

Erişilebilir etiketler ve görünür durum geri bildirimi kullanın. Yüklemeden sonra yalnızca kırmızıya veya pembeye dönen mikrofon kullanıcıya neredeyse hiçbir şey anlatmaz.

İptal işlemi ses izlerini, ses bağlamını, bekleyen tamponları ve etkin kayıt oturumunu temizlemelidir. Arayüz, daha önce iptal edilmiş bir kaydın geç gelen sonucunun yeni giriş durumunu ezmesini de engellemelidir.

Büyük model bellek ya da başlatma kısıtları nedeniyle başarısız olursa daha küçük modeli denemeden önce tamamen serbest bırakın. Tarayıcının çalıştıramadığı modelleri tekrar tekrar indirmemesi veya başlatmaması için yeniden deneme sayısını sınırlayın.

Yerel tanıma başarısız olursa habersizce bulut konuşma hizmetine geçmeyin. Yalnızca yerel işleme kesin bir gereksinimse yerel tanıyıcı başarısız olduğunda işlem de yerel olarak başarısız olmalıdır.

Tarayıcı hattının tamamını test edin

TypeScript denetiminin veya üretim derlemesinin başarılı olması, sesli girişin çalıştığını kanıtlamaz.

Benzer şekilde tarayıcının ONNX dosyalarını indirebilmesi, her iki model oturumunun da başarıyla başlatıldığını göstermez.

En yararlı regresyon testi, üretimde kullanılan worker'ı, yürütme dosyalarını, modeli, işlemciyi ve tokenizer'ı aynen çalıştırmalıdır.

Bilinen kısa bir PCM kaydını gerçek tarayıcı çıkarım yoluna verin ve boş olmayan bir döküm elde edildiğini doğrulayın.

Ardından gerçek tarayıcıda mikrofon etkileşiminin tamamını test edin.

  • İlk sayfa yüklemesi: Mikrofon kullanılmadan önce hiçbir konuşma modeli veya yürütme varlığı indirilmediğini doğrulayın.
  • Soğuk başlatma: Mikrofon iznini, model isteklerini, JavaScript ve WASM MIME türlerini ve worker'ın gerçek hazır yanıtını doğrulayın.
  • ONNX başlatma: Hem kodlayıcı hem kod çözücü oturumlarının oluşturulabildiğini doğrulayın.
  • Ses yakalama: AudioWorklet'in boş olmayan PCM tamponları ürettiğini doğrulayın.
  • Yeniden örnekleme: Worker'ın gerçek örnekleme hızını aldığını ve geçerli 16 kHz ses ürettiğini doğrulayın.
  • Elle durdurma: Mikrofona ikinci kez tıklamanın kaydı güvenilir biçimde durdurduğunu doğrulayın.
  • Otomatik durdurma: Doğal duraklamaların kısık konuşmayı kesmeden kaydı sonlandırdığını doğrulayın.
  • Döküm üretimi: İşlemci, model ve tokenizer'ın birlikte anlaşılabilir metin döndürdüğünü doğrulayın.
  • Giriş alanıyla bütünleştirme: Tanınan metnin, kullanıcı düzenlemelerini ezmeden gerçek denetimli alanda göründüğünü doğrulayın.
  • Hata sonrası toparlanma: Reddedilen izinleri, eksik dosyaları, worker hatalarını, model başlatma başarısızlıklarını, iptali ve küçük modele geçişi test edin.
  • Gizlilik: Ağ isteklerini inceleyin ve mikrofon sesinin sunucuya ya da analiz hizmetine yüklenmediğini doğrulayın.
  • Mobil uyumluluk: Soğuk ve sıcak başlangıçlar ile yinelenen dikte oturumları dâhil testleri gerçek telefonlarda tekrarlayın.

Kaydedilmiş PCM testleri çıkarım bileşenlerini doğrulamak için çok yararlıdır, ancak mikrofon yakalamanın çalıştığını kanıtlamaz. Son kabul testi gerçek mikrofonu ve gerçek kullanıcı arayüzünü içermelidir.

Güvenilir tarayıcı diktesi için pratik mimari

Kısa, çok dilli ve gizliliği koruyan sesli girişe ihtiyaç duyan bir web sitesi için en pratik mimari özellikle basittir:

React microphone button
        |
        v
Permission request
        |
        v
Lazy model initialization
        |
        v
AudioWorklet PCM capture
        |
        v
Adaptive RMS / manual stop
        |
        v
Dedicated Worker
        |
        v
16 kHz audio resampling
        |
        v
Whisper Tiny or Base Q8
        |
        v
Compatible ONNX Runtime WASM
        |
        v
Whisper processor + tokenizer
        |
        v
Final transcript
        |
        v
Controlled React input

Uygulama, sürümlendirilmiş model ve yürütme dosyalarını kendi sunucusunda barındırmalı, çıkarımı ana iş parçacığının dışında tutmalı, gereksiz model indirmelerinden kaçınmalı, iş bitince kaynakları serbest bırakmalı ve konuşma tanıma için mikrofon sesini asla yüklememelidir.

WebGPU hızlandırması, sinir ağı tabanlı ses etkinliği algılama, sürekli ara dökümler veya ek model düzeyleri gibi daha karmaşık seçenekler, ölçümler karmaşıklıklarını haklı çıkardığında ileride değerlendirilebilir.

En değerli ders belirli bir kütüphane sürümü ya da model boyutu değildir. Asıl önemli olan tarayıcıdaki konuşma tanıma hattının her sınırını doğrulamaktır.

Çalışan bir mikrofon izin penceresi, sesin metne dönüştürüldüğü anlamına gelmez. İndirilen model, kod çözücüsünün başlatıldığını göstermez. Başarılı ONNX oturumu, tokenizer'ın hazır olduğu anlamına gelmez. Başarılı bir döküm bile uygulamanın metni doğru eklediğini göstermez.

Özellik ancak ziyaretçi mikrofona basıp doğal biçimde konuşabildiğinde, kaydı durdurabildiğinde ve kayıt bir konuşma tanıma sunucusuna gönderilmeden tanınan sözcükleri düzenlenebilir alanda görebildiğinde tamamlanmış sayılır.