SFSpeechRecognizer — API اصلی Apple برای تشخیص گفتار در اکوسیستم iOS. این فریمورک از طریق Speech.framework به موتور ASR دستگاه دسترسی فراهم میکند و از رونویسی جریانی در زمان واقعی و تشخیص یکباره فایلهای صوتی پشتیبانی میکند. SFSpeechRecognizer در iOS 10+، macOS 10.15+، watchOS 6+ و tvOS 17+ در دسترس است. از iOS 17 اپل یک حالت on-device کامل اضافه کرد که تشخیص گفتار را بدون اتصال به اینترنت امکانپذیر میکند. طبق Apple Speech Documentation, 2025، SFSpeechRecognizer در بیش از 200,000 برنامه App Store استفاده میشود و با WER 7% برای زبان انگلیسی روزانه میلیونها درخواست را پردازش میکند.
نکات اصلی
SFSpeechRecognizer — کلاسی از Speech.framework که یک تشخیصدهنده گفتار برای یک زبان خاص را نشان میدهد. با Locale (ru_RU, en_US, zh_CN) مقداردهی اولیه میشود. SFSpeechRecognizer درخواست تشخیص (SFSpeechRecognitionRequest) را مدیریت کرده و نتیجه (SFSpeechRecognitionResult) را با رونوشتها و فراداده بازمیگرداند. از دو نوع درخواست پشتیبانی میکند: SFSpeechAudioBufferRecognitionRequest (جریان صوتی زنده) و SFSpeechURLRecognitionRequest (فایل صوتی). هر دو SFTranscription — آرایهای از گزینههای جایگزین تشخیص را بازمیگردانند.
SFSpeechRecognitionResult شامل: bestTranscription (بهترین گزینه، SFTranscription)، transcriptions (همه جایگزینها)، isFinal (نهایی/موقت). SFTranscription شامل: formattedString (متن)، segments (آرایه SFTranscriptionSegment با برچسبهای زمانی، confidence، substringRange، alternativeSubstrings). Confidence برای هر بخش (0..1) — امکان فیلتر کردن قطعات نامطمئن را میدهد. segments — ویژگی کلیدی Speech.framework: حاشیهنویسی هر کلمه با اطمینان را فراهم میکند.
معماری SFSpeechRecognizer: AVFoundation (ضبط صدا) → Audio Buffer → SFSpeechAudioBufferRecognitionRequest → SFSpeechRecognizer (موتور ASR) → SFSpeechRecognitionResult → SFSpeechRecognitionTask (کنترل: cancel, finish, pause). موتور ASR اپل از معماری ترکیبی استفاده میکند: Conformer (رمزگذار) + RNNT (رمزگشا) برای on-device، Transducer برای cloud. مدلها برای Apple Neural Engine (ANE) بهینه شدهاند. در A17 Pro on-device ASR با RTF 0.3–0.6 کار میکند (سریعتر از زمان واقعی).
| جزء | هدف | نسخه iOS |
|---|---|---|
| SFSpeechRecognizer | کلاس اصلی تشخیص | iOS 10+ |
| SFSpeechAudioBufferRecognitionRequest | جریان صوتی زنده | iOS 10+ |
| SFSpeechURLRecognitionRequest | فایل صوتی (.wav, .m4a) | iOS 10+ |
| SFSpeechRecognitionTask | مدیریت درخواست (cancel, finish) | iOS 10+ |
| On-device recognition | ASR آفلاین | iOS 17+ |
| Combined Recognition | ترکیبی on-device + cloud | iOS 17+ |
نیازمندیهای صوتی: SFSpeechRecognizer LPCM (16 kHz, 16 bit, mono) یا Opus (iOS 17+) را میپذیرد. AVFoundation میتواند بافر را در هر فرمتی ضبط کند، درخواست به طور خودکار تبدیل میکند. حداقل طول: 0.5 ثانیه (تشخیص سکوت). حداکثر: 1 دقیقه (cloud) / 2 دقیقه (on-device) برای هر درخواست. برای رونویسی طولانی، صدا را به قطعات 30–60 ثانیه با همپوشانی 2–5 ثانیه تقسیم کنید.
مجوزهای کاربر: SFSpeechRecognizer به دو مجوز صریح نیاز دارد. NSMicrophoneUsageDescription (Privacy — Microphone Usage Description) — برای دسترسی به میکروفون. NSSpeechRecognitionUsageDescription (Privacy — Speech Recognition Usage Description) — برای دسترسی به تشخیص گفتار. هر دو رشتههایی هستند که دلیل را برای کاربر توضیح میدهند. SFSpeechRecognizer.requestAuthorization — فراخوانی گفتگوی مجوز. وضعیتها: notDetermined, denied, restricted, authorized. بدون authorized فراخوانی recognizer خطای 216 را برمیگرداند (Speech framework error).
بررسی در دسترس بودن: SFSpeechRecognizer.isAvailable — بررسی میکند که آیا ASR برای زبان فعلی در دسترس است. در iOS 16- isAvailable = false بدون اینترنت. در iOS 17+ isAvailable = true برای زبانهای on-device حتی به صورت آفلاین. SFSpeechRecognizer.supportedLocales — روشی ایستا برای دریافت لیست زبانهای پشتیبانی شده توسط دستگاه. توصیه میشود قبل از هر راهاندازی isAvailable را بررسی کنید (کاربر ممکن است Siri/Dictation را در تنظیمات غیرفعال کند). در دسترس بودن به منطقه بستگی دارد: چینی — فقط در چین، عربی — در امارات.
// راهاندازی SFSpeechRecognizer
import Speech
SFSpeechRecognizer.requestAuthorization { status in
guard status == .authorized else { return }
}
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "ru_RU"))!
guard recognizer.isAvailable else {
print("ASR در دسترس نیست. Siri و Dictation را در تنظیمات فعال کنید")
return
}
let request = SFSpeechAudioBufferRecognitionRequest()
request.requiresOnDeviceRecognition = true
مدیریت خطا: SFSpeechRecognizer با completion handler فراخوانی میشود که ممکن است Error برگرداند. خطاهای اصلی: 203 — no internet (cloud, iOS 16-); 216 — not authorized (بدون مجوز); 301 — audio error (مشکل میکروفون/فرمت); 401 — service unavailable (سرویس بیش از حد بارگذاری شده); 601 — language unavailable (زبان در دستگاه پشتیبانی نمیشود). برای on-device iOS 17+ خطاهای اصلی: 301 (audio), 601 (language). همیشه completion handler را مدیریت کنید — خطاها ممکن است در هر لحظه از ضبط رخ دهند.
خط لوله Live ASR: AVAudioEngine (ضبط از میکروفون) → installTap (بافر صوتی) → request.append(buffer) → SFSpeechRecognizer → recognitionTask → delegate/resultHandler. AVAudioEngine تأخیر کم را تضمین میکند (5–10 ms از میکروفون تا بافر). SFSpeechRecognitionDelegate: didHypothesizeTranscription (هر 200–500 ms — متن جزئی), didFinishRecognition (نتیجه نهایی). Task.isFinishing — میتوان هنگام تکمیل تشخیص لغو کرد. برای تشخیص پیوسته (دیکته بیپایان) — پس از isFinal یک task جدید ایجاد کنید.
SFSpeechRecognitionTaskDelegate: روشهای اختیاری. speechRecognitionDidDetectSpeech (شروع گفتار) — برای نشانگر UI. didHypothesizeTranscription (متن موقت) — برای نمایش در حین گفتار. didFinishRecognition (نتیجه نهایی) — برای ثبت متن. didFinishSuccessfully (موفقیت/خطا) — برای اتمام. didProcessAudio (بافر صوتی پردازش شد) — برای متر RMS. توصیه میشود didHypothesizeTranscription را پیادهسازی کنید — کاربر متن را فوراً و بدون تأخیر میبیند. رونوشت نهایی — برای ذخیرهسازی.
// تشخیص گفتار زنده
let audioEngine = AVAudioEngine()
let request = SFSpeechAudioBufferRecognitionRequest()
request.shouldReportPartialResults = true
recognitionTask = recognizer.recognitionTask(with: request) { result, error in
if let result = result {
textView.text = result.bestTranscription.formattedString
}
if error != nil || result?.isFinal == true {
audioEngine.stop()
request.endAudio()
}
}
let inputNode = audioEngine.inputNode
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024,
format: recordingFormat) { buffer, _ in
request.append(buffer)
}
audioEngine.prepare()
try audioEngine.start()
تشخیص پیوسته: برای حالت «همیشه گوش کن» (ورودی صوتی، دستیار) نیاز به راهاندازی مجدد task پس از isFinal است. یک حلقه ایجاد کنید: finishTask → request = SFSpeechAudioBufferRecognitionRequest() → recognitionTask = recognizer.recognitionTask(with: request). برای جلوگیری از مکث، انتهای یک task را با شروع task بعدی همپوشانی کنید (درخواست جدید را 1–2 ثانیه قبل از پایان قبلی شروع کنید). AVFoundation AVAudioSession — پیکربندی .playAndRecord برای پخش و ضبط همزمان. در iOS 17+ ASR پیوسته با on-device 2–5% باتری در ساعت مصرف میکند (A15+).
SFSpeechURLRecognitionRequest — درخواست برای تشخیص فایل صوتی از طریق URL. از فرمتها پشتیبانی میکند: .wav (16 kHz, 16 bit, mono), .m4a (AAC), .mp4, .mov. حداکثر طول: ~1 دقیقه برای cloud، ~2 دقیقه برای on-device. برای فایلهای طولانیتر — به قطعات تقسیم کنید (AVAssetExportSession + trim). SFSpeechURLRecognitionRequest از جریان پشتیبانی نمیکند (بدون نتایج جزئی) — فقط نتیجه نهایی. برای نتایج جزئی با فایل — به Audio Buffer Request تبدیل کنید.
دریافت رونوشت فایل صوتی: SFSpeechRecognizer.recognitionTask(with: request) resultHandler. bestTranscription.formattedString را استخراج کنید. برای برچسبهای زمانی سطح کلمه — segments از bestTranscription.segments (segment.duration, segment.timestamp, segment.substring). Confidence در هر بخش — اطمینان ASR در هر کلمه (برای فیلتر کردن استفاده کنید). گزینههای جایگزین — جایگزینهای transcriptionFormatter برای کلمات با confidence پایین. برای فایلهای با چند گوینده — SFSpeechRecognitionRequest ممکن است چندین درخواست برگرداند (یکی برای هر گوینده، iOS 17+).
// رونویسی فایل صوتی
let audioURL = Bundle.main.url(forResource: "recording", withExtension: "m4a")!
let request = SFSpeechURLRecognitionRequest(url: audioURL)
request.requiresOnDeviceRecognition = true
recognizer.recognitionTask(with: request) { result, error in
guard let result = result, error == nil else {
print("خطا: \(error?.localizedDescription ?? "unknown")")
return
}
let transcription = result.bestTranscription
let text = transcription.formattedString
let words = transcription.segments.map { segment in
Word(text: segment.substring,
start: segment.timestamp,
duration: segment.duration,
confidence: segment.confidence)
}
}
تقسیم فایلهای صوتی طولانی: برای فایلهای > 1 دقیقه به قطعات 30–60 ثانیه با همپوشانی 2–3 ثانیه ببرید (اتصال). AVAssetExportSession + CMTimeRange — خروجی قطعات. جایگزین: UISelectionView (کاربر بخش را انتخاب میکند). اتصال رونوشتها: الحاق متنها، اتصال با همپوشانی (2–3 کلمه آخر قطعه قبلی با 2–3 کلمه اول قطعه بعدی مقایسه میشود — حذف تکراری). Vosk و Whisper از صدای طولانی به طور بومی پشتیبانی میکنند، SFSpeechRecognizer — نه. برای رونویسی طولانی Whisper (Core ML) را توصیه میکنم — بدون محدودیت طول.
حالت On-device (iOS 17+): request.requiresOnDeviceRecognition = true. ASR به صورت محلی روی Apple Neural Engine (ANE) اجرا میشود. مزایا: بدون اینترنت، حریم خصوصی (صدا دستگاه را ترک نمیکند)، هزینه صفر (رایگان)، تأخیر کم (RTF 0.3–0.6). معایب: دقت کمتر (WER 12–14% vs 7–12%), محدودیت 2 دقیقه برای هر درخواست، مجموعه زبان محدود (همه 60 زبان on-device در دسترس نیستند). مدل on-device ~50–100 MB در دستگاه اشغال میکند، در اولین درخواست بارگذاری میشود.
Cloud (iOS 16-): request.requiresOnDeviceRecognition = false (یا پارامتر وجود ندارد). ASR روی سرورهای اپل — دقیقتر (WER 7% EN, 12% RU), زبانهای بیشتر، تا 1 دقیقه برای هر درخواست. نیاز به اینترنت دارد (WiFi یا همراه). اپل از توسعهدهنده برای cloud ASR هزینه نمیگیرد (رایگان). محدودیتها: 1 درخواست در دقیقه برای هر برنامه (مشخص نشده)، اما برای مقیاس تولید اپل ممکن است محدود کند. cloud ASR — کیفیت best-effort، بدون SLA. برای برنامههای شرکتی از Google Cloud ASR یا Whisper (Core ML) استفاده کنید.
| پارامتر | On-device (iOS 17+) | Cloud (iOS 10+) |
|---|---|---|
| نیاز به اینترنت | خیر | بله |
| WER (EN) | 10–12% | 7% |
| WER (RU) | 12–14% | 12% |
| تأخیر (RTF) | 0.3–0.6 | 0.3–0.8 (+شبکه) |
| حداکثر طول | 2 دقیقه | 1 دقیقه |
| حریم خصوصی | کامل | صدا به سرور میرود |
| رایگان | بله | بله |
Combined Recognition (iOS 17+): request.requiresOnDeviceRecognition = false با اینترنت (cloud), = true در حالت آفلاین (fallback). اپل به طور خودکار حالت را انتخاب میکند. برای برنامههای حساس به دقت: NetworkMonitor (NWPathMonitor) را بررسی کنید — با اینترنت cloud، بدون آن on-device. برای برنامههای حساس به حریم خصوصی: همیشه on-device. برای رونویسی: cloud (دقیقتر). برای ورودی صوتی: on-device (سریعتر). Combined توصیه شده: 80% cloud، 20% on-device fallback.
ورودی صوتی در صفحهکلید سفارشی — SFSpeechRecognizer در افزونههای صفحهکلید جاسازی شده است (iOS 10+). کاربر دکمه میکروفون را فشار میدهد — ASR گفتار را به متن تبدیل کرده و در فیلد متن قرار میدهد. نیازمندیها: نتایج جزئی (دیدن متن در زمان واقعی), on-device (صفحهکلید باید بدون اینترنت کار کند). SFSpeechRecognizer + AVSpeechSynthesizer — ورودی صوتی + خروجی صوتی. برای صفحهکلید سفارشی در iOS 17+ از on-device استفاده کنید. محدودیتهای افزونه صفحهکلید: AVAudioEngine در دسترس است، اما با محدودیتهای زمانی (background execution limited).
رونویسی جلسات و سخنرانیها — برنامههای ضبط و رونویسی صدا (Otter.ai, Rev, Apple Voice Memos). SFSpeechURLRecognitionRequest فایل .m4a را پردازش میکند. برای ضبطهای طولانی (30–60 دقیقه) — Whisper Core ML (بدون محدودیت طول). بخشهای SFSpeechRecognizer با برچسبهای زمانی — برای همگامسازی متن با صدا (برجستهسازی متن هنگام پخش). Confidence در هر بخش — برای نمایش قطعات نامطمئن (برجستهسازی زرد). برای تشخیص گوینده (چه کسی صحبت کرد) — اپل API ارائه نمیدهد، از pyannote-audio + Whisper در سرور استفاده کنید.
دستورات صوتی در برنامههای iOS — SFSpeechRecognizer + VGS framework (Voice Grammar Services) برای اجرای دستورات: «تنظیمات را باز کن»، «پیام بفرست»، «چراغ را روشن کن». تشخیص مبتنی بر دستور زبان: SFSpeechRecognitionRequest contextualStrings = آرایه دستورات. این دقت تشخیص دستورات را به 95% افزایش میدهد (در مقابل 85% free-form). SFSpeechRecognitionTask.cancel — برای قطع پس از اجرای دستور. VGS + SFSpeechRecognizer + Shortcuts — دستورات صوتی سفارشی بدون نوشتن رابط. برای دسترسی: Voice Control (داخلی) + SFSpeechRecognizer (دستورات سفارشی).
// دستورات صوتی با رشتههای متنی
let request = SFSpeechAudioBufferRecognitionRequest()
request.requiresOnDeviceRecognition = true
request.shouldReportPartialResults = true
request.contextualStrings = ["open contacts", "send message",
"show notifications", "چراغ قوه را روشن کن"]
recognitionTask = recognizer.recognitionTask(with: request) { result, _ in
guard let text = result?.bestTranscription.formattedString.lowercased() else { return }
voiceCommands.first { text.contains($0) }.map { command in
DispatchQueue.main.async { self.executeCommand(command) }
recognitionTask?.cancel()
}
}
دیکته در برنامههای پزشکی و حقوقی — SFSpeechRecognizer برای ایجاد اسناد ساختاریافته با صدا. Domain Adaptation: contextualStrings با اصطلاحات پزشکی/حقوقی (500+ عبارت). SFSpeechRecognitionRequest.customLmProbability — تأثیر contextualStrings (0.1–1.0). برای دیکته پزشکی از on-device استفاده کنید (حریم خصوصی دادههای بیمار). Whisper تنظیمشده بر روی دادههای پزشکی — جایگزین با WER 5% به جای 12% SFSpeechRecognizer پایه. انطباق با HIPAA: حالت on-device (دادهها دستگاه را ترک نمیکنند). برای رونویسی ویزیتها — SFSpeechURLRecognitionRequest + segments با برچسبهای زمانی گوینده.
سوالات متداول
SFSpeechRecognizer از iOS 10، macOS 10.15، watchOS 6 و tvOS 17 در دسترس است. حالت on-device — از iOS 17 (requiresOnDeviceRecognition). در iOS 10–16 SFSpeechRecognizer فقط از طریق سرورهای ابری اپل کار میکند (نیاز به اینترنت). در همه نسخهها مجوز صریح کاربر الزامی است (NSMicrophoneUsageDescription + NSSpeechRecognitionUsageDescription). SFSpeechRecognizer.supportedLocales — لیست پویا، بستگی به منطقه و مدل دستگاه دارد.
بله، با ایجاد recognitionTask جدید پس از isFinal. برای تشخیص پیوسته، task را پس از نهاییسازی قبلی راهاندازی مجدد کنید. در iOS 17 ASR پیوسته on-device 2–5% باتری در ساعت مصرف میکند (A15+). در iOS 16- ASR پیوسته نیاز به اینترنت دارد (مصرف ترافیک ~1 MB/دقیقه). برای تشخیص واقعاً پیوسته (همیشه گوش میدهد) از Vosk (آفلاین) یا Whisper Core ML استفاده کنید. SFSpeechRecognizer از حالت همیشه روشن در iOS 16- پشتیبانی نمیکند.
از result.bestTranscription.segments استفاده کنید — هر SFTranscriptionSegment حاوی confidence (Float 0..1) برای کلمه است. segments[i].substring — متن کلمه. segments[i].confidence — اطمینان ASR در این کلمه. کلمات با confidence < 0.5 — نامطمئن، آنها را در رابط برجسته کنید. segments[i].timestamp — زمان شروع (TimeInterval). segments[i].duration — مدت زمان. segments[i].alternativeSubstrings — گزینههای جایگزین تشخیص کلمه. برای فایلهای طولانی، پیمایش در segments confidence هر کلمه را بدون تجزیه دستی میدهد.
203 — SFSpeechError.ErrorCode.opportunistic (بدون اینترنت برای cloud ASR). در iOS 16- یا با request.requiresOnDeviceRecognition = false بدون اینترنت رخ میدهد. راهحل: requiresOnDeviceRecognition = true (iOS 17+) را برای کار آفلاین تنظیم کنید. در iOS 16- از NWPathMonitor استفاده کنید — در صورت نبود اینترنت پیام «برای تشخیص گفتار اینترنت لازم است» نمایش دهید. جایگزین: Vosk (آفلاین، iOS 12+) به عنوان fallback در غیاب شبکه.
SFSpeechRecognizer — API داخلی اپل، رایگان، ساده در یکپارچهسازی، اما با محدودیت طول (1–2 دقیقه)، دقت WER 7–14% و فقط برای اکوسیستم iOS. Whisper Core ML — منبع باز (MIT), 99 زبان را پشتیبانی میکند، WER 6–10%, بدون محدودیت طول، اما نیاز به یکپارچهسازی دستی، مدلهای Core ML (39M–769M پارامتر), RTF 0.5–6 (کندتر از SFSpeechRecognizer). SFSpeechRecognizer — برای ورودی صوتی استاندارد. Whisper — برای رونویسی صدای طولانی با دقت بالا.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید