Skip to content

Voice Button

دیکته برای کادر نوشتن متن، بر پایهٔ Web Speech API.

کجا به کارش ببرید: وقتی گفتار را راهی دیگر برای پر کردن یک کادر متن می‌خواهید، نه جایگزین آن. تایپ باید در دسترس بماند: مسیرِ فقط‌صوتی کسانی را که گفتارشان تفاوت دارد، کسانی را که در اتاقی پرسروصدا هستند، و هرکسی را که مرورگرش اصلاً تشخیص گفتار ندارد کنار می‌گذارد.

یک دکمهٔ میکروفون، و همین. ضبط را برعهده می‌گیرد و آنچه شنیده را گزارش می‌دهد؛ اینکه آن متن کجا برود تصمیم فراخواننده است، چون کامپوننتی که خودش هم در یک ورودی بنویسد باید بداند کدام ورودی، افزودن یا جایگزینی، و با مکان‌نما چه کند: سه پاسخی که در هر برنامه فرق می‌کند.

شروع سریع

html
<r-voice-button label="شروع ورود صوتی" active-label="توقف ورود صوتی"></r-voice-button>
ts
const mic = document.createElement('r-voice-button');
mic.label = 'شروع ورود صوتی';
mic.activeLabel = 'توقف ورود صوتی';
const input = document.querySelector('textarea');
let base = '';

mic.addEventListener('voicestart', () => {
  // یک فاصله میان آنچه تایپ شده و آنچه گفته می‌شود، مگر آنکه از پیش باشد.
  base = input.value === '' || /\s$/.test(input.value) ? input.value : `${input.value} `;
});

mic.addEventListener('voiceresult', (event) => {
  input.value = base + event.detail.transcript;
});

composer.append(mic);

تصمیم‌هایی که پشت آن است

کل ضبط را گزارش می‌دهد، نه تازه‌ترین تکه را

نتیجه‌های میانی با ادامهٔ تشخیص بازنویسی می‌شوند: «你好» به «你好世界» بدل می‌شود، نه اینکه رویداد دومی با «世界» برسد. مصرف‌کننده‌ای که هر رویداد را می‌افزود، به 你好你好世界 می‌رسید. متنی را که از پیش در کادر بود به یاد بسپارید و تنها یک بار به‌هم بچسبانید.

ارسال نمی‌کند

تشخیص به‌اندازهٔ کافی اشتباه می‌کند که تأیید به‌جای گوینده، بازبینی موردنیازش را از او بگیرد. این کامپوننت کادر را پر می‌کند و همان‌جا می‌ایستد. ارسال کنشی آگاهانه می‌ماند.

جایی که تشخیص وجود ندارد خودش را پنهان می‌کند

فایرفاکس تشخیص گفتار ندارد، و همین‌طور هر مرورگری که این API در آن نباشد. وقتی تشخیص پشتیبانی نمی‌شود، عنصر به‌جای غیرفعال‌کردن خود با disabled، خودش را با hidden پنهان می‌کند: disabled یعنی قابلیت هست ولی موقتاً در دسترس نیست، حال آنکه وقتی قابلیت روی این بستر اصلاً وجود ندارد، برداشتن دکمه دقیق‌تر است. نشان‌دادن دکمه‌ای که هرگز کار نمی‌کند، به ضربه‌ای دعوت می‌کند که هیچ نمی‌کند و بعد توضیح می‌طلبد.

از چهار خطا تنها دو تا ارزش نشان‌دادن دارند

گونهچیستنشان داده شود؟
deniedدسترسی میکروفون رد شدبله (کاری می‌شود کرد)
failedچیز دیگری خطا دادبله
noSpeechمکثی خاموشخیر
abortedتوقفی از سمت برنامهخیر

دو مورد آخر از همان مجرای شکست واقعی می‌رسند و شکست نیستند. نمایان‌کردنشان یعنی پس از هر ضبط عادی خطا نشان دهیم، نه فقط پس از شکست‌های واقعی.

دسترس‌پذیری

نه‌فقط آیکون، بلکه نام دسترس‌پذیر با وضعیت عوض می‌شود و aria-pressed وضعیت دوحالته را حمل می‌کند: صفحه‌خوان می‌گوید «توقف ورود صوتی، فشرده»، نه یک آیکون. Escape ضبط را دور می‌ریزد و تأییدش نمی‌کند؛ همان چیزی که گوینده‌ای که وسط جمله می‌فهمد اشتباه گفته می‌خواهد.

حالت شنیدن با حاشیه، پرشدگی و یک حلقه منتقل می‌شود، پس تنها به رنگ تکیه ندارد. تنها چیز متحرک همان حلقه است و تزئینی است؛ prefers-reduced-motion آن را بی‌آنکه اطلاعاتی از دست برود کنار می‌گذارد.

زبان از صفحه پیروی می‌کند

lang در هر ضبط خوانده می‌شود و پیش‌فرضش زبان سند است، پس برنامه‌ای که وسط نشست زبانش را عوض می‌کند، به همان زبانی دیکته می‌گیرد که نشان می‌دهد.

مرجع API

خصیصه‌ها

خصیصهنوعپیش‌فرضتوضیح
langstringزبان سندبرچسب BCP 47 زبانی که گفته می‌شود. در هر ضبط خوانده می‌شود.
continuousbooleantrueبه‌جای ایستادن در نخستین مکث، در سراسر مکث‌ها به شنیدن ادامه می‌دهد.
disabledbooleanfalseدکمه را غیرفعال می‌کند: start() نادیده گرفته می‌شود و دکمهٔ درونی هم غیرفعال است. ضبطِ در جریان را متوقف نمی‌کند.
labelstring'Start voice input'نام دسترس‌پذیر در حالت بی‌کار.
activeLabelstring'Stop voice input'نام دسترس‌پذیر هنگام شنیدن.
listeningbooleanfalseفقط‌خواندنی و بازتاب‌یافته: با :host([listening]) استایل بدهید.
supportedbooleanفقط‌خواندنی. اینکه این بستر می‌تواند گفتار را تشخیص دهد یا نه.
sheetstring''CSS تزریق‌شده به shadow DOM عنصر.

متدها

start() · stop() (آنچه تشخیص داده شده را نگه می‌دارد) · abort() (دورش می‌ریزد) · toggle().

toggle() به‌جای ویژگی بازتاب‌یافته، وضعیت خودِ تشخیص‌دهنده را می‌خواند: ضبطی که بدون گزارش آغاز شده باشد، این دو را ناهم‌خوان می‌گذارد و فعال‌سازی بعدی می‌کوشد ضبط دومی باز کند، رد می‌شود و کاری نمی‌کند.

رویدادها

رویدادDetailچه زمانی
voicestartضبطی آغاز می‌شود
voiceresult{ transcript, isFinal }متنی می‌رسد یا بازنویسی می‌شود
voiceerror{ kind, detail }بستر مشکلی را گزارش می‌کند
voiceendضبط به هر دلیلی پایان می‌یابد

Part‌ها

button، icon.

استایل

<r-voice-button> ۲۰ ویژگی سفارشی CSS از آنِ خود و افزون بر آن توکن‌های معنایی‌ای که از پوسته می‌خواند در اختیار می‌گذارد. آن را هرجا که ارث می‌رسد تعیین کنید: :root، یک نگه‌دارنده، یا خود عنصر.

css
r-voice-button {
  --ran-voice-background: var(--ran-color-bg-subtle);
}

Part‌ها: button · hint · icon

فهرست کامل در توکن‌های استایل است و اینکه کدام توکن را برگزینید در سیستم طراحی آمده.

همچنین ببینید

  • createSpeechRecognizer: تشخیص‌دهنده‌ای که این کامپوننت آن را دربر گرفته
  • Conversation: رونوشتی که پیامِ دیکته‌شده در آن می‌نشیند

منتشرشده تحت مجوز MIT.