You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/fa/6-consumer/lessons/1-speech-recognition/wio-terminal-speech-to-text.md

542 lines
28 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "3f92edf2975175577174910caca4a389",
"translation_date": "2025-08-25T22:48:52+00:00",
"source_file": "6-consumer/lessons/1-speech-recognition/wio-terminal-speech-to-text.md",
"language_code": "fa"
}
-->
# تبدیل گفتار به متن - Wio Terminal
در این بخش از درس، شما کدی خواهید نوشت که گفتار ضبط‌شده در فایل صوتی را به متن تبدیل کند، با استفاده از سرویس گفتار.
## ارسال فایل صوتی به سرویس گفتار
فایل صوتی می‌تواند با استفاده از REST API به سرویس گفتار ارسال شود. برای استفاده از سرویس گفتار، ابتدا باید یک توکن دسترسی درخواست کنید و سپس از آن توکن برای دسترسی به REST API استفاده کنید. این توکن‌ها پس از ۱۰ دقیقه منقضی می‌شوند، بنابراین کد شما باید به طور منظم توکن جدید درخواست کند تا همیشه به‌روز باشد.
### وظیفه - دریافت توکن دسترسی
1. پروژه `smart-timer` را باز کنید، اگر هنوز باز نشده است.
1. وابستگی‌های کتابخانه زیر را به فایل `platformio.ini` اضافه کنید تا به WiFi دسترسی داشته باشید و JSON را مدیریت کنید:
```ini
seeed-studio/Seeed Arduino rpcWiFi @ 1.0.5
seeed-studio/Seeed Arduino rpcUnified @ 2.1.3
seeed-studio/Seeed_Arduino_mbedtls @ 3.0.1
seeed-studio/Seeed Arduino RTC @ 2.0.0
bblanchon/ArduinoJson @ 6.17.3
```
1. کد زیر را به فایل هدر `config.h` اضافه کنید:
```cpp
const char *SSID = "<SSID>";
const char *PASSWORD = "<PASSWORD>";
const char *SPEECH_API_KEY = "<API_KEY>";
const char *SPEECH_LOCATION = "<LOCATION>";
const char *LANGUAGE = "<LANGUAGE>";
const char *TOKEN_URL = "https://%s.api.cognitive.microsoft.com/sts/v1.0/issuetoken";
```
`<SSID>` و `<PASSWORD>` را با مقادیر مربوط به شبکه WiFi خود جایگزین کنید.
`<API_KEY>` را با کلید API مربوط به منبع سرویس گفتار خود جایگزین کنید. `<LOCATION>` را با مکانی که هنگام ایجاد منبع سرویس گفتار استفاده کرده‌اید جایگزین کنید.
`<LANGUAGE>` را با نام محلی زبانی که در آن صحبت خواهید کرد جایگزین کنید، برای مثال `en-GB` برای انگلیسی یا `zn-HK` برای کانتونی. لیست زبان‌های پشتیبانی‌شده و نام‌های محلی آن‌ها را می‌توانید در [مستندات پشتیبانی زبان و صدا در Microsoft Docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn#speech-to-text) پیدا کنید.
ثابت `TOKEN_URL` آدرس URL صادرکننده توکن بدون مکان است. این آدرس بعداً با مکان ترکیب می‌شود تا URL کامل به دست آید.
1. درست مانند اتصال به Custom Vision، شما باید از اتصال HTTPS برای اتصال به سرویس صادرکننده توکن استفاده کنید. کد زیر را به انتهای `config.h` اضافه کنید:
```cpp
const char *TOKEN_CERTIFICATE =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIF8zCCBNugAwIBAgIQAueRcfuAIek/4tmDg0xQwDANBgkqhkiG9w0BAQwFADBh\r\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\r\n"
"MjAeFw0yMDA3MjkxMjMwMDBaFw0yNDA2MjcyMzU5NTlaMFkxCzAJBgNVBAYTAlVT\r\n"
"MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKjAoBgNVBAMTIU1pY3Jv\r\n"
"c29mdCBBenVyZSBUTFMgSXNzdWluZyBDQSAwNjCCAiIwDQYJKoZIhvcNAQEBBQAD\r\n"
"ggIPADCCAgoCggIBALVGARl56bx3KBUSGuPc4H5uoNFkFH4e7pvTCxRi4j/+z+Xb\r\n"
"wjEz+5CipDOqjx9/jWjskL5dk7PaQkzItidsAAnDCW1leZBOIi68Lff1bjTeZgMY\r\n"
"iwdRd3Y39b/lcGpiuP2d23W95YHkMMT8IlWosYIX0f4kYb62rphyfnAjYb/4Od99\r\n"
"ThnhlAxGtfvSbXcBVIKCYfZgqRvV+5lReUnd1aNjRYVzPOoifgSx2fRyy1+pO1Uz\r\n"
"aMMNnIOE71bVYW0A1hr19w7kOb0KkJXoALTDDj1ukUEDqQuBfBxReL5mXiu1O7WG\r\n"
"0vltg0VZ/SZzctBsdBlx1BkmWYBW261KZgBivrql5ELTKKd8qgtHcLQA5fl6JB0Q\r\n"
"gs5XDaWehN86Gps5JW8ArjGtjcWAIP+X8CQaWfaCnuRm6Bk/03PQWhgdi84qwA0s\r\n"
"sRfFJwHUPTNSnE8EiGVk2frt0u8PG1pwSQsFuNJfcYIHEv1vOzP7uEOuDydsmCjh\r\n"
"lxuoK2n5/2aVR3BMTu+p4+gl8alXoBycyLmj3J/PUgqD8SL5fTCUegGsdia/Sa60\r\n"
"N2oV7vQ17wjMN+LXa2rjj/b4ZlZgXVojDmAjDwIRdDUujQu0RVsJqFLMzSIHpp2C\r\n"
"Zp7mIoLrySay2YYBu7SiNwL95X6He2kS8eefBBHjzwW/9FxGqry57i71c2cDAgMB\r\n"
"AAGjggGtMIIBqTAdBgNVHQ4EFgQU1cFnOsKjnfR3UltZEjgp5lVou6UwHwYDVR0j\r\n"
"BBgwFoAUTiJUIBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1Ud\r\n"
"JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMHYG\r\n"
"CCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu\r\n"
"Y29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln\r\n"
"aUNlcnRHbG9iYWxSb290RzIuY3J0MHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9j\r\n"
"cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwN6A1oDOG\r\n"
"MWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5j\r\n"
"cmwwHQYDVR0gBBYwFDAIBgZngQwBAgEwCAYGZ4EMAQICMBAGCSsGAQQBgjcVAQQD\r\n"
"AgEAMA0GCSqGSIb3DQEBDAUAA4IBAQB2oWc93fB8esci/8esixj++N22meiGDjgF\r\n"
"+rA2LUK5IOQOgcUSTGKSqF9lYfAxPjrqPjDCUPHCURv+26ad5P/BYtXtbmtxJWu+\r\n"
"cS5BhMDPPeG3oPZwXRHBJFAkY4O4AF7RIAAUW6EzDflUoDHKv83zOiPfYGcpHc9s\r\n"
"kxAInCedk7QSgXvMARjjOqdakor21DTmNIUotxo8kHv5hwRlGhBJwps6fEVi1Bt0\r\n"
"trpM/3wYxlr473WSPUFZPgP1j519kLpWOJ8z09wxay+Br29irPcBYv0GMXlHqThy\r\n"
"8y4m/HyTQeI2IMvMrQnwqPpY+rLIXyviI2vLoI+4xKE4Rn38ZZ8m\r\n"
"-----END CERTIFICATE-----\r\n";
```
این همان گواهی است که هنگام اتصال به Custom Vision استفاده کردید.
1. یک دستور include برای فایل هدر WiFi و فایل هدر config به بالای فایل `main.cpp` اضافه کنید:
```cpp
#include <rpcWiFi.h>
#include "config.h"
```
1. کدی برای اتصال به WiFi در `main.cpp` بالای تابع `setup` اضافه کنید:
```cpp
void connectWiFi()
{
while (WiFi.status() != WL_CONNECTED)
{
Serial.println("Connecting to WiFi..");
WiFi.begin(SSID, PASSWORD);
delay(500);
}
Serial.println("Connected!");
}
```
1. این تابع را از تابع `setup` پس از برقراری اتصال سریال فراخوانی کنید:
```cpp
connectWiFi();
```
1. یک فایل هدر جدید در پوشه `src` با نام `speech_to_text.h` ایجاد کنید. در این فایل هدر، کد زیر را اضافه کنید:
```cpp
#pragma once
#include <Arduino.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include "config.h"
#include "mic.h"
class SpeechToText
{
public:
private:
};
SpeechToText speechToText;
```
این شامل برخی فایل‌های هدر ضروری برای اتصال HTTP، پیکربندی و فایل هدر `mic.h` است و یک کلاس به نام `SpeechToText` تعریف می‌کند، سپس یک نمونه از این کلاس را که بعداً می‌توان استفاده کرد اعلام می‌کند.
1. دو فیلد زیر را به بخش `private` این کلاس اضافه کنید:
```cpp
WiFiClientSecure _token_client;
String _access_token;
```
`_token_client` یک WiFi Client است که از HTTPS استفاده می‌کند و برای دریافت توکن دسترسی استفاده خواهد شد. این توکن سپس در `_access_token` ذخیره می‌شود.
1. متد زیر را به بخش `private` اضافه کنید:
```cpp
String getAccessToken()
{
char url[128];
sprintf(url, TOKEN_URL, SPEECH_LOCATION);
HTTPClient httpClient;
httpClient.begin(_token_client, url);
httpClient.addHeader("Ocp-Apim-Subscription-Key", SPEECH_API_KEY);
int httpResultCode = httpClient.POST("{}");
if (httpResultCode != 200)
{
Serial.println("Error getting access token, trying again...");
delay(10000);
return getAccessToken();
}
Serial.println("Got access token.");
String result = httpClient.getString();
httpClient.end();
return result;
}
```
این کد URL مربوط به API صادرکننده توکن را با استفاده از مکان منبع گفتار ایجاد می‌کند. سپس یک `HTTPClient` برای انجام درخواست وب ایجاد می‌کند و آن را برای استفاده از WiFi Client پیکربندی‌شده با گواهی نقاط پایانی توکن تنظیم می‌کند. کلید API به عنوان یک هدر برای درخواست تنظیم می‌شود. سپس یک درخواست POST برای دریافت گواهی انجام می‌دهد و در صورت دریافت خطا دوباره تلاش می‌کند. در نهایت توکن دسترسی بازگردانده می‌شود.
1. به بخش `public` یک متد برای دریافت توکن دسترسی اضافه کنید. این متد در درس‌های بعدی برای تبدیل متن به گفتار مورد نیاز خواهد بود.
```cpp
String AccessToken()
{
return _access_token;
}
```
1. به بخش `public` یک متد `init` اضافه کنید که کلاینت توکن را تنظیم می‌کند:
```cpp
void init()
{
_token_client.setCACert(TOKEN_CERTIFICATE);
_access_token = getAccessToken();
}
```
این گواهی را روی WiFi Client تنظیم می‌کند و سپس توکن دسترسی را دریافت می‌کند.
1. این فایل هدر جدید را به دستورات include در `main.cpp` اضافه کنید:
```cpp
#include "speech_to_text.h"
```
1. کلاس `SpeechToText` را در انتهای تابع `setup` مقداردهی اولیه کنید، پس از فراخوانی `mic.init` اما قبل از اینکه `Ready` در مانیتور سریال نوشته شود:
```cpp
speechToText.init();
```
### وظیفه - خواندن فایل صوتی از حافظه فلش
1. در بخش قبلی این درس، فایل صوتی در حافظه فلش ضبط شد. این فایل صوتی باید به REST API سرویس گفتار ارسال شود، بنابراین باید از حافظه فلش خوانده شود. نمی‌توان آن را به یک بافر در حافظه بارگذاری کرد زیرا بسیار بزرگ خواهد بود. کلاس `HTTPClient` که درخواست‌های REST را انجام می‌دهد می‌تواند داده‌ها را با استفاده از یک Arduino Stream ارسال کند - کلاسی که می‌تواند داده‌ها را در قطعات کوچک بارگذاری کند و هر قطعه را به صورت جداگانه به عنوان بخشی از درخواست ارسال کند. هر بار که `read` را روی یک استریم فراخوانی می‌کنید، بلوک بعدی داده‌ها را بازمی‌گرداند. یک Arduino Stream می‌تواند ایجاد شود که بتواند از حافظه فلش بخواند. یک فایل جدید به نام `flash_stream.h` در پوشه `src` ایجاد کنید و کد زیر را به آن اضافه کنید:
```cpp
#pragma once
#include <Arduino.h>
#include <HTTPClient.h>
#include <sfud.h>
#include "config.h"
class FlashStream : public Stream
{
public:
virtual size_t write(uint8_t val)
{
}
virtual int available()
{
}
virtual int read()
{
}
virtual int peek()
{
}
private:
};
```
این کلاس `FlashStream` را اعلام می‌کند که از کلاس `Stream` Arduino مشتق شده است. این یک کلاس انتزاعی است - کلاس‌های مشتق‌شده باید چند متد را قبل از اینکه کلاس قابل مقداردهی اولیه باشد پیاده‌سازی کنند، و این متدها در این کلاس تعریف شده‌اند.
✅ اطلاعات بیشتر درباره Arduino Streams را در [مستندات Arduino Stream](https://www.arduino.cc/reference/en/language/functions/communication/stream/) بخوانید.
1. فیلدهای زیر را به بخش `private` اضافه کنید:
```cpp
size_t _pos;
size_t _flash_address;
const sfud_flash *_flash;
byte _buffer[HTTP_TCP_BUFFER_SIZE];
```
این یک بافر موقت برای ذخیره داده‌های خوانده‌شده از حافظه فلش تعریف می‌کند، همراه با فیلدهایی برای ذخیره موقعیت فعلی هنگام خواندن از بافر، آدرس فعلی برای خواندن از حافظه فلش، و دستگاه حافظه فلش.
1. متد زیر را به بخش `private` اضافه کنید:
```cpp
void populateBuffer()
{
sfud_read(_flash, _flash_address, HTTP_TCP_BUFFER_SIZE, _buffer);
_flash_address += HTTP_TCP_BUFFER_SIZE;
_pos = 0;
}
```
این کد از حافظه فلش در آدرس فعلی می‌خواند و داده‌ها را در یک بافر ذخیره می‌کند. سپس آدرس را افزایش می‌دهد، بنابراین فراخوانی بعدی بلوک بعدی حافظه را می‌خواند. اندازه بافر بر اساس بزرگ‌ترین قطعه‌ای که `HTTPClient` در یک زمان به REST API ارسال خواهد کرد تنظیم شده است.
> 💁 پاک کردن حافظه فلش باید با اندازه دانه انجام شود، اما خواندن نیازی به این کار ندارد.
1. یک سازنده به بخش `public` این کلاس اضافه کنید:
```cpp
FlashStream()
{
_pos = 0;
_flash_address = 0;
_flash = sfud_get_device_table() + 0;
populateBuffer();
}
```
این سازنده تمام فیلدها را برای شروع خواندن از ابتدای بلوک حافظه فلش تنظیم می‌کند و اولین قطعه داده‌ها را در بافر بارگذاری می‌کند.
1. متد `write` را پیاده‌سازی کنید. این استریم فقط داده‌ها را می‌خواند، بنابراین این متد می‌تواند هیچ کاری انجام ندهد و مقدار ۰ را بازگرداند:
```cpp
virtual size_t write(uint8_t val)
{
return 0;
}
```
1. متد `peek` را پیاده‌سازی کنید. این داده‌ها را در موقعیت فعلی بدون حرکت دادن استریم بازمی‌گرداند. فراخوانی چندباره `peek` همیشه همان داده‌ها را بازمی‌گرداند تا زمانی که داده‌ای از استریم خوانده نشود.
```cpp
virtual int peek()
{
return _buffer[_pos];
}
```
1. تابع `available` را پیاده‌سازی کنید. این تعداد بایت‌هایی که می‌توان از استریم خواند را بازمی‌گرداند، یا -1 اگر استریم کامل شده باشد. برای این کلاس، حداکثر مقدار موجود هرگز بیشتر از اندازه قطعه HTTPClient نخواهد بود. وقتی این استریم در HTTPClient استفاده می‌شود، تابع `available` را فراخوانی می‌کند تا ببیند چه مقدار داده موجود است، سپس همان مقدار داده را برای ارسال به REST API درخواست می‌کند. نمی‌خواهیم هر قطعه بیشتر از اندازه قطعه HTTPClient باشد، بنابراین اگر بیشتر از آن موجود باشد، اندازه قطعه بازگردانده می‌شود. اگر کمتر باشد، مقدار موجود بازگردانده می‌شود. وقتی تمام داده‌ها استریم شدند، مقدار -1 بازگردانده می‌شود.
```cpp
virtual int available()
{
int remaining = BUFFER_SIZE - ((_flash_address - HTTP_TCP_BUFFER_SIZE) + _pos);
int bytes_available = min(HTTP_TCP_BUFFER_SIZE, remaining);
if (bytes_available == 0)
{
bytes_available = -1;
}
return bytes_available;
}
```
1. متد `read` را پیاده‌سازی کنید تا بایت بعدی از بافر بازگردانده شود و موقعیت افزایش یابد. اگر موقعیت از اندازه بافر فراتر رود، بافر با بلوک بعدی از حافظه فلش پر می‌شود و موقعیت بازنشانی می‌شود.
```cpp
virtual int read()
{
int retVal = _buffer[_pos++];
if (_pos == HTTP_TCP_BUFFER_SIZE)
{
populateBuffer();
}
return retVal;
}
```
1. در فایل هدر `speech_to_text.h` یک دستور include برای این فایل هدر جدید اضافه کنید:
```cpp
#include "flash_stream.h"
```
### وظیفه - تبدیل گفتار به متن
1. گفتار می‌تواند با ارسال فایل صوتی به سرویس گفتار از طریق REST API به متن تبدیل شود. این REST API گواهی متفاوتی نسبت به صادرکننده توکن دارد، بنابراین کد زیر را به فایل هدر `config.h` اضافه کنید تا این گواهی تعریف شود:
```cpp
const char *SPEECH_CERTIFICATE =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIF8zCCBNugAwIBAgIQCq+mxcpjxFFB6jvh98dTFzANBgkqhkiG9w0BAQwFADBh\r\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\r\n"
"MjAeFw0yMDA3MjkxMjMwMDBaFw0yNDA2MjcyMzU5NTlaMFkxCzAJBgNVBAYTAlVT\r\n"
"MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKjAoBgNVBAMTIU1pY3Jv\r\n"
"c29mdCBBenVyZSBUTFMgSXNzdWluZyBDQSAwMTCCAiIwDQYJKoZIhvcNAQEBBQAD\r\n"
"ggIPADCCAgoCggIBAMedcDrkXufP7pxVm1FHLDNA9IjwHaMoaY8arqqZ4Gff4xyr\r\n"
"RygnavXL7g12MPAx8Q6Dd9hfBzrfWxkF0Br2wIvlvkzW01naNVSkHp+OS3hL3W6n\r\n"
"l/jYvZnVeJXjtsKYcXIf/6WtspcF5awlQ9LZJcjwaH7KoZuK+THpXCMtzD8XNVdm\r\n"
"GW/JI0C/7U/E7evXn9XDio8SYkGSM63aLO5BtLCv092+1d4GGBSQYolRq+7Pd1kR\r\n"
"EkWBPm0ywZ2Vb8GIS5DLrjelEkBnKCyy3B0yQud9dpVsiUeE7F5sY8Me96WVxQcb\r\n"
"OyYdEY/j/9UpDlOG+vA+YgOvBhkKEjiqygVpP8EZoMMijephzg43b5Qi9r5UrvYo\r\n"
"o19oR/8pf4HJNDPF0/FJwFVMW8PmCBLGstin3NE1+NeWTkGt0TzpHjgKyfaDP2tO\r\n"
"4bCk1G7pP2kDFT7SYfc8xbgCkFQ2UCEXsaH/f5YmpLn4YPiNFCeeIida7xnfTvc4\r\n"
"7IxyVccHHq1FzGygOqemrxEETKh8hvDR6eBdrBwmCHVgZrnAqnn93JtGyPLi6+cj\r\n"
"WGVGtMZHwzVvX1HvSFG771sskcEjJxiQNQDQRWHEh3NxvNb7kFlAXnVdRkkvhjpR\r\n"
"GchFhTAzqmwltdWhWDEyCMKC2x/mSZvZtlZGY+g37Y72qHzidwtyW7rBetZJAgMB\r\n"
"AAGjggGtMIIBqTAdBgNVHQ4EFgQUDyBd16FXlduSzyvQx8J3BM5ygHYwHwYDVR0j\r\n"
"BBgwFoAUTiJUIBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1Ud\r\n"
"JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMHYG\r\n"
"CCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu\r\n"
"Y29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln\r\n"
"aUNlcnRHbG9iYWxSb290RzIuY3J0MHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9j\r\n"
"cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwN6A1oDOG\r\n"
"MWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5j\r\n"
"cmwwHQYDVR0gBBYwFDAIBgZngQwBAgEwCAYGZ4EMAQICMBAGCSsGAQQBgjcVAQQD\r\n"
"AgEAMA0GCSqGSIb3DQEBDAUAA4IBAQAlFvNh7QgXVLAZSsNR2XRmIn9iS8OHFCBA\r\n"
"WxKJoi8YYQafpMTkMqeuzoL3HWb1pYEipsDkhiMnrpfeYZEA7Lz7yqEEtfgHcEBs\r\n"
"K9KcStQGGZRfmWU07hPXHnFz+5gTXqzCE2PBMlRgVUYJiA25mJPXfB00gDvGhtYa\r\n"
"+mENwM9Bq1B9YYLyLjRtUz8cyGsdyTIG/bBM/Q9jcV8JGqMU/UjAdh1pFyTnnHEl\r\n"
"Y59Npi7F87ZqYYJEHJM2LGD+le8VsHjgeWX2CJQko7klXvcizuZvUEDTjHaQcs2J\r\n"
"+kPgfyMIOY1DMJ21NxOJ2xPRC/wAh/hzSBRVtoAnyuxtkZ4VjIOh\r\n"
"-----END CERTIFICATE-----\r\n";
```
1. یک ثابت برای URL گفتار بدون مکان به این فایل اضافه کنید. این URL بعداً با مکان و زبان ترکیب خواهد شد تا URL کامل به دست آید.
```cpp
const char *SPEECH_URL = "https://%s.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=%s";
```
1. در فایل هدر `speech_to_text.h`، در بخش `private` کلاس `SpeechToText`، یک فیلد برای WiFi Client با استفاده از گواهی گفتار تعریف کنید:
```cpp
WiFiClientSecure _speech_client;
```
1. در متد `init` گواهی را روی این WiFi Client تنظیم کنید:
```cpp
_speech_client.setCACert(SPEECH_CERTIFICATE);
```
1. کد زیر را به بخش `public` کلاس `SpeechToText` اضافه کنید تا یک متد برای تبدیل گفتار به متن تعریف شود:
```cpp
String convertSpeechToText()
{
}
```
1. کد زیر را به این متد اضافه کنید تا یک HTTPClient با استفاده از WiFi Client پیکربندی‌شده با گواهی گفتار ایجاد شود و از URL گفتار تنظیم‌شده با مکان و زبان استفاده کند:
```cpp
char url[128];
sprintf(url, SPEECH_URL, SPEECH_LOCATION, LANGUAGE);
HTTPClient httpClient;
httpClient.begin(_speech_client, url);
```
1. برخی هدرها باید روی اتصال تنظیم شوند:
```cpp
httpClient.addHeader("Authorization", String("Bearer ") + _access_token);
httpClient.addHeader("Content-Type", String("audio/wav; codecs=audio/pcm; samplerate=") + String(RATE));
httpClient.addHeader("Accept", "application/json;text/xml");
```
این هدرها برای احراز هویت با استفاده از توکن دسترسی، فرمت فایل صوتی با استفاده از نرخ نمونه‌برداری، و تنظیم اینکه کلاینت انتظار دارد نتیجه به صورت JSON باشد تنظیم می‌شوند.
1. پس از این، کد زیر را برای انجام درخواست REST API اضافه کنید:
```cpp
Serial.println("Sending speech...");
FlashStream stream;
int httpResponseCode = httpClient.sendRequest("POST", &stream, BUFFER_SIZE);
Serial.println("Speech sent!");
```
این یک `FlashStream` ایجاد می‌کند و از آن برای ارسال داده‌ها به REST API استفاده می‌کند.
1. کد زیر را به این متد اضافه کنید:
```cpp
String text = "";
if (httpResponseCode == 200)
{
String result = httpClient.getString();
Serial.println(result);
DynamicJsonDocument doc(1024);
deserializeJson(doc, result.c_str());
JsonObject obj = doc.as<JsonObject>();
text = obj["DisplayText"].as<String>();
}
else if (httpResponseCode == 401)
{
Serial.println("Access token expired, trying again with a new token");
_access_token = getAccessToken();
return convertSpeechToText();
}
else
{
Serial.print("Failed to convert text to speech - error ");
Serial.println(httpResponseCode);
}
```
این کد کد پاسخ را بررسی می‌کند.
اگر کد 200 باشد، که کد موفقیت است، نتیجه دریافت می‌شود، از JSON رمزگشایی می‌شود، و ویژگی `DisplayText` در متغیر `text` تنظیم می‌شود. این ویژگی متن گفتار به صورت متن بازگردانده می‌شود.
اگر کد پاسخ 401 باشد، توکن دسترسی منقضی شده است (این توکن‌ها فقط ۱۰ دقیقه اعتبار دارند). یک توکن دسترسی جدید درخواست می‌شود و درخواست دوباره انجام می‌شود.
در غیر این صورت، یک خطا به مانیتور سریال ارسال می‌شود و `text` خالی باقی می‌ماند.
1. کد زیر را به انتهای این متد اضافه کنید تا HTTPClient بسته شود و متن بازگردانده شود:
```cpp
httpClient.end();
return text;
```
1. در `main.cpp` این متد جدید `convertSpeechToText` را در تابع `processAudio` فراخوانی کنید، سپس گفتار را در مانیتور سریال ثبت کنید:
```cpp
String text = speechToText.convertSpeechToText();
Serial.println(text);
```
1. این کد را بسازید، آن را به Wio Terminal خود آپلود کنید و از طریق مانیتور سریال آن را آزمایش کنید. هنگامی که `Ready` را در مانیتور سریال مشاهده کردید، دکمه C (دکمه سمت چپ، نزدیک به کلید پاور) را فشار دهید و صحبت کنید. ۴ ثانیه فایل صوتی ضبط می‌شود و سپس به متن تبدیل می‌شود.
```output
--- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at http://bit.ly/pio-monitor-filters
--- Miniterm on /dev/cu.usbmodem1101 9600,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
Connecting to WiFi..
Connected!
Got access token.
Ready.
Starting recording...
Finished recording
Sending speech...
Speech sent!
{"RecognitionStatus":"Success","DisplayText":"Set a 2 minute and 27 second timer.","Offset":4700000,"Duration":35300000}
Set a 2 minute and 27 second timer.
```
> 💁 می‌توانید این کد را در پوشه [code-speech-to-text/wio-terminal](../../../../../6-consumer/lessons/1-speech-recognition/code-speech-to-text/wio-terminal) پیدا کنید.
😀 برنامه تبدیل گفتار به متن شما موفقیت‌آمیز بود!
**سلب مسئولیت**:
این سند با استفاده از سرویس ترجمه هوش مصنوعی [Co-op Translator](https://github.com/Azure/co-op-translator) ترجمه شده است. در حالی که ما تلاش می‌کنیم دقت را حفظ کنیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادرستی‌ها باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حساس، توصیه می‌شود از ترجمه حرفه‌ای انسانی استفاده کنید. ما مسئولیتی در قبال سوء تفاهم‌ها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.