Skip to main content

🎙ïļ āļĢāļ°āļšāļšāđāļ›āļĨāļ‡āđ€āļŠāļĩāļĒāļ‡āļžāļđāļ”āļ āļēāļĐāļēāđ„āļ—āļĒāđ€āļ›āđ‡āļ™āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ (ASR) 🆕

🎙ïļ āļĢāļ°āļšāļšāđāļ›āļĨāļ‡āđ€āļŠāļĩāļĒāļ‡āļžāļđāļ”āļ āļēāļĐāļēāđ„āļ—āļĒāđ€āļ›āđ‡āļ™āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ (Real-time)

Version Status

āļĒāļīāļ™āļ”āļĩāļ•āđ‰āļ­āļ™āļĢāļąāļšāļŠāļđāđˆāļĢāļ°āļšāļš ASR āđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒāļŠāļģāļŦāļĢāļąāļšāļ āļēāļĐāļēāđ„āļ—āļĒ - āļšāļĢāļīāļāļēāļĢāļˆāļ”āļˆāļģāļ„āļģāļžāļđāļ”āļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļīāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒāļ—āļĩāđˆāđƒāļŠāđ‰ WebSocket āļ‚āļ­āļ‡āđ€āļĢāļē āļšāļĢāļīāļāļēāļĢāļ™āļĩāđ‰āđāļ›āļĨāļ‡āļ‚āđ‰āļ­āļĄāļđāļĨāļŠāļ•āļĢāļĩāļĄāđ€āļŠāļĩāļĒāļ‡āđ€āļ›āđ‡āļ™āļ‚āđ‰āļ­āļĄāļđāļĨāļŠāļ•āļĢāļĩāļĄāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ āļĢāļ­āļ‡āļĢāļąāļšāļ—āļąāđ‰āļ‡āļāļēāļĢāļŠāļ•āļĢāļĩāļĄāđ„āļŸāļĨāđŒāđāļĨāļ°āļāļēāļĢāļšāļąāļ™āļ—āļķāļāļˆāļēāļāđ„āļĄāđ‚āļ„āļĢāđ‚āļŸāļ™āđ‚āļ”āļĒāļ•āļĢāļ‡

iApp Text to Speech API

āđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āđƒāļŠāđ‰āļ‡āļēāļ™â€‹

  1. āļ‚āđ‰āļ­āļāļģāļŦāļ™āļ”āđ€āļšāļ·āđ‰āļ­āļ‡āļ•āđ‰āļ™

    • API key āļˆāļēāļ āļšāļĢāļīāļĐāļąāļ— āđ„āļ­āđāļ­āļžāļžāđŒāđ€āļ—āļ„āđ‚āļ™āđ‚āļĨāļĒāļĩ āļˆāļģāļāļąāļ”
    • āļŠāļ•āļĢāļĩāļĄāđ€āļŠāļĩāļĒāļ‡āđƒāļ™āļĢāļđāļ›āđāļšāļšāļ—āļĩāđˆāļĢāļ­āļ‡āļĢāļąāļš
    • āļāļēāļĢāđƒāļŠāđ‰āļ‡āļēāļ™ WebSocket client
    • āļĢāļđāļ›āđāļšāļšāļ—āļĩāđˆāļĢāļ­āļ‡āļĢāļąāļš: āđ€āļŠāļĩāļĒāļ‡ PCM
    • āđ„āļĄāđˆāļĄāļĩāļ‚āđ‰āļ­āļˆāļģāļāļąāļ”āļ„āļ§āļēāļĄāļĒāļēāļ§āļ—āļĩāđˆāđ€āļ‰āļžāļēāļ°āđ€āļˆāļēāļ°āļˆāļ‡
  2. āđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āļ­āļĒāđˆāļēāļ‡āļĢāļ§āļ”āđ€āļĢāđ‡āļ§

    • āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
    • āļŠāļ•āļĢāļĩāļĄāļˆāļēāļāđ„āļŸāļĨāđŒāļŦāļĢāļ·āļ­āđ„āļĄāđ‚āļ„āļĢāđ‚āļŸāļ™
    • āļĢāļ­āļ‡āļĢāļąāļšāļ āļēāļĐāļēāđ„āļ—āļĒ
  3. āļ„āļļāļ“āļŠāļĄāļšāļąāļ•āļīāļŦāļĨāļąāļ

    • āļāļēāļĢāļŠāļ•āļĢāļĩāļĄāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
    • āļāļēāļĢāļŠāļ·āđˆāļ­āļŠāļēāļĢāđāļšāļšāđƒāļŠāđ‰ WebSocket
    • āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāļ—āļĩāđˆāļĄāļĩāđ€āļ§āļĨāļēāđāļāļ‡āļ•āđˆāļģ
    • āļ•āļąāļ§āđ€āļĨāļ·āļ­āļāļāļēāļĢāļœāļŠāļēāļ™āļĢāļ§āļĄāļ—āļĩāđˆāļĒāļ·āļ”āļŦāļĒāļļāđˆāļ™
    • āļāļēāļĢāļˆāļ”āļˆāļģāļ„āļģāļžāļđāļ”āļ­āļĒāđˆāļēāļ‡āļ•āđˆāļ­āđ€āļ™āļ·āđˆāļ­āļ‡
  4. āļ„āļ§āļēāļĄāļ›āļĨāļ­āļ”āļ āļąāļĒāđāļĨāļ°āļāļēāļĢāļ›āļāļīāļšāļąāļ•āļīāļ•āļēāļĄāļāļŽāļĢāļ°āđ€āļšāļĩāļĒāļš

    • āļ›āļāļīāļšāļąāļ•āļīāļ•āļēāļĄ GDPR āđāļĨāļ° PDPA
    • āļĢāļ­āļ‡āļĢāļąāļš WebSocket āļ—āļĩāđˆāļ›āļĨāļ­āļ”āļ āļąāļĒ (WSS)
    • āđ„āļĄāđˆāļĄāļĩāļāļēāļĢāđ€āļāđ‡āļšāļĢāļąāļāļĐāļēāļ‚āđ‰āļ­āļĄāļđāļĨāļŦāļĨāļąāļ‡āļˆāļēāļāļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨ
āļ§āļīāļ˜āļĩāļāļēāļĢāļĢāļąāļš API Key?

āļāļĢāļļāļ“āļēāđ€āļĒāļĩāđˆāļĒāļĄāļŠāļĄ iApp AI Portal āđ€āļžāļ·āđˆāļ­āļ”āļđ API key āļ—āļĩāđˆāļĄāļĩāļ­āļĒāļđāđˆāļ‚āļ­āļ‡āļ„āļļāļ“āļŦāļĢāļ·āļ­āļ‚āļ­ API key āđƒāļŦāļĄāđˆ

āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡â€‹

āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āļ„āļģāļ‚āļ­:​

  • āđ„āļĄāđˆāļĄāļĩāļāļēāļĢāđ€āļ‚āđ‰āļēāļĢāļŦāļąāļŠ : ws://api-uat.iapp.co.th/asr
  • āļĄāļĩāļāļēāļĢāđ€āļ‚āđ‰āļēāļĢāļŦāļąāļŠ : wss://api-uat.iapp.co.th/asr

āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āļāļēāļĢāļ•āļ­āļšāļŠāļ™āļ­āļ‡:​

{
"type": "realtime",
"state": "Sentence",
"text": "āļŠāļ§āļąāļŠāļ”āļĩāļ„āļĢāļąāļš"
}

āļ„āļļāļ“āļŠāļĄāļšāļąāļ•āļīāđāļĨāļ°āļ„āļ§āļēāļĄāļŠāļēāļĄāļēāļĢāļ–​

āļ„āļļāļ“āļŠāļĄāļšāļąāļ•āļīāļŦāļĨāļąāļâ€‹

  • āļāļēāļĢāļˆāļ”āļˆāļģāļ„āļģāļžāļđāļ”āđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
  • āļĢāļ­āļ‡āļĢāļąāļšāļāļēāļĢāļŠāļ•āļĢāļĩāļĄ WebSocket
  • āļ­āļīāļ™āļžāļļāļ•āļˆāļēāļāđ„āļŸāļĨāđŒāđāļĨāļ°āđ„āļĄāđ‚āļ„āļĢāđ‚āļŸāļ™
  • āļĢāļ°āļšāļšāļāļēāļĢāļ•āļ­āļšāļŠāļ™āļ­āļ‡āļ•āļēāļĄāļŠāļ–āļēāļ™āļ°
  • āļāļēāļĢāļˆāļ”āļˆāļģāļ­āļĒāđˆāļēāļ‡āļ•āđˆāļ­āđ€āļ™āļ·āđˆāļ­āļ‡

āļŸāļīāļĨāļ”āđŒāļ—āļĩāđˆāļĢāļ­āļ‡āļĢāļąāļšâ€‹

  • āļ‚āđ‰āļ­āļĄāļđāļĨāļŠāļ•āļĢāļĩāļĄāđ€āļŠāļĩāļĒāļ‡
  • āļĢāļđāļ›āđāļšāļšāđ€āļŠāļĩāļĒāļ‡ PCM
  • āđ‚āļ›āļĢāđ‚āļ•āļ„āļ­āļĨ WebSocket
  • āđ€āļ­āļēāļ•āđŒāļžāļļāļ•āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
  • āļ•āļąāļ§āļšāđˆāļ‡āļŠāļĩāđ‰āļŠāļ–āļēāļ™āļ°

āļ‚āđ‰āļ­āļĄāļđāļĨāļ­āđ‰āļēāļ‡āļ­āļīāļ‡ API​

  • āļˆāļļāļ”āļŠāļīāđ‰āļ™āļŠāļļāļ”:
    • āđ„āļĄāđˆāļĄāļĩāļāļēāļĢāđ€āļ‚āđ‰āļēāļĢāļŦāļąāļŠ : ws://api-uat.iapp.co.th/asr
    • āļĄāļĩāļāļēāļĢāđ€āļ‚āđ‰āļēāļĢāļŦāļąāļŠ : wss://api-uat.iapp.co.th/asr
  • āļŠāđˆāļ§āļ™āļŦāļąāļ§āļ—āļĩāđˆāļˆāļģāđ€āļ›āđ‡āļ™:
    • apikey: API key āļ‚āļ­āļ‡āļ„āļļāļ“

āļ‚āđ‰āļ­āļāļģāļŦāļ™āļ”āļĢāļđāļ›āđāļšāļšāđ€āļŠāļĩāļĒāļ‡â€‹

  • āļ­āļąāļ•āļĢāļēāļāļēāļĢāļŠāļļāđˆāļĄāļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡: 16,000 Hz
  • āļŠāđˆāļ­āļ‡āļŠāļąāļāļāļēāļ“: āđ‚āļĄāđ‚āļ™
  • āļ„āļ§āļēāļĄāļĨāļķāļāļ‚āļ­āļ‡āļšāļīāļ•: 16 āļšāļīāļ•
  • āļāļēāļĢāđ€āļ‚āđ‰āļēāļĢāļŦāļąāļŠāđ€āļŠāļĩāļĒāļ‡: PCM

āļĢāļēāļ„āļē​

āļŠāļ·āđˆāļ­āļšāļĢāļīāļāļēāļĢ AI APIāļˆāļļāļ”āļŠāļīāđ‰āļ™āļŠāļļāļ”IC āļ•āđˆāļ­āļ§āļīāļ™āļēāļ—āļĩOn-Premise
āļĢāļ°āļšāļšāđāļ›āļĨāļ‡āđ€āļŠāļĩāļĒāļ‡āļžāļđāļ”āđ€āļ›āđ‡āļ™āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāļ āļēāļĐāļēāđ„āļ—āļĒ (ASR)iapp-asr-v3-en1 IC/30 āļ§āļīāļ™āļēāļ—āļĩāļ•āļīāļ”āļ•āđˆāļ­
iapp-asr-v3-th-en1 IC/30 āļ§āļīāļ™āļēāļ—āļĩ

āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āđ‚āļ„āđ‰āļ”​

Python (āļāļēāļĢāļŠāļ•āļĢāļĩāļĄāđ„āļĄāđ‚āļ„āļĢāđ‚āļŸāļ™)​

    import pyaudio
import websockets
import asyncio

async def stream_microphone():
url = "wss://api-uat.iapp.co.th/asr"
audio = pyaudio.PyAudio()
stream = audio.open(format=pyaudio.paInt16,
channels=1,
rate=16000,
input=True,
frames_per_buffer=1024)

async with websockets.connect(url, extra_headers={"apikey": "YOUR_API_KEY"}) as ws:
while True:
data = stream.read(1024)
await ws.send(data)
await asyncio.sleep(0.05)

Python (āļāļēāļĢāļŠāļ•āļĢāļĩāļĄāđ„āļŸāļĨāđŒ)​

    from websockets.client import WebSocketClientProtocol
import websockets
import asyncio
import json

async def send_audio_data(ws_client: WebSocketClientProtocol):
frame_size = 1024
with open("audio.pcm", "rb") as file:
while True:
buff = file.read(frame_size)
if buff:
await ws_client.send(buff)
else:
break
await asyncio.sleep(0.02)

async def client_test():
url = "wss://api-uat.iapp.co.th/asr"
async with websockets.connect(url, extra_headers={"apikey": "YOUR_API_KEY"}) as ws:
await send_audio_data(ws)

Javascript​

const WebSocket = require('ws'); // Ensure WebSocket is installed (npm install ws)
const fs = require('fs');

async function sendAudioData(ws) {
const frameSize = 1024; // Define the frame size for audio chunks
const fileStream = fs.createReadStream('audio.pcm', { highWaterMark: frameSize });

// Read and send audio data frame by frame
for await (const chunk of fileStream) {
if (chunk) {
ws.send(chunk); // Send the audio data
}
await new Promise(resolve => setTimeout(resolve, 20)); // Wait for 20 ms
}

// Close the WebSocket connection after sending all data
ws.close();
}

function clientTest() {
const url = "wss://api-iflytek.iapp.co.th/asr";
const apiKey = "YOUR_API_KEY";

// Connect to the WebSocket server
const ws = new WebSocket(url, {
headers: {
apikey: apiKey
}
});

ws.on('open', async () => {
console.log('WebSocket connection opened');
await sendAudioData(ws);
});

ws.on('message', (message) => {
console.log('Received:', message.toString());
});

ws.on('error', (error) => {
console.error('WebSocket error:', error);
});

ws.on('close', (code, reason) => {
console.log('WebSocket closed:', code, reason);
});
}

// Run the client
clientTest();

PHP​

<?php
$apiKey = "YOUR_API_KEY";
$url = "wss://api-iflytek.iapp.co.th/asr";

$ws = new WebSocket($url, ['headers' => ["apikey: $apiKey"]]);

function sendAudioData($ws) {
$frameSize = 1024; // Frame size in bytes
$file = fopen("audio.pcm", "rb");

while (!feof($file)) {
$data = fread($file, $frameSize);
$ws->send($data);
usleep(20000); // 20ms delay
}

fclose($file);
$ws->close();
}

$ws->on("open", function($ws) {
sendAudioData($ws);
});

$ws->on("message", function($message) {
echo "Received: $message\n";
});

$ws->on("error", function($error) {
echo "Error: $error\n";
});

$ws->on("close", function() {
echo "WebSocket closed\n";
});

Swift​

import Foundation

class WebSocketClient: NSObject, URLSessionWebSocketDelegate {
let apiKey = "YOUR_API_KEY"
let url = URL(string: "wss://api-iflytek.iapp.co.th/asr")!
var webSocket: URLSessionWebSocketTask?

func connect() {
let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
var request = URLRequest(url: url)
request.addValue(apiKey, forHTTPHeaderField: "apikey")

webSocket = session.webSocketTask(with: request)
webSocket?.resume()

sendAudioData()
}

func sendAudioData() {
guard let webSocket = webSocket else { return }
let fileURL = URL(fileURLWithPath: "audio.pcm")

guard let fileHandle = try? FileHandle(forReadingFrom: fileURL) else {
print("Could not open audio file.")
return
}

DispatchQueue.global().async {
while true {
let data = fileHandle.readData(ofLength: 1024)
if data.isEmpty { break }

let message = URLSessionWebSocketTask.Message.data(data)
webSocket.send(message) { error in
if let error = error {
print("Error sending data: \(error)")
return
}
}

Thread.sleep(forTimeInterval: 0.02)
}

fileHandle.closeFile()
webSocket.cancel()
}
}

func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
print("WebSocket closed")
}
}

let client = WebSocketClient()
client.connect()

Kotlin​

import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import okio.ByteString
import java.io.File
import kotlinx.coroutines.*

class WebSocketClient : WebSocketListener() {
private val apiKey = "YOUR_API_KEY"
private val url = "wss://api-iflytek.iapp.co.th/asr"

fun connect() {
val client = OkHttpClient()
val request = Request.Builder()
.url(url)
.addHeader("apikey", apiKey)
.build()

val webSocket = client.newWebSocket(request, this)

CoroutineScope(Dispatchers.IO).launch {
sendAudioData(webSocket)
}
}

private suspend fun sendAudioData(webSocket: WebSocket) {
val frameSize = 1024
val file = File("audio.pcm")
val byteArray = ByteArray(frameSize)

file.inputStream().use { inputStream ->
while (inputStream.read(byteArray) != -1) {
webSocket.send(ByteString.of(byteArray, 0, frameSize))
delay(20) // 20ms delay
}
}
webSocket.close(1000, "Finished sending data")
}

override fun onMessage(webSocket: WebSocket, text: String) {
println("Received: $text")
}

override fun onFailure(webSocket: WebSocket, t: Throwable, response: okhttp3.Response?) {
println("Error: ${t.message}")
}

override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
println("WebSocket closing: $code / $reason")
webSocket.close(code, reason)
}
}

fun main() {
val client = WebSocketClient()
client.connect()
}

Java​

import okhttp3.*;
import okio.ByteString;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class WebSocketClient {
private static final String URL = "wss://api-iflytek.iapp.co.th/asr";
private static final String API_KEY = "YOUR_API_KEY";

public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.addHeader("apikey", API_KEY)
.build();

WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
System.out.println("WebSocket opened");
new Thread(() -> sendAudioData(webSocket)).start();
}

@Override
public void onMessage(WebSocket webSocket, String text) {
System.out.println("Received: " + text);
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
System.out.println("Error: " + t.getMessage());
}

@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
System.out.println("WebSocket closing: " + code + " / " + reason);
webSocket.close(code, reason);
}
});
}

private static void sendAudioData(WebSocket webSocket) {
int frameSize = 1024;
File file = new File("audio.pcm");
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[frameSize];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
webSocket.send(ByteString.of(buffer, 0, bytesRead));
Thread.sleep(20); // 20ms delay
}
webSocket.close(1000, "Finished sending data");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Dart​

import 'dart:async';
import 'dart:convert';
import 'dart:io';

void main() async {
final url = "wss://api-iflytek.iapp.co.th/asr";
final apiKey = "YOUR_API_KEY";

final socket = await WebSocket.connect(url, headers: {'apikey': apiKey});
print('WebSocket connected');

sendAudioData(socket);
socket.listen(
(data) => print('Received: $data'),
onError: (error) => print('Error: $error'),
onDone: () => print('WebSocket closed'),
);
}

void sendAudioData(WebSocket socket) async {
final file = File('audio.pcm');
final frameSize = 1024;
final raf = file.openRead();

await for (final chunk in raf) {
socket.add(chunk);
await Future.delayed(Duration(milliseconds: 20)); // 20ms delay
}

socket.close();
}

āļ‚āđ‰āļ­āļˆāļģāļāļąāļ”āđāļĨāļ°āđāļ™āļ§āļ—āļēāļ‡āļ›āļāļīāļšāļąāļ•āļīāļ—āļĩāđˆāļ”āļĩāļ—āļĩāđˆāļŠāļļāļ”​

āļ‚āđ‰āļ­āļˆāļģāļāļąāļ”​

  • āļĢāļ­āļ‡āļĢāļąāļšāđ€āļ‰āļžāļēāļ°āļ āļēāļĐāļēāđ„āļ—āļĒ
  • āļ‚āđ‰āļ­āļāļģāļŦāļ™āļ”āļĢāļđāļ›āđāļšāļšāđ€āļŠāļĩāļĒāļ‡āļ—āļĩāđˆāđ€āļ‰āļžāļēāļ°āđ€āļˆāļēāļ°āļˆāļ‡
  • āļˆāļģāđ€āļ›āđ‡āļ™āļ•āđ‰āļ­āļ‡āđƒāļŠāđ‰āļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­ WebSocket
  • āļ‚āļķāđ‰āļ™āļ­āļĒāļđāđˆāļāļąāļšāđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ

āđāļ™āļ§āļ—āļēāļ‡āļ›āļāļīāļšāļąāļ•āļīāļ—āļĩāđˆāļ”āļĩāļ—āļĩāđˆāļŠāļļāļ”​

  • āļĢāļąāļāļĐāļēāļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­āđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒāļ—āļĩāđˆāđ€āļŠāļ–āļĩāļĒāļĢ
  • āđƒāļŠāđ‰āļ‚āļ™āļēāļ”āđ€āļŸāļĢāļĄāļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļĄ
  • āļˆāļąāļ”āļāļēāļĢāļ‚āđ‰āļ­āļœāļīāļ”āļžāļĨāļēāļ”āļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­āļ­āļĒāđˆāļēāļ‡āļ–āļđāļāļ•āđ‰āļ­āļ‡
  • āļ•āļĢāļ§āļˆāļŠāļ­āļšāļŠāļ–āļēāļ™āļ° WebSocket
  • āļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāļŠāļ–āļēāļ™āļ°āļāļēāļĢāļ•āļ­āļšāļŠāļ™āļ­āļ‡āļ­āļĒāđˆāļēāļ‡āļ–āļđāļāļ•āđ‰āļ­āļ‡

āļ„āļ§āļēāļĄāđāļĄāđˆāļ™āļĒāļģāđāļĨāļ°āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžâ€‹

āļ„āļ§āļēāļĄāđāļĄāđˆāļ™āļĒāļģāđ‚āļ”āļĒāļĢāļ§āļĄâ€‹

  • āļ„āļļāļ“āļ āļēāļžāļāļēāļĢāļ–āļ­āļ”āļ„āļ§āļēāļĄāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
  • āļāļēāļĢāļˆāļ”āļˆāļģāļ„āļģāļžāļđāļ”āļ­āļĒāđˆāļēāļ‡āļ•āđˆāļ­āđ€āļ™āļ·āđˆāļ­āļ‡
  • āļāļēāļĢāļ•āļīāļ”āļ•āļēāļĄāļ„āļ§āļēāļĄāđāļĄāđˆāļ™āļĒāļģāļ•āļēāļĄāļŠāļ–āļēāļ™āļ°

āļ„āļ§āļēāļĄāđ€āļĢāđ‡āļ§āđƒāļ™āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨ​

  • āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
  • āļāļēāļĢāļ•āļ­āļšāļŠāļ™āļ­āļ‡āļ—āļĩāđˆāļĄāļĩāđ€āļ§āļĨāļēāđāļāļ‡āļ•āđˆāļģ
  • āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāļ—āļĩāđˆāļ‚āļķāđ‰āļ™āļ­āļĒāļđāđˆāļāļąāļšāđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ

āļ›āļąāļˆāļˆāļąāļĒāļ—āļĩāđˆāļŠāđˆāļ‡āļœāļĨāļ•āđˆāļ­āļ„āļ§āļēāļĄāđāļĄāđˆāļ™āļĒāļģ​

  • āļ„āļļāļ“āļ āļēāļžāđ€āļŠāļĩāļĒāļ‡
  • āļ„āļ§āļēāļĄāđ€āļŠāļ–āļĩāļĒāļĢāļ‚āļ­āļ‡āđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ
  • āđ€āļŠāļĩāļĒāļ‡āļĢāļšāļāļ§āļ™āļˆāļēāļāļžāļ·āđ‰āļ™āļŦāļĨāļąāļ‡
  • āļ„āļ§āļēāļĄāļŠāļąāļ”āđ€āļˆāļ™āđƒāļ™āļāļēāļĢāļžāļđāļ”
  • āļ„āļļāļ“āļ āļēāļžāļ‚āļ­āļ‡āđ„āļĄāđ‚āļ„āļĢāđ‚āļŸāļ™

āļ›āļĢāļ°āļ§āļąāļ•āļī​

āđ€āļ§āļ­āļĢāđŒāļŠāļąāļ™ 1.0 (2023)​

  • āļāļēāļĢāđ€āļ›āļīāļ”āļ•āļąāļ§āļ„āļĢāļąāđ‰āļ‡āđāļĢāļ
  • āļĢāļ­āļ‡āļĢāļąāļšāļāļēāļĢāļŠāļ•āļĢāļĩāļĄ WebSocket
  • āļ„āļ§āļēāļĄāļŠāļēāļĄāļēāļĢāļ–āđƒāļ™āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāđāļšāļšāđ€āļĢāļĩāļĒāļĨāđ„āļ—āļĄāđŒ
  • āļĢāļ­āļ‡āļĢāļąāļšāļ­āļīāļ™āļžāļļāļ•āļˆāļēāļāđ„āļŸāļĨāđŒāđāļĨāļ°āđ„āļĄāđ‚āļ„āļĢāđ‚āļŸāļ™
  • āļĢāļ°āļšāļšāļāļēāļĢāļ•āļ­āļšāļŠāļ™āļ­āļ‡āļ•āļēāļĄāļŠāļ–āļēāļ™āļ°