Skip to main content

tingwu-sdk-java-realtime

This topic describes the real-time interfaces of the Tingwu Java software development kit (SDK) and helps developers quickly call the real-time services of Tingwu.

Prerequisites

Activate the service and obtain and configure an API key. To prevent security risks from code leaks, configure the API key as an environment variable instead of hard coding it in your code.
To grant temporary access permissions to third-party applications or users, or want to strictly control risky operations such as accessing or deleting sensitive data, you can use a temporary authentication token.Compared to a long-term API key, a temporary authentication token is valid for only a short period (60 seconds) and offers higher security. It is suitable for temporary call scenarios and can effectively reduce the risk of API key leaks.Usage: In your code, replace the API key used for authentication with the obtained temporary authentication token.

Interface description

TingWuRealtimeParam.java

This is the parameter configuration class. The following table lists the main parameters for creating a task. The interaction protocol for industrial instruction transcription (WebSocket) is used as an example.

Name

Type

Required

Description

appId

string

Yes

The application ID.

sampleRate

int

No

The audio sample rate. Only 16000 Hz is supported.

format

string

Yes

The format of the audio to be recognized. Supported formats: pcm, wav, mp3, opus, speex, aac, and amr. For opus and speex formats, ogg encapsulation is required. For the wav format, pcm encoding is required.

maxEndSilence

int

No

Optional. The maximum duration of silence in ms. If silence exceeds this duration, the system considers the sentence complete and finishes the transcription.

terminology

string

No

The ID of the correction instruction set.

Sample code

TingWuRealtimeParam tingWuRealtimeParam = TingWuRealtimeParam.builder()
    .model("tingwu-industrial-instruction")
    .format("pcm")
    .sampleRate(16000)
    .terminology("terminology")
    .appId("your-app-id")
    .apiKey("your-api-key")
    .build();

TingWuRealtime.java

  • The Tingwu real-time client interface.
/**
   * Tingwu real-time SDK.
   *
   * @param baseUrl The base URL.
   */
public TingWuRealtime(String baseUrl)

/**
   * Starts a Tingwu real-time session. The correct call order is: first call `call`,
   * then repeatedly call `sendAudioFrame`, and finally call `stop`.
   *
   * @param param The configuration for Tingwu real-time, including audio format,
   *     source language, and target languages.
   * @param callback The result callback.
   */
public void call(
      TingWuRealtimeParam param, TingWuRealtimeCallback callback)

/**
   * Sends one audio frame.
   *
   * @param audioFrame A frame of binary audio.
   */
public void sendAudioFrame(ByteBuffer audioFrame)

/**
   * Stops the Tingwu real-time call session.
   */
public void stop()

TingWuRealtimeCallback

  • This callback returns server-side events and results.
/**
 * An abstract class for callbacks that handle real-time transcription events.
 *
 * author songsong.shao
 * date 2025/4/27
 */
public abstract class TingWuRealtimeCallback {

  /**
   * Called when a task starts.
   * @param taskId The task ID.
   */
  public abstract void onStarted(String taskId);

  /**
   * Called when a task stops.
   * @param taskId The task ID.
   */
  public abstract void onStopped(String taskId);

  /**
   * Called when an error occurs.
   *
   * @param errorCode The error code.
   * @param errorMsg The error message.
   */
  public abstract void onError(String errorCode, String errorMsg);

  /**
   * Called when an AI result is available.
   *
   * @param taskId The task ID.
   * @param content The response content as a JsonObject.
   */
  public abstract void onAiResult(String taskId, JsonObject content);

  /**
   * Called when a recognition result is available.
   *
   * @param taskId The task ID.
   * @param content The speech content as a JsonObject.
   */
  public abstract void onRecognizeResult(String taskId, JsonObject content);

  /**
   * Called when the server is ready to listen for speech.
   *
   * @param taskId The task ID.
   * @param dataId The data ID for this task.
   */
  public abstract void onSpeechListen(String taskId, String dataId);

  /** Called when the connection is closed. */
  public abstract void onClosed();
}

Call sequence

The following time series chart shows the call sequence for the Tingwu real-time interface. After you establish a connection and receive the SpeechListen event, you can send streaming audio data. The server then returns streaming recognition and correction results.
Screenshot

Response results

Using the interaction protocol for industrial instruction transcription (WebSocket) as an example, after you send an instruction or audio, the server sends you different types of events. Each event represents a different processing stage. You must strictly follow the time series chart to handle these events. There are four types of events: speech-listen, recognize-result, ai-result, and speech-end.

speech-listen event

This corresponds to process 3 in the sequence diagram. The speech-listen event is returned after the run-task instruction. It indicates that the server has received your transcription instruction and completed the initialization. You can now start sending audio. The protocol fields are as follows:

Field

Type

Description

header

Object

header.event

String

Always result-generated.

header.task_id

String

The task_id that you specified in the run-task instruction.

payload

Object

payload.output

Object

payload.output.action

String

Always speech-listen.

payload.output.dataId

String

The ID of the current transcription task. You can use this ID to submit feedback. You can also use this ID to view the billing items for the task in your bill.

The following is an example of a speech-listen event:
{
  "header": {
    "event": "result-generated",
    "task_id": "f2E3zvK*******wp"
  },
  "payload": {
    "output": {
      "action": "speech-listen",
      "dataId": "Adb*******uY"
    }
  }
}

recognize-result event

This corresponds to process 4 in the sequence diagram. The recognize-result event is returned after you send audio. It may also be returned after you send the finish-task instruction. This event contains the text and translation results that the server has recognized so far. The protocol fields are as follows:

Field

Type

Description

header

Object

header.event

String

Always result-generated.

header.task_id

String

The task_id that you specified in the run-task instruction.

payload

Object

payload.output

Object

payload.output.action

String

Always recognize-result.

payload.output.transcription

Object

The original transcription result.

payload.output.transcription.sentenceId

Integer

The sentence sequence number.

payload.output.transcription.beginTime

Integer

The start time in the audio for the first character of the currently recognized part of the sentence, in ms.

payload.output.transcription.endTime

Integer

The end time in the audio for the last character of the currently recognized part of the sentence, in ms.

payload.output.transcription.sentenceEnd

Boolean

Indicates whether the current sentence is complete.

payload.output.transcription.text

String

The content of the currently recognized part of the sentence.

payload.output.transcription.words

List[Word]

Word segmentation information for the sentence.

payload.output.translations

Object

The translation result of the transcription.

payload.output.translations.sentenceEnd

Boolean

Indicates whether the current sentence is complete.

payload.output.translations.translations

Object

The result set for the target translation languages.

payload.output.translations.translations.zh

Object

Currently, only translation to Chinese is supported, so there will only be one zh object.

payload.output.translations.translations.zh.lang

String

Set the value to zh.

payload.output.translations.translations.zh.sentenceId

Integer

The sentence sequence number.

payload.output.translations.translations.zh.beginTime

Integer

The start time in the audio for the first character of the currently translated part of the sentence, in ms.

payload.output.translations.translations.zh.endTime

Integer

The end time in the audio for the last character of the currently translated part of the sentence, in ms.

payload.output.translations.translations.zh.sentenceEnd

Boolean

Indicates whether the current sentence is complete.

payload.output.translations.translations.zh.text

String

The content of the currently translated part of the sentence.

payload.output.translations.translations.zh.words

List[Word]

Word segmentation information for the translated sentence.

The Word type protocol is as follows:

Field

Type

Description

beginTime

Integer

The start time of the current word in the audio.

endTime

Integer

The end time of the current word in the audio.

text

String

The content of the current word.

The following is an example of a recognize-result event:
{
  "header": {
    "event":"result-generated",
    "task_id": "f2E3zvK*******wp"
  },
  "payload": {
    "output": {
      "action": "recognize-result",
      "transcription": {
        "sentenceId": 0,
        "beginTime": 100,
        "endTime": 2720,
        "sentenceEnd": true,
        "text": "This is a sentence for testing.",
        "words": [
          {
            "beginTime": 100,
            "endTime": 427,
            "text": "This"
          },
          {
            "beginTime": 427,
            "endTime": 755,
            "text": "is a"
          },
          {
            "beginTime": 755,
            "endTime": 1082,
            "text": "sentence"
          },
          {
            "beginTime": 1082,
            "endTime": 1410,
            "text": "used for"
          },
          {
            "beginTime": 1410,
            "endTime": 1737,
            "text": "testing"
          },
          {
            "beginTime": 1737,
            "endTime": 2065,
            "text": "of"
          },
          {
            "beginTime": 2065,
            "endTime": 2392,
            "text": "text"
          },
          {
            "beginTime": 2392,
            "endTime": 2720,
            "text": "."
          }
        ]
      },
      "translations": {
        "sentenceEnd": true,
        "translations": {
          "zh": {
            "sentenceId": 0,
            "beginTime": 100,
            "endTime": 2720,
            "text": "This is a sentence for testing.",
            "lang": "zh",
            "words": [
              {
                "beginTime": 100,
                "endTime": 427,
                "text": "This"
              },
              {
                "beginTime": 427,
                "endTime": 755,
                "text": "is a"
              },
              {
                "beginTime": 755,
                "endTime": 1082,
                "text": "sentence"
              },
              {
                "beginTime": 1082,
                "endTime": 1410,
                "text": "used for"
              },
              {
                "beginTime": 1410,
                "endTime": 1737,
                "text": "testing"
              },
              {
                "beginTime": 1737,
                "endTime": 2065,
                "text": "of"
              },
              {
                "beginTime": 2065,
                "endTime": 2392,
                "text": "text"
              },
              {
                "beginTime": 2392,
                "endTime": 2720,
                "text": "."
              }
            ],
            "sentenceEnd": true
          }
        }
      }
    }
  }
}

ai-result event

This corresponds to process 6 in the sequence diagram. The ai-result event is returned after the last recognize-result event. It represents the final transcription result, which has been corrected using the specified instruction set. The protocol fields are as follows:

Field

Type

Description

header

Object

header.event

String

Always result-generated.

header.task_id

String

The task_id that you specified in the run-task instruction.

payload

Object

payload.output

Object

payload.output.action

String

Always ai-result.

payload.output.aiResult

Object

payload.output.aiResult.correction

String

The final result of the industrial instruction transcription.

The following is an example of an ai-result event:
{
  "header": {
    "event": "result-generated",
    "task_id": "f2E3zvK*******wp"
  },
  "payload": {
    "output": {
      "action": "ai-result",
      "aiResult": {
        "correction": "Right fender paint slag SQE."
      }
    }
  }
}

speech-end event

This corresponds to process 7 in the sequence diagram. The speech-end event is sent after the ai-result event. It indicates that the industrial instruction transcription is complete. You can then close the WebSocket connection. The protocol fields are as follows:

Field

Type

Description

header

Object

header.event

String

Always result-generated.

header.task_id

String

The task_id that you specified in the run-task instruction.

payload

Object

payload.output

Object

payload.output.action

String

This is fixed to the end of the speech.

The following is an example of a speech-end event:
{
  "header": {
    "event": "result-generated",
    "task_id": "f2E3zvK*******wp"
  },
  "payload": {
    "output": {
      "action": "speech-end"
    }
  }
}

task-failed event

If a task fails during processing because of incorrect parameters from the client or an internal server error, the server returns a task-failed event and then closes the WebSocket connection. The protocol fields are as follows:

Field

Type

Description

header

Object

header.event

String

Always result-generated.

header.task_id

String

The task_id that you specified in the run-task instruction.

payload

Object

payload.output

Object

payload.output.action

String

The value is always set to task-failed.

payload.output.errorCode

String

Error code

payload.output.errorMessage

String

Error message

The following is an example of a task-failed event:
{
  "header": {
    "event": "result-generated",
    "task_id": "f2E3zvK*******wp"
  },
  "payload": {
    "output": {
      "action": "task-failed",
      "errorCode": "Error code",
      "errorMessage": "Error message"
    }
  }
}
For more information about specific error codes and their meanings, see Error codes.

Error codes

Error code

Error message

Description

InvalidParameter

Invalid parameter. For more information, see the official documentation.

The parameter is invalid. Check the parameters that you passed.

InvalidParameter

The value of maxEndSilence is invalid. It must be between 0 and 6000.

The value of the maxEndSilence parameter is invalid.

InvalidParameter

The term is not found.

The specified instruction set does not exist.

InvalidParameter

The sample rate is invalid.

The value of the sample rate parameter is invalid.

InvalidParameter

The audio format is invalid.

The value of the audio coding format parameter is invalid.

InvalidParameter

The term is invalid.

The specified instruction set ID is invalid.

Agent.FrameSequenceIllegal

The WebSocket frame sequence is invalid.

The instruction call sequence is invalid.

Agent.InputActionIllegal

The input action is invalid.

The value of the action field in the instruction is invalid.

Agent.InputAppIdIllegal

The input application ID is invalid.

The value of the application ID field is invalid.

Agent.AppNotPublished

The application has not been published.

The specified application has not been published.

Agent.CustomTaskIdInvalid

The custom task ID must be 16 characters long.

The length of the task ID is invalid.

BIL.ServiceNotActivate

The user has not activated the service.

You have not activated the Tingwu Agent service.

BIL.UserArrears

The user's account has an overdue payment.

Your account has an overdue payment.

Agent.AppInfoNotExist

The application information does not exist.

The specified application ID information does not exist. You must first save and publish the application configuration in the console.

ServerError

A server error occurred.

Internal server error.

Code example

The following example shows how to call the Java SDK for industrial instruction transcription:
package org.alibaba.speech.examples.speech_plus;

import com.alibaba.dashscope.multimodal.tingwu.TingWuRealtime;
import com.alibaba.dashscope.multimodal.tingwu.TingWuRealtimeCallback;
import com.alibaba.dashscope.multimodal.tingwu.TingWuRealtimeParam;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;

import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.CountDownLatch;

@Slf4j
public class TingWuRealtimeUsage {

    private static CountDownLatch speechListenLatch = new CountDownLatch(1);
    private static boolean isStopped = false;

    public static TingWuRealtimeCallback tingWuRealtimeCallback = new TingWuRealtimeCallback() {

        @Override
        public void onStarted(String taskId) {
            log.debug("onStarted: {}", taskId);
        }

        @Override
        public void onStopped(String taskId) {
            log.debug("onStopped: {}", taskId);
            isStopped = true;
        }

        @Override
        public void onError(String errorCode, String errorMsg) {
            log.debug("onError: {}, {}", errorCode, errorMsg);
        }

        @Override
        public void onAiResult(String taskId, JsonObject content) {
            log.debug("onAiResult: {}, {}", taskId, content.toString());
        }

        @Override
        public void onRecognizeResult(String taskId, JsonObject content) {
            log.debug("onRecognizeResult: {}, {}", taskId, content.toString());
        }

        @Override
        public void onSpeechListen(String taskId, String dataId) {
            log.debug("onSpeechListen: {}", taskId);
            speechListenLatch.countDown();
        }

        @Override
        public void onClosed() {
            log.debug("onClosed");
        }
    };

    public static void main(String[] args) {
        TingWuRealtimeParam tingWuRealtimeParam = TingWuRealtimeParam.builder()
                .model("tingwu-industrial-instruction")
                .format("pcm")
                .sampleRate(16000)
                .terminology("your-terminology")
                .appId("your-app-id")
                .apiKey("your-api-key")
                .build();

        Path filePath = Paths.get("/path-to-your-file/test.pcm");
        String baseWebsocketApiUrl = "wss://dashscope.aliyuncs.com/api-ws/v1/inference";
        TingWuRealtime tingWuRealtime = new TingWuRealtime(baseWebsocketApiUrl);
        tingWuRealtime.call(tingWuRealtimeParam, tingWuRealtimeCallback);

        try {
            // Wait for the onSpeechListen callback to be triggered, with a timeout of 5 seconds.
            if (!speechListenLatch.await(5, java.util.concurrent.TimeUnit.SECONDS)) {
                log.warn("onSpeechListen callback not received within 5 seconds");
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        log.info("start to send audio....");

        // Send audio.
        try (FileInputStream fis = new FileInputStream(filePath.toFile())) {
            // The chunk size is set to 100 ms for a 16 KHz sample rate.
            byte[] buffer = new byte[3200];
            int bytesRead;
            // Loop to read chunks of the file.
            while ((bytesRead = fis.read(buffer)) != -1 && !isStopped) {
                ByteBuffer byteBuffer;
                if (bytesRead < buffer.length) {
                    byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead);
                } else {
                    byteBuffer = ByteBuffer.wrap(buffer);
                }
                // Send the ByteBuffer to the Tingwu real-time instance.
                tingWuRealtime.sendAudioFrame(byteBuffer);
                Thread.sleep(100);
                buffer = new byte[3200];
            }
            if (!isStopped) {
                tingWuRealtime.stop();
            }
            Thread.sleep(1000); // Wait for 1 second.
            log.info("end test.");
            tingWuRealtime.getDuplexApi().close(1000, "bye");
        } catch (Exception e) {
            e.printStackTrace();
            tingWuRealtime.getDuplexApi().close(1000, "bye");
        }

        System.exit(0);
    }
}
Agent Development
Agent Context
Agent Governance & Evolution
Store
Application Marketplace