İçeriğe geç
Batuhan YAZICI

Senior Cyber Security Specialist

Senior System and Network Admin

Batuhan YAZICI

Senior Cyber Security Specialist

Senior System and Network Admin

Finansal sistemlerde güvenlik,
altyapıda süreklilik.

  • Fortinet
  • SIEM
  • PCI DSS
  • ISO/IEC 27001
← Teknik blog
MagicMirror Projesi · Otomasyon

MagicMirror Projesi: sesli yanıt iptali ve ses odağı

Batuhan YAZICI · · 10 dk okuma
MagicMirror Projesi: sesli yanıt iptali ve ses odağı — Batuhan YAZICI
Batuhan YAZICI · batuhanyazici.com

MagicMirror Projesi: sesli yanıt iptali ve ses odağı kapsamında kaynakta uygulanan bileşenler, doğrulama sınırları ve geri dönüş.

MagicMirror Projesi’nde sesli yanıtın üretimini, oynatılmasını ve iptalini aynı istek kimliğine bağladık. Kullanıcı yeni bir komut verdiğinde veya sistem uykuya geçtiğinde eski sentezin sonradan konuşmaya başlamaması için sahiplik denetimleri ekledik. Bu yazı kaynakta yapılan düzenlemeyi anlatıyor; bu turda fiziksel mikrofon veya hoparlör testi yürütülmedi.

Projede yaptığımız düzenleme

Sürümlü kararlılık kaydında ortak ses dosyası ve eski seri oynatma kuyruğundan uzaklaşıldığı belirtiliyor. Geç tamamlanan sentezin yeni konuşmaya karışmasını önleyen istek kimliği, iptal sinyali ve süre sınırları aynı akışa bağlandı. Ses hazırlanırken arayüzde hazırlık durumu gösteriliyor; yalnızca isteğin başlaması konuşmanın gerçekten başladığı anlamına getirilmiyor.

Müzik sesiyle asistan sesini de ayrı yönettik. Konuşma sırasında geçici ses azaltma ve sonrasında geri bırakma davranışı, oturumun durumuyla ilişkilendirildi. Ağ üzerinden ses üretimi başarısız olduğunda yerel yedek yol ve hata beklemesi bulunuyor. Bunların varlığı uzak mesafeden her komutun anlaşılacağı veya her ses aygıtında aynı gecikmenin oluşacağı güvencesi değildir; fiziksel kabul ayrıca gerekir.

İptal edilmesi gereken katmanları ayırın

Bir yanıt, sunucuda üretim, ağda taşınan parçalar, tarayıcı kuyruğu ve ses aygıtındaki oynatma gibi farklı aşamalarda olabilir. Yalnızca istek bağlantısını kapatmak önceden alınmış sesi susturmayabilir. Yalnızca oynatmayı durdurmak da gereksiz üretimi ve geç gelen yanıtları sonlandırmaz. Tasarımda her katmanın iptal davranışı ve tamamlanma sinyali ayrı tanımlanmalıdır. Her ses motorunun aynı arayüzü sunduğu varsayılmamalıdır.

MDN, SpeechSynthesis.cancel yönteminin tarayıcının konuşma kuyruğunu temizlediğini ve devam eden konuşmayı durdurduğunu açıklar. Bu davranış o tarayıcı arayüzü içindir; başka bir ses motoruna kendiliğinden uygulanmaz. AbortController ise onu destekleyen eşzamansız işlemler için iptal sinyali sağlar. Bu iki mekanizma birbirinin yerine geçmez. Kullanılan aktarım ve oynatıcı kendi belgeleriyle ayrıca değerlendirilmelidir.

Bir tur iptal edildiğinde hem ses üretimi hem oynatma kuyruğu ele alınır. Eski turun geç gelen bitiş olayı yeni turun ses odağını değiştiremez.

  1. Yeni konuşmayı algıla
  2. Eski turu geçersiz kıl
  3. Üretim ve oynatmayı durdur
  4. Geç gelen olayı reddet
  5. Ses odağını sahibine bırak
Bir tur iptal edildiğinde hem ses üretimi hem oynatma kuyruğu ele alınır. Eski turun geç gelen bitiş olayı yeni turun ses odağını değiştiremez.

Her konuşma turunun bir sahibi olsun

Deneme tasarımında her yanıt için bir tur kimliği ve geçerlilik durumu oluşturun. Kullanıcı araya girdiğinde mevcut tur geçersiz kılınır; yeni tur kendi kimliğiyle başlar. Ağdan veya ses motorundan geç gelen olay yalnızca ait olduğu tur hâlâ geçerliyse arayüzü etkileyebilsin. Böylece eski bitiş bildiriminin yeni konuşmayı kapatması veya eski metnin yeni yanıtın üstüne yazılması önlenebilir.

Bu, yalnızca ekrana bir sayaç koymak değildir. Yanıt parçaları, tamamlanma olayı, hata, zaman aşımı ve yeniden bağlantı aynı sahiplik kuralına uymalıdır. Kullanıcı uyku komutu verdikten sonra geç gelen bir parça cihazı tekrar konuşturamamalıdır. İptal isteğiyle gerçek oynatmanın durduğu anı ayrı gözlemleyin. Aradaki süre ölçülmeden anında kesildiği iddiası kurmayın; kullanılan ses aygıtının tamponu da sonucu etkileyebilir.

Müzik sesini geçici ödünç alın

Asistan konuşurken müzik sesinin azaltılması, önceki düzeyi saklayan ve geri bırakan bir sahiplik işlemi olarak ele alınabilir. İki konuşma turu iç içe geçtiğinde ilk turun bitişi ikinci turun sesini geri açmamalıdır. Kullanıcı bu sırada sesi kendisi değiştirirse eski değeri zorla geri yazmak da beklenmeyen davranış üretir. Hangi bileşenin son söz sahibi olduğu açık bir kuralla belirlenmelidir.

Kabul matrisi en az normal bitiş, kullanıcı söz kesmesi, ağ hatası ve ses aygıtının kaybolması durumlarını kapsasın. Her satırda konuşma durumu, kuyruk, müzik düzeyi ve arayüz göstergesi birlikte kontrol edilsin. Sessiz hoparlör, sistemin artık dinlemediğini veya verinin saklanmadığını göstermez. Dinleme ve oynatma durumlarını kullanıcıya aynı işaretle anlatmak yerine işlevlerine uygun görünür durumlar tasarlayın.

Geri dönüş ve sınırlar

Laboratuvarda gerçek özel konuşmalar yerine kısa sentetik cümleler kullanın. Önceki turu bilerek geciktirin, sonra yeni bir tur başlatın ve geciken olayın reddedildiğini gözlemleyin. Bu senaryo yalnız test ortamında kurulmalıdır; üretim bağlantısını bozmak veya gerçek kullanıcı konuşmasını hata ayıklama kaydına almak gerekmez. Kayıtta tur kimliği, olay türü ve zaman bilgisi yeterli olacak şekilde veri kapsamını daraltın.

Geri dönüşte yeni ses odağı mantığını önceki onaylı sürüme alın; açık kuyrukları ve sahipliği de temizleyin. Sadece dosyayı değiştirmek devam eden oturumun durumunu düzeltmeyebilir. Temiz oturumda normal yanıtı, söz kesmeyi ve müziğin toparlanmasını yeniden sınayın. Bu kabul konuşma tanıma doğruluğunu ölçmez; yalnızca iptal ve olay sırası davranışının belirlenmiş koşullarda tutarlı olduğunu göstermeyi hedefler.

Serinin bütün çalışmaları: MagicMirror Projesi.

Nasıl yapılır: ayrıntılı uygulama

Ortam ve ön koşullar: Tarayıcı yanıt iptali örneği — HTTP isteği ve oynatıcının aynı kullanıcı eylemiyle iptal edileceği tasarlanmalı.

  1. İstek sahipliğini belirleyin
  2. Tam küçük konuşma denetleyicisini kaydedin
  3. Server üretiminde AbortSignal’ı da taşıyın
  4. Üç yarış durumunu açıkça deneyin
  5. Ses odağı ve geri dönüşü kapatın

1. İstek sahipliğini belirleyin

TTS hazırlama, oynatma ve iptal aynı request/generation kimliğine bağlanır. İptal sadece hoparlörü susturmak değildir; geç gelen eski sentez tekrar oynatılmamalı. Bu tarayıcı örneği desteklenen Web Speech sentezini kullanır, projenin özel provider’ını kurmaz.

2. Tam küçük konuşma denetleyicisini kaydedin

Aşağıdaki kodu izinli tarayıcı test sayfasında speakLatest("batuhanyazici.com deneme") ve cancelSpeech() düğme eylemlerine bağlayın. Kullanıcı jesti ve tarayıcı ses desteği gerekir. Eski callback yeni isteğin durumunu değiştiremez.

let speechGeneration = 0;
let activeUtterance = null;
function cancelSpeech() {
  speechGeneration++;
  speechSynthesis.cancel();
  activeUtterance = null;
}
function speakLatest(text) {
  cancelSpeech();
  const mine = speechGeneration;
  const utterance = new SpeechSynthesisUtterance(text);
  utterance.lang = "tr-TR";
  activeUtterance = utterance;
  const finish = () => {
    if (mine === speechGeneration && activeUtterance === utterance) activeUtterance = null;
  };
  utterance.onend = finish;
  utterance.addEventListener("error", finish);
  speechSynthesis.speak(utterance);
}
window.addEventListener("pagehide", cancelSpeech);

3. Server üretiminde AbortSignal’ı da taşıyın

Mevcut gerçek TTS provider adapter’ı AbortSignal destekliyorsa fetch/request’e geçirin. Desteklemiyorsa generation denetimi sonucu yine atmalıdır. Aşağıdaki parça interface örneğidir; synthesize fonksiyonu kendi sağlayıcınızın desteklenen adapter’ıdır.

let pendingTts = null, audioGeneration = 0;
async function prepareLatest(text, synthesize, acceptAudio) {
  pendingTts?.abort();
  const controller = new AbortController();
  pendingTts = controller;
  const mine = ++audioGeneration;
  try {
    const audio = await synthesize(text, {signal:controller.signal});
    if (!controller.signal.aborted && mine === audioGeneration) acceptAudio(audio);
  } catch (error) {
    if (error.name !== "AbortError") throw error;
  }
}
function cancelPendingTts() {
  audioGeneration++;
  pendingTts?.abort();
  pendingTts = null;
}

4. Üç yarış durumunu açıkça deneyin

A konuşurken iptal; A hazırlıkta iken B isteği; A iptal edildikten sonra geç A sonucu senaryolarını sentetik metinle çalışın. Sonuç yalnız B’ye ait olmalı, eski onend/error callback’i B’nin ses odağını bırakmamalı.

5. Ses odağı ve geri dönüşü kapatın

Projede mikrofon dinleme/müzik ducking ve stream/Blob URL temizliği ayrı sahipliğe bağlanır. Yeni ses yönetimi başarısızsa önceki provider/UI sürüm takımına dönün; gerçek konuşma veya hesap token’ı loglamayın.

Beklenen sonuç: İptal edilen istek ve konuşma devam etmez; yeni yanıt kendi yaşam döngüsünü korur.

Sonuç farklıysa: Bu API örneği proje özelindeki önbellek veya ayrı oynatıcının kuyruğunu kendiliğinden temizlemez.

Geri dönüş: Önceki uyumlu iptal/oynatıcı sürümüne dönüp geç sonuç senaryosunu tekrar sınayın.

MagicMirror Projesi: sesli yanıt iptali ve ses odağı için temsili uygulama ve kabul haritası
Temsili uygulama ve kabul haritası; gerçek ürün ekran görüntüsü değildir. Haritayı büyük aç.

Kaynaklar

Uygulama örnekleri teknik, kaynak ve mahremiyet incelemesinden geçti. Temsili haritalar üretici ekran görüntüsü veya canlı sistem testi olarak sunulmaz. Kullanılan ürün sürümü ve kapsam uygulama öncesinde doğrulanmalıdır.

Batuhan YAZICI

Senior Cyber Security Specialist · Altyapı ve güvenlik üzerine teknik notlar.

Okumaya devam edin

MagicMirror Projesi — Batuhan YAZICI