C# SDK

更新时间:
复制 MD 格式

This topic describes how to use the C# software development kit (SDK) for Alibaba Cloud Voice Service, including installation instructions and code examples.

Download the SDK

Note
  • Current version: 3.1.17. This version is based on C++ SDK API 3.1.x. Release date: August 28, 2023.

  • This SDK is a C# wrapper for the underlying C++ code and supports only the Windows platform.

  • Before you use the SDK, read the API reference. For more information, see API reference.

You can obtain the SDK using one of the following methods.

  • Method 1: Obtain the latest source code from GitHub. For detailed instructions on how to compile and run the code, see the following sections or the readme.md file included in the source code.

    git clone --depth 1 https://github.com/aliyun/alibabacloud-nls-cpp-sdk
  • Method 2: Download the required SDK package from the table below. The SDK source code package contains the original SDK code, which you must compile to generate the required library files. The other SDK packages are platform-specific, contain the relevant library and header files, and do not require compilation.

    Latest SDK package

    Platform

    MD5

    alibabacloud-nls-cpp-sdk3.1.17-master_fd7c7d8.zip

    SDK source code

    8beeaad832d4b249464f4338429c3b15

    NlsCsharpSdk_Windows_3.1.17_fd7c7d8.zip

    Windows

    81fdd1579e103d8c93b4dab98ee0f71c

    Where:

    • alibabacloud-nls-cpp-sdk-master_<github commit id>.zip is the SDK source code package.

    • NlsCsharpSdk_Windows_<version number>_<github commit id>.zip is the SDK package required for development on the Windows platform. For more information, see the readme.md file in the package.

Compile and run C# on the Windows platform

To integrate the SDK, use the pre-compiled library NlsCsharpSdk_Windows_<version>_<github commit id>.zip. If you want to compile the code yourself, download and decompress alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip, or obtain the latest code from GitHub. Then, follow the compilation steps in the readme.md file.

Key interfaces

using nlsCsharpSdk;
  • Basic interfaces

    • NlsClient: A voice processing client that you can use to perform voice processing tasks such as short sentence recognition, real-time speech recognition, and speech synthesis. This client is thread-safe. We recommend that you create only one global instance.

      Interface

      Enable Versioning

      Description

      SetLogConfig

      3.1.9

      Sets the log file and storage path. Call this interface as early as possible to record more detailed information.

      GetVersion

      3.1.9

      Sets the log file and storage path. Call this interface as early as possible to record more detailed information.

      CreateNlsToken

      3.1.9

      Sets the log file and storage path. Call this interface as early as possible to record more detailed information.

      ReleaseNlsToken

      3.1.9

      Sets the log file and storage path. Call this interface as early as possible to record more detailed information.

      SetDirectHost

      3.1.16

      Skips domain name resolution and directly sets the server IP address. If you call this interface, call it before StartWorkThread.

      StartWorkThread

      3.1.9

      Starts worker threads. The default value is 1, which starts one thread. If you set this parameter to -1, the number of started threads is the same as the number of CPU cores. For high-concurrency scenarios, set this parameter to -1. This interface also initializes the NlsClient.

      ReleaseInstance

      3.1.9

      Destroys the NlsClient object instance and releases the NLS SDK. Call this operation after you destroy all requests.

      CreateNlsToken

      3.1.9

      Creates a token object to request a TokenId. For more information, see the NlsToken section below.

      ReleaseNlsToken

      3.1.9

      Destroys the token object.

      CreateTranscriberRequest

      3.1.9

      Creates a real-time speech recognition object. This object is thread-safe and supports high-concurrency requests.

      ReleaseTranscriberRequest

      3.1.9

      Destroys the real-time speech recognition object. Call this interface after the closed event of the current request occurs.

    • NlsToken: Creates a token object to request a TokenId. To request a new token, you must first obtain a valid timestamp. If a token expires, you must request a new one. Requesting a new token multiple times within the validity period of an existing token invalidates the TokenId.

      Interface

      Description

      SetAccessKeyId

      Sets the AccessKey ID of your Alibaba Cloud account.

      SetKeySecret

      Sets the AccessKey secret of your Alibaba Cloud account.

      ApplyNlsToken

      Requests a TokenId. This TokenId is valid for all voice requests under the AccessKey ID of the Alibaba Cloud account within the validity period. You do not need to request a new TokenId for each voice request.

      GetToken

      Obtains the TokenId.

      GetExpireTime

      Obtains the UNIX timestamp (in seconds) when the token expires.

      GetErrorMsg

      Obtains the error message if the request for a TokenId fails.

    • NlsEvent: The NLS_EVENT_STRUCT event object returned by CallbackDelegate. You can retrieve the request status code, the result returned from the cloud, and failure information from this object.

      Parameter name

      Description

      statusCode

      Obtains the status code. A value of 0 or 20000000 indicates success. Otherwise, an error code is returned.

      taskId

      Obtains the TaskId of the task.

      msg

      Obtains the response result returned from the cloud. This is used to get event information, such as information for Started, Closed, TaskFailed, SentenceBegin, and SentenceEnd callbacks.

      result

      Obtains the recognition result returned from the cloud. This is used to get the recognition result, such as information for ResultChanged and SentenceEnd callbacks.

  • Recognition interfaces

    SpeechTranscriberRequest: A request object for the real-time recognition of long-form audio.

    Interface

    Description

    SetOnTaskFailed

    Sets the error callback function.

    SetOnTranscriptionStarted

    Sets the callback function for the start of real-time audio stream recognition.

    SetOnSentenceBegin

    Sets the callback for the start of a sentence.

    SetOnSentenceEnd

    Sets the callback function for the end of a sentence.

    SetOnTranscriptionResultChanged

    Sets the callback function for intermediate results of real-time audio stream recognition.

    SetOnTranscriptionCompleted

    Sets the callback function for when the server-side service ends.

    SetOnChannelClosed

    Sets the callback function for when the channel is closed.

    SetAppKey

    Sets the AppKey.

    SetToken

    Authenticates using a security token. All requests must be authenticated by the SetToken method before they can be used.

    SetUrl

    Sets the service URL. If not set, the service in the public cloud in Shanghai is called by default.

    SetIntermediateResult

    Sets whether to return intermediate recognition results. The results are returned from the onTranscriptionResultChanged callback.

    SetPunctuationPrediction

    Sets whether to add punctuation in post-processing.

    SetInverseTextNormalization

    Sets whether to perform number conversion in post-processing.

    SetFormat

    Sets the audio data encoding format. For Windows environments, the PCM format is recommended.

    SetSampleRate

    Sets the audio sampling rate.

    SetSemanticSentenceDetection

    Sets whether to use semantic sentence detection.

    SetMaxSentenceSilence

    Sets the VAD threshold. This is mutually exclusive with semantic sentence detection and cannot be used at the same time. Before calling this setting, set SetSemanticSentenceDetection to false.

    SetCustomizationId

    Sets a custom model.

    SetVocabularyId

    Sets a hotword vocabulary, for example, ("TestId_456").

    SetTimeout

    Sets the socket reception timeout period.

    SetEnableNlp

    Sets whether to enable the NLP service.

    SetNlpModel

    Sets the NLP model name. This is required after enabling the NLP service.

    SetSessionId

    Sets the Session ID.

    SetOutputFormat

    Sets the encoding format of the output text. The default for the Windows platform is GBK. For non-Chinese languages, set this to UTF-8 to prevent garbled characters.

    SetPayloadParam

    Sets parameters. The input parameter is a JSON-formatted string. For example, to specify an acoustic model: "{\"model\":\"test-regression-model\"}").

    SetContextParam

    Sets user-defined parameters. The input parameter is a JSON-formatted string.

    AppendHttpHeaderParam

    Sets user-defined WebSocket HTTP header parameters.

    Start

    Asynchronous interface. Starts SpeechTranscriberRequest. You must wait for the OnTranscriptionStarted callback to ensure the request is in a working state.

    Stop

    Asynchronous interface. Confirms shutdown with the server and stops the connection normally. You must wait for the OnChannelClosed callback to ensure the request has finished its work.

    Cancel

    Does not confirm shutdown with the server. Directly closes the real-time audio stream recognition process.

    Control

    Requests the server to update recognition parameters.

    SendAudio

    Asynchronous interface. Sends voice data. To ensure real-time performance, do not send excessively long data segments. Send audio data of less than 100 ms at a time, in the range of 640 bytes to 16384 bytes.

SDK error codes

Status code

Status message

Cause

Solution

0

Success

Success

-10

DefaultError

Default error

Not in use.

-11

JsonParseFailed

Invalid JSON format

Check whether the input JSON string is in the valid JSON format.

-12

JsonObjectError

Invalid JSON object

Retry the operation.

-13

MallocFailed

Malloc failed

Check whether the memory is sufficient.

-14

ReallocFailed

Realloc failed

Check whether the memory is sufficient.

-15

InvalidInputParam

Invalid input parameter

Not in use.

-50

InvalidLogLevel

Invalid log level

Check the configured log level.

-51

InvalidLogFileSize

Invalid log file size

Check the configured log file size parameter.

-52

InvalidLogFileNum

Invalid number of log files

Check the configured number of log files parameter.

-100

EncoderExistent

The NLS encoder already exists.

Retry the operation.

-101

EncoderInexistent

The NLS encoder does not exist.

We recommend re-initializing.

-102

OpusEncoderCreateFailed

Failed to create the Opus encoder.

You need to reinitialize.

-103

OggOpusEncoderCreateFailed

Failed to create the OggOpus encoder.

We recommend reinitializing.

-150

EventClientEmpty

The main worker thread has a null pointer and has been released.

Reinitialize the thread by calling startWorkThread().

-151

SelectThreadFailed

Failed to select a worker thread. The thread is not initialized.

Reinitialize the thread by calling startWorkThread().

-160

StartCommandFailed

Failed to send the start command.

Retry the operation.

-161

InvokeStartFailed

The request state machine is incorrect, which causes the start operation to fail.

Check whether the current request has not been created or has been completed.

-162

InvokeSendAudioFailed

The request state machine is incorrect, which causes the sendAudio operation to fail.

Check whether the current request has started (the started event callback has been received) or has been completed.

-163

InvalidOpusFrameSize

Invalid Opus frame size. The default is 640 bytes.

In OPU encoding mode, sendAudio accepts only 640 bytes of data per frame.

-164

InvokeStopFailed

The request state machine is incorrect, which causes the stop operation to fail.

Check whether the current request has not started (the started event callback has not been received) or has been completed.

-165

InvokeCancelFailed

The request state machine is incorrect, which causes the stop operation to fail.

Check whether the current request has not started (the started event callback has not been received) or has been completed.

-166

InvokeStControlFailed

The request state machine is incorrect, which causes the stControl operation to fail.

Check whether the current request has not started (the started event callback has not been received) or has been completed.

-200

NlsEventEmpty

The NLS event is empty.

For internal SDK use. The NlsEvent frame is lost.

-201

NewNlsEventFailed

Failed to create an NlsEvent.

For internal SDK use. Failed to create the NlsEvent frame.

-202

NlsEventMsgEmpty

The message in the NLS event is empty.

The message string was found to be empty during parsing by parseJsonMsg().

-203

InvalidNlsEventMsgType

Invalid message type in the NLS event.

For internal SDK use. The event type of the NlsEvent frame is invalid.

-204

InvalidNlsEventMsgStatusCode

Invalid message status code in the NLS event.

For internal SDK use. The event message status of the NlsEvent frame is invalid.

-205

InvalidNlsEventMsgHeader

Invalid message header in the NLS event.

For internal SDK use. The event message header of the NlsEvent frame is invalid.

-250

CancelledExitStatus

Cancel has been called.

Not in use.

-251

InvalidWorkStatus

Invalid working status

For internal SDK use. The internal state of the current request is invalid.

-252

InvalidNodeQueue

The NodeQueue in workThread is invalid.

For internal SDK use. The current request to be run is invalid. Release the current request and try again.

-300

InvalidRequestParams

Invalid request parameters

The data passed to sendAudio is empty.

-301

RequestEmpty

The request is a null pointer.

For internal SDK use. The current request has been released. Release the current request and try again.

-302

InvalidRequest

Invalid request

For internal SDK use. The current request has been released. Release the current request and try again.

-303

SetParamsEmpty

The input parameter is empty.

Check whether the input parameter is empty.

-350

GetHttpHeaderFailed

Failed to get the HTTP header.

For internal SDK use. Locate the issue based on the feedback in the logs.

-351

HttpGotBadStatus

HTTP error status

For internal SDK use. Locate the issue based on the feedback in the logs.

-352

WsResponsePackageFailed

Failed to parse the WebSocket response package.

For internal SDK use. Locate the issue based on the feedback in the logs.

-353

WsResponsePackageEmpty

The parsed WebSocket response package is empty.

For internal SDK use. Locate the issue based on the feedback in the logs.

-354

WsRequestPackageEmpty

The WebSocket request package is empty.

For internal SDK use. Locate the issue based on the feedback in the logs.

-355

UnknownWsFrameHeadType

Unknown WebSocket frame header type

For internal SDK use. Locate the issue based on the feedback in the logs.

-356

InvalidWsFrameHeaderSize

Invalid WebSocket frame header size

For internal SDK use. Locate the issue based on the feedback in the logs.

-357

InvalidWsFrameHeaderBody

Invalid WebSocket frame header body

For internal SDK use. Locate the issue based on the feedback in the logs.

-358

InvalidWsFrameBody

Invalid WebSocket frame body

For internal SDK use. Locate the issue based on the feedback in the logs.

-359

WsFrameBodyEmpty

The frame data is empty. This is often caused by receiving dirty data.

For internal SDK use. Locate the issue based on the feedback in the logs.

-400

NodeEmpty

The node is a null pointer.

Release the current request and try again.

-401

InvaildNodeStatus

The node is in an invalid state.

For internal SDK use. Release the current request and try again.

-402

GetAddrinfoFailed

Address detection using DNS parsing

For internal SDK use. Check whether DNS is available in the current environment.

-403

ConnectFailed

Connection failed.

Check whether your network is available.

-404

InvalidDnsSource

No DNS on the current device.

For internal SDK use. Check whether DNS is available in the current environment.

-405

ParseUrlFailed

Invalid URL

Check whether the configured URL is valid.

-406

SslHandshakeFailed

SSL handshake failed.

For internal SDK use. Check whether the network is available and try again.

-407

SslCtxEmpty

SSL_CTX is empty.

For internal SDK use. Check whether the network is available and try again.

-408

SslNewFailed

SSL_new failed.

For internal SDK use. Check whether the network is available and try again.

-409

SslSetFailed

Failed to set SSL parameters.

For internal SDK use. Check whether the network is available and try again.

-410

SslConnectFailed

SSL_connect failed.

For internal SDK use. Check whether the network is available and try again.

-411

SslWriteFailed

Failed to send data over SSL.

For internal SDK use. Check whether the network is available and try again.

-412

SslReadSysError

A SYSCALL error occurred while receiving data over SSL.

For internal SDK use. Check whether the network is available and try again.

-413

SslReadFailed

Failed to receive data over SSL.

For internal SDK use. Check whether the network is available and try again.

-414

SocketFailed

Failed to create a socket.

For internal SDK use. Check whether the network is available and try again.

-415

SetSocketoptFailed

Failed to set socket parameters.

For internal SDK use. Check whether the network is available and try again.

-416

SocketConnectFailed

Failed to establish a socket connection.

For internal SDK use. Check whether the network is available and try again.

-417

SocketWriteFailed

Failed to send data over the socket.

For internal SDK use. Check whether the network is available and try again.

-418

SocketReadFailed

Failed to receive data from the socket.

For internal SDK use. Check whether the network is available and try again.

-430

NlsReceiveFailed

Failed to receive NLS frame data.

For internal SDK use. Check whether the network is available and try again.

-431

NlsReceiveEmpty

Received NLS frame data is empty.

For internal SDK use. Check whether the network is available and try again.

-432

ReadFailed

Failed to receive data.

For internal SDK use. Check whether the network is available and try again.

-433

NlsSendFailed

Failed to send NLS data.

For internal SDK use. Check whether the network is available and try again.

-434

NewOutputBufferFailed

Failed to create a buffer.

For internal SDK use. Check whether the memory is sufficient.

-435

NlsEncodingFailed

Audio encoding failed.

For internal SDK use. Release the current request and try again.

-436

EventEmpty

The event is empty.

For internal SDK use. Release the current request and try again.

-437

EvbufferTooMuch

Too much data in evbuffer.

For internal SDK use. The send data cache is full (max cache for 16K audio is 320000, for 8K audio is 160000). Check if audio data is being sent too frequently or if too much data is sent at once.

-438

EvutilSocketFailed

Failed to set evutil parameters.

For internal SDK use. Release the current request and try again.

-439

InvalidExitStatus

Invalid exit status

Check whether the current request has been canceled.

-450

InvalidAkId

Invalid AccessKey ID for the Alibaba Cloud account.

Check whether the AccessKey ID of your Alibaba Cloud account is empty.

-451

InvalidAkSecret

Invalid AccessKey secret for the Alibaba Cloud account.

Check whether the AccessKey secret of your Alibaba Cloud account is empty.

-452

InvalidAppKey

Invalid project AppKey.

Check whether the AppKey of your Alibaba Cloud project is empty.

-453

InvalidDomain

Invalid domain

Check whether the input domain is empty.

-454

InvalidAction

Invalid action

Check whether the input action is empty.

-455

InvalidServerVersion

Invalid ServerVersion

Check whether the input ServerVersion is empty.

-456

InvalidServerResource

Invalid ServerResource

Check whether the input ServerResource is empty.

-457

InvalidRegionId

Invalid RegionId

Check whether the input RegionId is empty.

-500

InvalidFileLink

Invalid audio file link

The audio file transcription link is empty.

-501

ErrorStatusCode

Error status code

An error is returned for audio file transcription. See the error code for details.

-502

IconvOpenFailed

Failed to transform the description.

UTF-8 to GBK conversion failed.

-503

IconvFailed

Encoding conversion failed.

UTF-8 to GBK conversion failed.

-504

ClientRequestFaild

Account client request failed.

Audio file transcription request failed.

-999

NlsMaxErrorCode

Other status codes

Status message

Cause

Solution

10000001

NewSslCtxFailed

SSL: couldn't create a context!

We recommend re-initializing.

10000002

DefaultErrorCode

return of SSL_read: error:00000000:lib(0):func(0):reason(0)

Retry the operation.

return of SSL_read: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init

10000003

SysErrorCode

System error.

Handle the error based on the system feedback.

10000004

EmptyUrl

URL: The url is empty.

The input URL is empty. Enter a valid URL.

10000005

InvalidWsUrl

Could not parse WebSocket url:

The input URL format is invalid. Enter a valid URL.

10000007

JsonStringParseFailed

JSON: Json parse failed.

Invalid JSON format. Check the logs for the specific error point.

10000008

UnknownWsHeadType

WEBSOCKET: unkown head type.

Connection failed. Check your local DNS resolution and whether the URL is valid.

10000009

HttpConnectFailed

HTTP: connect failed.

Failed to connect to the cloud. Check your network and try again.

10000010

MemNotEnough

Out of memory.

Check whether the memory is sufficient.

10000015

SysConnectFailed

connect failed.

Connection failed. Check your local DNS resolution and whether the URL is valid.

10000100

HttpGotBadStatusWith403

Got bad status host=xxxxx line=HTTP/1.1 403 Forbidden

The connection was rejected. Check your account and whether the token has expired.

10000101

EvSendTimeout

Send timeout. socket error:

libevent timed out while sending an event. Check for time-consuming tasks in the callback or high concurrency that prevents timely event processing.

10000102

EvRecvTimeout

Recv timeout. socket error:

libevent timed out while receiving an event. Check for time-consuming tasks in the callback or high concurrency that prevents timely event processing.

10000103

EvUnknownEvent

Unknown event:

Unknown libevent event. Retry the operation.

10000104

OpNowInProgress

Operation now in progress

The connection is in progress. Retry the operation.

10000105

BrokenPipe

Broken pipe

The pipe cannot handle the request. Retry the operation.

10000110

TokenHasExpired

Gateway:ACCESS_DENIED:The token 'xxx' has expired!

Update the token.

10000111

TokenIsInvalid

Meta:ACCESS_DENIED:The token 'xxx' is invalid!

Check the validity of the token.

10000112

NoPrivilegeToVoice

Gateway:ACCESS_DENIED:No privilege to this voice! (voice: zhinan, privilege: 0)

You do not have permission to use this speaker.

10000113

MissAuthHeader

Gateway:ACCESS_DENIED:Missing authorization header!

Check whether your account has the required permissions or if the concurrency is within the limit.

10000120

Utf8ConvertError

utf8ToGbk failed

UTF-8 transcoding failed. This is often a system issue. Retry the operation.

20000000

SuccessStatusCode

Success

Server response status codes

For information about service status codes, see Service status codes.

Code examples

  • The audio file used in the example has a sampling rate of 16000 Hz, and the model set in the console is the Universal model. If you use other audio files, you must set the model to one that supports the corresponding audio scenario. For more information about model settings, see Manage projects.

  • The example uses the default public endpoint for the real-time speech recognition service that is built into the SDK. If you are using an Alibaba Cloud ECS instance in Shanghai and need to use an internal endpoint, you must set the internal endpoint URL in the SpeechTranscriberRequest object that you create.

    SpeechTranscriberRequest stPtr;
    stPtr.SetUrl(stPtr, "ws://nls-gateway.cn-shanghai-internal.aliyuncs.com/ws/v1")
  • The following code provides a brief example. For the complete code example, see the nlsCsharpSdkDemo.cs file in the demo directory of the SDK package.

    using System;
    using System.IO;
    using System.Threading;
    using System.Windows.Forms;
    using nlsCsharpSdk;
    
    namespace nlsCsharpSdkDemo
    {
        public partial class nlsCsharpSdkDemo : Form
     {
            private NlsClient nlsClient;
            private SpeechTranscriberRequest stPtr;
            private NlsToken tokenPtr;
            private UInt64 expireTime;
    
            private string appKey;
            private string akId;
            private string akSecret;
            private string token;
            private string url;
    
            static bool running;
    
            static bool st_send_audio_flag = false;
            static bool st_audio_loop_flag = false;
            static Thread st_send_audio;
            static string cur_st_result;
            static string cur_st_completed;
            static string cur_st_closed;
    
            private void FlushLab()
            {
                while (running)
                {
                    if (cur_st_result != null && cur_st_result.Length > 0)
                    {
                        stResult.Text = cur_st_result;
                    }
                    if (cur_st_completed != null && cur_st_completed.Length > 0)
                    {
                        stCompleted.Text = cur_st_completed;
                    }
                    if (cur_st_closed != null && cur_st_closed.Length > 0)
                    {
                        stClosed.Text = cur_st_closed;
                    }
    
                    Thread.Sleep(200);
                }
            }
    
            /// <summary>
            /// Audio push thread for real-time recognition.
            /// </summary>
            private void STAudioLab()
            {
                string file_name = System.Environment.CurrentDirectory + @"\audio_files\test3.wav";
                System.Diagnostics.Debug.WriteLine("st audio file_name = {0}", file_name);
                FileStream fs = new FileStream(file_name, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(fs);
    
                while (st_audio_loop_flag)
                {
                    if (st_send_audio_flag)
                    {
                        byte[] byData = br.ReadBytes((int)3200);
                        if (byData.Length > 0)
                        {
                            // Push the audio data in PCM format, with a length of byData.Length bytes.
                            stPtr.SendAudio(stPtr, byData, (UInt64)byData.Length, EncoderType.ENCODER_PCM);
                        }
                        else
                        {
                            /*
                             * After the audio push is complete, reopen the loop to continue.
                             */
                            br.Close();
                            fs.Dispose();
                            fs = new FileStream(file_name, FileMode.Open, FileAccess.Read);
                            br = new BinaryReader(fs);
                        }
                    }
                    /*
                     * Pushing 3200 bytes of audio data simulates 100 ms of audio.
                     * In a real environment where audio data is obtained from a recording, you do not need to call this Sleep.
                     */
                    Thread.Sleep(100);
                }
                br.Close();
                fs.Dispose();
            }
    
            public nlsCsharpSdkDemo()
            {
                InitializeComponent();
                System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
    
                nlsClient = new NlsClient();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                // Enable the logging system. Store logs named nlsLog.log at the LogDebug level. The logs are stored in 10 rotating files, with each file up to 400 MB in size.
                int ret = nlsClient.SetLogConfig("nlsLog", LogLevel.LogDebug, 400, 10);
                if (ret == 0)
                    nlsResult.Text = "OpenLog Success";
                else
                    nlsResult.Text = "OpenLog Failed";
            }
    
            private void button1_Click_1(object sender, EventArgs e)
            {
                // Get the current version number of the SDK.
                string version = nlsClient.GetVersion();
                nlsResult.Text = version;
            }
    
            private void button1_Click_2(object sender, EventArgs e)
            {            
                // A value of -1 indicates that the number of event pools to start is equal to the number of CPU cores. These pools are used for internal event processing.
                // For single-channel calls, set the parameter to 1 to start a single event pool.
                // For high-concurrency scenarios (hundreds of channels), set the parameter to a value from 4 to the number of CPU cores. A larger value reduces processing latency but increases CPU usage.
                nlsClient.StartWorkThread(1);
                nlsResult.Text = "StartWorkThread and init NLS success.";
                running = true;
                Thread t = new Thread(FlushLab);
                t.Start();
            }
    
            private void button1_Click_3(object sender, EventArgs e)
            {
                // Release the NlsClient. This is the reverse operation of StartWorkThread.
                nlsClient.ReleaseInstance();
                nlsResult.Text = "Release NLS success.";
            }
    
            #region Info
            private void textBox1_TextChanged(object sender, EventArgs e)
            {
                akId = tAkId.Text;
            }
    
            private void tAppKey_TextChanged(object sender, EventArgs e)
            {
                appKey = tAppKey.Text;
            }
    
            private void tAkSecret_TextChanged(object sender, EventArgs e)
            {
                akSecret = tAkSecret.Text;
            }
    
            private void tToken_TextChanged(object sender, EventArgs e)
            {
                token = tToken.Text;
            }
    
            private void tUrl_TextChanged(object sender, EventArgs e)
            {
                url = tUrl.Text;
            }
            #endregion
    
            #region TokenButton
            // create token
            private void button3_Click_1(object sender, EventArgs e)
            {
                int ret = 0;
                tokenPtr = nlsClient.CreateNlsToken();
                if (tokenPtr.native_token != IntPtr.Zero)
                {
                    if (akId != null && akSecret != null & akId.Length > 0 && akSecret.Length > 0)
                    {
                        tokenPtr.SetAccessKeyId(tokenPtr, akId);
                        tokenPtr.SetKeySecret(tokenPtr, akSecret);
    
                        ret = tokenPtr.ApplyNlsToken(tokenPtr);
                        if (ret < 0)
                        {
                            System.Diagnostics.Debug.WriteLine("ApplyNlsToken failed");
                            nlsResult.Text = tokenPtr.GetErrorMsg(tokenPtr);
                        }
                        else
                        {
                            System.Diagnostics.Debug.WriteLine("ApplyNlsToken success");
                            token = tokenPtr.GetToken(tokenPtr);
                            tToken.Text = token;
                            expireTime = tokenPtr.GetExpireTime(tokenPtr);
                            nlsResult.Text = "ExpireTime:" + expireTime.ToString();
                        }
                    }
                    else
                    {
                        nlsResult.Text = "CreateToken Failed, akId or Secret is null";
                    }
                }
                else
                {
                    nlsResult.Text = "CreateToken Failed";
                }
            }
    
            // release token
            private void button4_Click(object sender, EventArgs e)
            {
                if (tokenPtr.native_token != IntPtr.Zero)
                {
                    nlsClient.ReleaseNlsToken(tokenPtr);
                    tokenPtr.native_token = IntPtr.Zero;
                    nlsResult.Text = "ReleaseNlsToken Success";
                }
                else
                {
                    nlsResult.Text = "ReleaseNlsToken is nullptr";
                }
            }
            #endregion
    
            #region TranscriberCallback
            private CallbackDelegate DemoOnTranscriptionStarted =
                (ref NLS_EVENT_STRUCT e, ref string uuid) =>
            {
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionStarted user uuid = {0}", uuid);
                string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0');
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionStarted msg = {0}", msg);
                cur_st_completed = "msg : " + msg;
    
                st_send_audio_flag = true;
            };
            private CallbackDelegate DemoOnTranscriptionClosed =
                (ref NLS_EVENT_STRUCT e, ref string uuid) =>
            {
                string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0');
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionClosed = {0}", msg);
                cur_st_closed = "msg : " + msg;
            };
            private CallbackDelegate DemoOnTranscriptionTaskFailed =
                (ref NLS_EVENT_STRUCT e, ref string uuid) =>
            {
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionStarted user uuid = {0}", uuid);
                string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0');
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionTaskFailed = {0}", msg);
                cur_st_completed = "msg : " + msg;
                st_send_audio_flag = false;
                st_audio_loop_flag = false;
            };
            private CallbackDelegate DemoOnTranscriptionResultChanged =
                (ref NLS_EVENT_STRUCT e, ref string uuid) =>
            {
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionStarted user uuid = {0}", uuid);
                // If you are recognizing a non-Chinese language, set the format to UTF-8 and decode using UTF-8 to prevent garbled text.
                // string result = System.Text.Encoding.UTF8.GetString(e.result).TrimEnd('\0');
                string result = System.Text.Encoding.Default.GetString(e.result).TrimEnd('\0');
                System.Diagnostics.Debug.WriteLine("DemoOnTranscriptionResultChanged = {0}", result);
                cur_st_result = "middle result : " + result;
            };
            private CallbackDelegate DemoOnSentenceBegin =
                (ref NLS_EVENT_STRUCT e, ref string uuid) =>
            {
                System.Diagnostics.Debug.WriteLine("DemoOnSentenceBegin user uuid = {0}", uuid);
                // If you are recognizing a non-Chinese language, set the format to UTF-8 and decode using UTF-8 to prevent garbled text.
                // string msg = System.Text.Encoding.UTF8.GetString(e.msg).TrimEnd('\0');
                string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0');
                System.Diagnostics.Debug.WriteLine("DemoOnSentenceBegin msg = {0}", msg);
                cur_st_completed = "sentenceBegin : " + msg;
            };
            private CallbackDelegate DemoOnSentenceEnd =
                (ref NLS_EVENT_STRUCT e, ref string uuid) =>
            {
                System.Diagnostics.Debug.WriteLine("DemoOnSentenceEnd user uuid = {0}", uuid);
                // If you are recognizing a non-Chinese language, set the format to UTF-8 and decode using UTF-8 to prevent garbled text.
                // string msg = System.Text.Encoding.UTF8.GetString(e.msg).TrimEnd('\0');
                string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0');
                System.Diagnostics.Debug.WriteLine("DemoOnSentenceEnd msg = {0}", msg);
                cur_st_completed = "sentenceEnd : " + msg;
            };
            #endregion
    
            // create transcriber
            private void button1_Click_4(object sender, EventArgs e)
            {
                stPtr = nlsClient.CreateTranscriberRequest();
                if (stPtr.native_request != IntPtr.Zero)
                {
                    nlsResult.Text = "CreateTranscriberRequest Success";
                }
                else
                {
                    nlsResult.Text = "CreateTranscriberRequest Failed";
                }
                cur_st_result = "null";
                cur_st_closed = "null";
                cur_st_completed = "null";
            }
    
            // start transcriber
            private void button3_Click(object sender, EventArgs e)
            {
                int ret = -1;
                if (stPtr.native_request != IntPtr.Zero)
                {
                    stPtr.SetAppKey(stPtr, appKey);
                    stPtr.SetToken(stPtr, token);
                    stPtr.SetUrl(stPtr, url);
                    stPtr.SetFormat(stPtr, "pcm");
                    stPtr.SetSampleRate(stPtr, 16000);
                    stPtr.SetIntermediateResult(stPtr, true);
                    stPtr.SetPunctuationPrediction(stPtr, true);
                    stPtr.SetInverseTextNormalization(stPtr, true);
    
                    string uuid = System.Guid.NewGuid().ToString("N");
    
                    stPtr.SetOnTranscriptionStarted(stPtr, DemoOnTranscriptionStarted, uuid);
                    stPtr.SetOnChannelClosed(stPtr, DemoOnTranscriptionClosed, uuid);
                    stPtr.SetOnTaskFailed(stPtr, DemoOnTranscriptionTaskFailed, uuid);
                    stPtr.SetOnSentenceEnd(stPtr, DemoOnSentenceEnd, uuid);
                    stPtr.SetOnTranscriptionResultChanged(stPtr, DemoOnTranscriptionResultChanged, uuid);
    
                    ret = stPtr.Start(stPtr);
    
                    if (st_audio_loop_flag == false)
                    {
                        st_audio_loop_flag = true;
                        st_send_audio = new Thread(STAudioLab);
                        st_send_audio.Start();
                    }
                }
    
                if (ret != 0)
                {
                    nlsResult.Text = "Transcriber Start failed";
                }
                else
                {
                    nlsResult.Text = "Transcriber Start success";
                }
            }
    
         	// stop transcriber
            private void btnSTstop_Click(object sender, EventArgs e)
            {
                int ret = -1;
                if (stPtr.native_request != IntPtr.Zero)
                    ret = stPtr.Stop(stPtr);
    
                st_send_audio_flag = false;
                st_audio_loop_flag = false;
                if (ret != 0)
                {
                    nlsResult.Text = "Transcriber Stop failed";
                }
                else
                {
                    nlsResult.Text = "Transcriber Stop success";
                }
            }
    
         	// release transcriber
            private void button2_Click(object sender, EventArgs e)
            {
                if (stPtr.native_request != IntPtr.Zero)
                {
                    nlsClient.ReleaseTranscriberRequest(stPtr);
                    stPtr.native_request = IntPtr.Zero;
                    nlsResult.Text = "ReleaseTranscriberRequest Success";
                }
                else
                {
                    nlsResult.Text = "TranscriberRequest is nullptr";
                }
                cur_st_result = "null";
                cur_st_closed = "null";
                cur_st_completed = "null";
            }
    	}
    }