macOS companion app

پوشش صوتی

چرخهٔ عمر لایهٔ رویی صوتی (macOS)

مخاطب: مشارکت‌کنندگان برنامهٔ macOS. هدف: حفظ رفتار پیش‌بینی‌پذیر لایهٔ رویی صوتی هنگام هم‌پوشانی واژهٔ بیدارباش و فشار برای صحبت.

رفتار

  • اگر لایهٔ رویی از قبل به‌دلیل واژهٔ بیدارباش قابل مشاهده باشد و کاربر کلید میان‌بر را فشار دهد، نشست کلید میان‌بر به‌جای بازنشانی متن، متن موجود را به‌کار می‌گیرد. تا زمانی که کلید میان‌بر نگه داشته شده است، لایهٔ رویی باز می‌ماند. هنگام رهاسازی: اگر پس از حذف فاصله‌های ابتدا و انتها متنی وجود دارد، آن را ارسال می‌کند؛ در غیر این صورت، لایهٔ رویی را می‌بندد.
  • واژهٔ بیدارباش به‌تنهایی همچنان هنگام سکوت به‌طور خودکار ارسال می‌کند؛ فشار برای صحبت نیز بلافاصله پس از رهاسازی ارسال می‌کند.

پیاده‌سازی

  • VoiceSessionCoordinator (apps/macos/Sources/OpenClaw/VoiceSessionCoordinator.swift) تنها مالک نشست صوتی فعال است. این مؤلفه یک تک‌نمونهٔ @MainActor @Observable است، نه یک actor. رابط برنامه‌نویسی: startSession، updatePartial، finalize، sendNow، dismiss، updateLevel، snapshot. هر نشست یک توکن UUID دارد؛ فراخوانی‌هایی با توکن منقضی یا نامطابق نادیده گرفته می‌شوند.
  • VoiceWakeOverlayController (VoiceWakeOverlayController+Session.swift) لایهٔ رویی را نمایش می‌دهد و کنش‌های کاربر (requestSend، dismiss) را با استفاده از توکن نشست به هماهنگ‌کننده بازمی‌گرداند. این مؤلفه هرگز مالک وضعیت نشست نیست.
  • فشار برای صحبت (VoicePushToTalk.begin()) هر متن قابل مشاهده در لایهٔ رویی را به‌عنوان adoptedPrefix (از طریق VoiceSessionCoordinator.shared.snapshot()) به‌کار می‌گیرد؛ بنابراین، فشردن کلید میان‌بر هنگامی که لایهٔ رویی بیدارباش باز است، متن را حفظ می‌کند و گفتار جدید را به آن می‌افزاید. هنگام رهاسازی، تا ۱٫۵ ثانیه منتظر رونوشت نهایی می‌ماند و سپس، در صورت آماده‌نشدن آن، از متن فعلی استفاده می‌کند.
  • هنگام dismiss، لایهٔ رویی VoiceSessionCoordinator.overlayDidDismiss را فراخوانی می‌کند که باعث اجرای VoiceWakeRuntime.refresh(state:) می‌شود؛ در نتیجه، بستن دستی با X، بستن به‌دلیل خالی‌بودن متن و بستن پس از ارسال، همگی گوش‌دادن برای واژهٔ بیدارباش را از سر می‌گیرند.
  • مسیر یکپارچهٔ ارسال: اگر متن پس از حذف فاصله‌های ابتدا و انتها خالی باشد، لایهٔ رویی بسته می‌شود؛ در غیر این صورت، sendNow صدای اعلان ارسال را یک‌بار پخش می‌کند، متن را از طریق VoiceWakeForwarder می‌فرستد و سپس لایهٔ رویی را می‌بندد.

ثبت گزارش

زیرسامانهٔ صوتی ai.openclaw است؛ هر مؤلفه گزارش‌ها را در دستهٔ مخصوص خود ثبت می‌کند:

دسته مؤلفه
voicewake.coordinator VoiceSessionCoordinator
voicewake.overlay VoiceWakeOverlayController/VoiceWakeOverlay
voicewake.ptt کلید میان‌بر و ضبط فشار برای صحبت
voicewake.runtime زمان اجرای واژهٔ بیدارباش
voicewake.chime پخش صدای اعلان
voicewake.sync همگام‌سازی تنظیمات سراسری
voicewake.forward ارسال رونوشت
voicewake.meter پایشگر سطح میکروفون

فهرست بررسی اشکال‌زدایی

  • هنگام بازتولید لایهٔ رویی گیرکرده، گزارش‌ها را به‌صورت جریانی مشاهده کنید:

    bash
    sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact
  • بررسی کنید که فقط یک توکن نشست فعال وجود داشته باشد؛ فراخوانی‌های برگشتی منقضی توسط هماهنگ‌کننده نادیده گرفته می‌شوند.

  • تأیید کنید که رهاسازی فشار برای صحبت همیشه end() را با توکن فعال فراخوانی می‌کند؛ اگر متن خالی باشد، انتظار می‌رود لایهٔ رویی بدون صدای اعلان یا ارسال بسته شود.

مرتبط

Was this useful?
On this page

On this page