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

28 KiB

تبدیل گفتار به متن - Wio Terminal

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

ارسال فایل صوتی به سرویس گفتار

فایل صوتی می‌تواند با استفاده از REST API به سرویس گفتار ارسال شود. برای استفاده از سرویس گفتار، ابتدا باید یک توکن دسترسی درخواست کنید و سپس از آن توکن برای دسترسی به REST API استفاده کنید. این توکن‌ها پس از ۱۰ دقیقه منقضی می‌شوند، بنابراین کد شما باید به طور منظم توکن جدید درخواست کند تا همیشه به‌روز باشد.

وظیفه - دریافت توکن دسترسی

  1. پروژه smart-timer را باز کنید، اگر هنوز باز نشده است.

  2. وابستگی‌های کتابخانه زیر را به فایل platformio.ini اضافه کنید تا به WiFi دسترسی داشته باشید و JSON را مدیریت کنید:

    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
    
  3. کد زیر را به فایل هدر config.h اضافه کنید:

    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 پیدا کنید.

    ثابت TOKEN_URL آدرس URL صادرکننده توکن بدون مکان است. این آدرس بعداً با مکان ترکیب می‌شود تا URL کامل به دست آید.

  4. درست مانند اتصال به Custom Vision، شما باید از اتصال HTTPS برای اتصال به سرویس صادرکننده توکن استفاده کنید. کد زیر را به انتهای config.h اضافه کنید:

    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 استفاده کردید.

  5. یک دستور include برای فایل هدر WiFi و فایل هدر config به بالای فایل main.cpp اضافه کنید:

    #include <rpcWiFi.h>
    
    #include "config.h"
    
  6. کدی برای اتصال به WiFi در main.cpp بالای تابع setup اضافه کنید:

    void connectWiFi()
    {
        while (WiFi.status() != WL_CONNECTED)
        {
            Serial.println("Connecting to WiFi..");
            WiFi.begin(SSID, PASSWORD);
            delay(500);
        }
    
        Serial.println("Connected!");
    }
    
  7. این تابع را از تابع setup پس از برقراری اتصال سریال فراخوانی کنید:

    connectWiFi();
    
  8. یک فایل هدر جدید در پوشه src با نام speech_to_text.h ایجاد کنید. در این فایل هدر، کد زیر را اضافه کنید:

    #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 تعریف می‌کند، سپس یک نمونه از این کلاس را که بعداً می‌توان استفاده کرد اعلام می‌کند.

  9. دو فیلد زیر را به بخش private این کلاس اضافه کنید:

    WiFiClientSecure _token_client;
    String _access_token;
    

    _token_client یک WiFi Client است که از HTTPS استفاده می‌کند و برای دریافت توکن دسترسی استفاده خواهد شد. این توکن سپس در _access_token ذخیره می‌شود.

  10. متد زیر را به بخش private اضافه کنید:

    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 برای دریافت گواهی انجام می‌دهد و در صورت دریافت خطا دوباره تلاش می‌کند. در نهایت توکن دسترسی بازگردانده می‌شود.

  11. به بخش public یک متد برای دریافت توکن دسترسی اضافه کنید. این متد در درس‌های بعدی برای تبدیل متن به گفتار مورد نیاز خواهد بود.

    String AccessToken()
    {
        return _access_token;
    }
    
  12. به بخش public یک متد init اضافه کنید که کلاینت توکن را تنظیم می‌کند:

    void init()
    {
        _token_client.setCACert(TOKEN_CERTIFICATE);
        _access_token = getAccessToken();
    }
    

    این گواهی را روی WiFi Client تنظیم می‌کند و سپس توکن دسترسی را دریافت می‌کند.

  13. این فایل هدر جدید را به دستورات include در main.cpp اضافه کنید:

    #include "speech_to_text.h"
    
  14. کلاس SpeechToText را در انتهای تابع setup مقداردهی اولیه کنید، پس از فراخوانی mic.init اما قبل از اینکه Ready در مانیتور سریال نوشته شود:

    speechToText.init();
    

وظیفه - خواندن فایل صوتی از حافظه فلش

  1. در بخش قبلی این درس، فایل صوتی در حافظه فلش ضبط شد. این فایل صوتی باید به REST API سرویس گفتار ارسال شود، بنابراین باید از حافظه فلش خوانده شود. نمی‌توان آن را به یک بافر در حافظه بارگذاری کرد زیرا بسیار بزرگ خواهد بود. کلاس HTTPClient که درخواست‌های REST را انجام می‌دهد می‌تواند داده‌ها را با استفاده از یک Arduino Stream ارسال کند - کلاسی که می‌تواند داده‌ها را در قطعات کوچک بارگذاری کند و هر قطعه را به صورت جداگانه به عنوان بخشی از درخواست ارسال کند. هر بار که read را روی یک استریم فراخوانی می‌کنید، بلوک بعدی داده‌ها را بازمی‌گرداند. یک Arduino Stream می‌تواند ایجاد شود که بتواند از حافظه فلش بخواند. یک فایل جدید به نام flash_stream.h در پوشه src ایجاد کنید و کد زیر را به آن اضافه کنید:

    #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 بخوانید.

  2. فیلدهای زیر را به بخش private اضافه کنید:

    size_t _pos;
    size_t _flash_address;
    const sfud_flash *_flash;
    
    byte _buffer[HTTP_TCP_BUFFER_SIZE];
    

    این یک بافر موقت برای ذخیره داده‌های خوانده‌شده از حافظه فلش تعریف می‌کند، همراه با فیلدهایی برای ذخیره موقعیت فعلی هنگام خواندن از بافر، آدرس فعلی برای خواندن از حافظه فلش، و دستگاه حافظه فلش.

  3. متد زیر را به بخش private اضافه کنید:

    void populateBuffer()
    {
        sfud_read(_flash, _flash_address, HTTP_TCP_BUFFER_SIZE, _buffer);
        _flash_address += HTTP_TCP_BUFFER_SIZE;
        _pos = 0;
    }
    

    این کد از حافظه فلش در آدرس فعلی می‌خواند و داده‌ها را در یک بافر ذخیره می‌کند. سپس آدرس را افزایش می‌دهد، بنابراین فراخوانی بعدی بلوک بعدی حافظه را می‌خواند. اندازه بافر بر اساس بزرگ‌ترین قطعه‌ای که HTTPClient در یک زمان به REST API ارسال خواهد کرد تنظیم شده است.

    💁 پاک کردن حافظه فلش باید با اندازه دانه انجام شود، اما خواندن نیازی به این کار ندارد.

  4. یک سازنده به بخش public این کلاس اضافه کنید:

    FlashStream()
    {
        _pos = 0;
        _flash_address = 0;
        _flash = sfud_get_device_table() + 0;
    
        populateBuffer();
    }
    

    این سازنده تمام فیلدها را برای شروع خواندن از ابتدای بلوک حافظه فلش تنظیم می‌کند و اولین قطعه داده‌ها را در بافر بارگذاری می‌کند.

  5. متد write را پیاده‌سازی کنید. این استریم فقط داده‌ها را می‌خواند، بنابراین این متد می‌تواند هیچ کاری انجام ندهد و مقدار ۰ را بازگرداند:

    virtual size_t write(uint8_t val)
    {
        return 0;
    }
    
  6. متد peek را پیاده‌سازی کنید. این داده‌ها را در موقعیت فعلی بدون حرکت دادن استریم بازمی‌گرداند. فراخوانی چندباره peek همیشه همان داده‌ها را بازمی‌گرداند تا زمانی که داده‌ای از استریم خوانده نشود.

    virtual int peek()
    {
        return _buffer[_pos];
    }
    
  7. تابع available را پیاده‌سازی کنید. این تعداد بایت‌هایی که می‌توان از استریم خواند را بازمی‌گرداند، یا -1 اگر استریم کامل شده باشد. برای این کلاس، حداکثر مقدار موجود هرگز بیشتر از اندازه قطعه HTTPClient نخواهد بود. وقتی این استریم در HTTPClient استفاده می‌شود، تابع available را فراخوانی می‌کند تا ببیند چه مقدار داده موجود است، سپس همان مقدار داده را برای ارسال به REST API درخواست می‌کند. نمی‌خواهیم هر قطعه بیشتر از اندازه قطعه HTTPClient باشد، بنابراین اگر بیشتر از آن موجود باشد، اندازه قطعه بازگردانده می‌شود. اگر کمتر باشد، مقدار موجود بازگردانده می‌شود. وقتی تمام داده‌ها استریم شدند، مقدار -1 بازگردانده می‌شود.

    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;
    }
    
  8. متد read را پیاده‌سازی کنید تا بایت بعدی از بافر بازگردانده شود و موقعیت افزایش یابد. اگر موقعیت از اندازه بافر فراتر رود، بافر با بلوک بعدی از حافظه فلش پر می‌شود و موقعیت بازنشانی می‌شود.

    virtual int read()
    {
        int retVal = _buffer[_pos++];
    
        if (_pos == HTTP_TCP_BUFFER_SIZE)
        {
            populateBuffer();
        }
    
        return retVal;
    }
    
  9. در فایل هدر speech_to_text.h یک دستور include برای این فایل هدر جدید اضافه کنید:

    #include "flash_stream.h"
    

وظیفه - تبدیل گفتار به متن

  1. گفتار می‌تواند با ارسال فایل صوتی به سرویس گفتار از طریق REST API به متن تبدیل شود. این REST API گواهی متفاوتی نسبت به صادرکننده توکن دارد، بنابراین کد زیر را به فایل هدر config.h اضافه کنید تا این گواهی تعریف شود:

    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";
    
  2. یک ثابت برای URL گفتار بدون مکان به این فایل اضافه کنید. این URL بعداً با مکان و زبان ترکیب خواهد شد تا URL کامل به دست آید.

    const char *SPEECH_URL = "https://%s.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=%s";
    
  3. در فایل هدر speech_to_text.h، در بخش private کلاس SpeechToText، یک فیلد برای WiFi Client با استفاده از گواهی گفتار تعریف کنید:

    WiFiClientSecure _speech_client;
    
  4. در متد init گواهی را روی این WiFi Client تنظیم کنید:

    _speech_client.setCACert(SPEECH_CERTIFICATE);
    
  5. کد زیر را به بخش public کلاس SpeechToText اضافه کنید تا یک متد برای تبدیل گفتار به متن تعریف شود:

    String convertSpeechToText()
    {
    
    }
    
  6. کد زیر را به این متد اضافه کنید تا یک HTTPClient با استفاده از WiFi Client پیکربندی‌شده با گواهی گفتار ایجاد شود و از URL گفتار تنظیم‌شده با مکان و زبان استفاده کند:

    char url[128];
    sprintf(url, SPEECH_URL, SPEECH_LOCATION, LANGUAGE);
    
    HTTPClient httpClient;
    httpClient.begin(_speech_client, url);
    
  7. برخی هدرها باید روی اتصال تنظیم شوند:

    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 باشد تنظیم می‌شوند.

  8. پس از این، کد زیر را برای انجام درخواست REST API اضافه کنید:

    Serial.println("Sending speech...");
    
    FlashStream stream;
    int httpResponseCode = httpClient.sendRequest("POST", &stream, BUFFER_SIZE);
    
    Serial.println("Speech sent!");
    

    این یک FlashStream ایجاد می‌کند و از آن برای ارسال داده‌ها به REST API استفاده می‌کند.

  9. کد زیر را به این متد اضافه کنید:

    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 خالی باقی می‌ماند.

  10. کد زیر را به انتهای این متد اضافه کنید تا HTTPClient بسته شود و متن بازگردانده شود:

    httpClient.end();
    
    return text;
    
  11. در main.cpp این متد جدید convertSpeechToText را در تابع processAudio فراخوانی کنید، سپس گفتار را در مانیتور سریال ثبت کنید:

    String text = speechToText.convertSpeechToText();
    Serial.println(text);
    
  12. این کد را بسازید، آن را به Wio Terminal خود آپلود کنید و از طریق مانیتور سریال آن را آزمایش کنید. هنگامی که Ready را در مانیتور سریال مشاهده کردید، دکمه C (دکمه سمت چپ، نزدیک به کلید پاور) را فشار دهید و صحبت کنید. ۴ ثانیه فایل صوتی ضبط می‌شود و سپس به متن تبدیل می‌شود.

    --- 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 پیدا کنید.

😀 برنامه تبدیل گفتار به متن شما موفقیت‌آمیز بود!

سلب مسئولیت:
این سند با استفاده از سرویس ترجمه هوش مصنوعی Co-op Translator ترجمه شده است. در حالی که ما تلاش می‌کنیم دقت را حفظ کنیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادرستی‌ها باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حساس، توصیه می‌شود از ترجمه حرفه‌ای انسانی استفاده کنید. ما مسئولیتی در قبال سوء تفاهم‌ها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.