QwenCloudBRASIL
Tradução de apoio para consulta. Código e identificadores técnicos preservados. Consultar referência original ↗

Reconhecimento de fala em tempo real

Discurso ao vivo para texto

Use para legendas ao vivo, reuniões online, bate-papo de voz, assistentes inteligentes e cenários semelhantes.

Visão geral

O serviço transmite áudio e retorna texto transcrito com baixa latência.

Além do WebSocket, Qwen-Audio-3.x-ASR-Flash-Streaming e Fun-ASR-Realtime Modelos também apoiam o protocolo de QOA. Para integração cliente-side que prioriza latência estável, resiliência em redes fracas, e integração de ruído e cancelamento de eco, o AOQ é recomendado. Para uma comparação de protocolo, veja [Realtime API overview] (/api-reference/realtime-api/overview).

Para cenários de lote, como transcrição de encontro, análise de chamadas, e geração de legendas, use [reconhecimento de fala em tempo real] (/developer-guides/speech/asr). Para orientação sobre escolher um modelo, veja [Speech-to-text] (/developer-guides/speech/speech-to-text-models).

Para a disponibilidade de modelos, idiomas suportados e comparação de características, veja [Modelos de voz para texto] (/developer-guides/speech/speech-to-text-models).

Pré-requisitos

Começando.

Qwen-Audio-3.x-ASR-Flash-Streaming/Fun-ASR-Realtime

DashScope SDK

    Para mais amostras de código, veja [GitHub] (https://github.com/aliyun/alibabacloud-bailian-speech-demo).

    [Pegue uma chave API] (/api-reference/preparation/api-keyE o define como uma variável de ambiente./api-reference/preparation/export-api-key-env). Para usar o SDK, [instale-o] (/api-reference/preparation/install-sdk).

    ### - A disponibilidade do modelo.
Modelo Versão Preço unitário Quota livre(Nota)
fun-asr-realtime Estável. US$ 0.00009/second 36 mil segundos (10 horas)
Válido por 90 dias.
    -  Mandarim, cantonês, Wu, Minnan, Hakka, Gan, Xiang e Jin.  Também apoia sotaques mandarinos de Zhongyuan, sudoeste, Jilu, Jianghuai, Lanyin, Jiaoliao, nordeste, Pequim, e Hong Kong-Taiwan regiões - incluindo Henan, Shaanxi, Hubei, Sichuan, Chongqing, Yunnan, Guizhou, Guangdong, Guangxi, Hebei, Tianjin, Shandong, Anhui, Nanjing, Jiangsu, Hangzhou, Gansu, e Ningxia. Inglês e japonês também são apoiados.
    -  Taxa de amostragem 16 kHz
    - ** Formatos de áudio**: pcm, wav, mp3, opus, spex, aac, amr

    ### Reconheça o discurso de um microfone.

     Reconhecer fala de um microfone e texto de saída em tempo real, então as palavras aparecem como o falante fala.

    

      ```java Java
      import com.alibaba.dashscope.audio.asr.recognition.Recognition;
      import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
      import com.alibaba.dashscope.audio.asr.recognition.RecognitionResult;
      import com.alibaba.dashscope.common.ResultCallback;
      import com.alibaba.dashscope.utils.Constants;

      import javax.sound.sampled.AudioFormat;
      import javax.sound.sampled.AudioSystem;
      import javax.sound.sampled.TargetDataLine;

      import java.nio.ByteBuffer;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.TimeUnit;

      public class Main {
        public static void main(String[] args) throws InterruptedException {
          Constants.baseWebsocketApiUrl = "wss://maas.qwencloudapi.com/api-ws/v1/inference";
          ExecutorService executorService = Executors.newSingleThreadExecutor();
          executorService.submit(new RealtimeRecognitionTask());
          executorService.shutdown();
          executorService.awaitTermination(1, TimeUnit.MINUTES);
          System.exit(0);
        }
      }

      class RealtimeRecognitionTask implements Runnable {
        @Override
        public void run() {
          RecognitionParam param = RecognitionParam.builder()
              .model("qwen-audio-3.0-asr-flash-streaming")
              // If you have not configured an environment variable, replace the following line with your API key: .apiKey("sk-xxx")
              .apiKey(System.getenv("DASHSCOPE_API_KEY"))
              .format("pcm")
              .sampleRate(16000)
              .build();
          Recognition recognizer = new Recognition();

          ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
            @Override
            public void onEvent(RecognitionResult result) {
              if (result.isSentenceEnd()) {
                System.out.println("Final Result: " + result.getSentence().getText());
              } else {
                System.out.println("Intermediate Result: " + result.getSentence().getText());
              }
            }

            @Override
            public void onComplete() {
              System.out.println("Recognition complete");
            }

            @Override
            public void onError(Exception e) {
              System.out.println("RecognitionCallback error: " + e.getMessage());
            }
          };
          try {
            recognizer.call(param, callback);
            // Create the audio format
            AudioFormat audioFormat = new AudioFormat(16000, 16, 1, true, false);
            // Match the default recording device based on the format
            TargetDataLine targetDataLine =
                AudioSystem.getTargetDataLine(audioFormat);
            targetDataLine.open(audioFormat);
            // Start recording
            targetDataLine.start();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long start = System.currentTimeMillis();
            // Record for 50s and perform real-time transcription
            while (System.currentTimeMillis() - start < 50000) {
              int read = targetDataLine.read(buffer.array(), 0, buffer.capacity());
              if (read > 0) {
                buffer.limit(read);
                // Send the recorded audio data to the streaming recognition service
                recognizer.sendAudioFrame(buffer);
                buffer = ByteBuffer.allocate(1024);
                // The recording rate is limited; sleep for a short while to prevent excessive CPU usage
                Thread.sleep(20);
              }
            }
            recognizer.stop();
          } catch (Exception e) {
            e.printStackTrace();
          } finally {
            // Close the WebSocket connection after the task is complete
            recognizer.getDuplexApi().close(1000, "bye");
          }

          System.out.println(
              "[Metric] requestId: "
                  + recognizer.getLastRequestId()
                  + ", first package delay ms: "
                  + recognizer.getFirstPackageDelay()
                  + ", last package delay ms: "
                  + recognizer.getLastPackageDelay());
        }
      }
      ```

      ```python Python
      import os
      import signal  # for keyboard events handling (press "Ctrl+C" to terminate recording)
      import sys

      import dashscope
      import pyaudio
      from dashscope.audio.asr import *

      mic = None
      stream = None

      # Set recording parameters
      sample_rate = 16000  # sampling rate (Hz)
      channels = 1  # mono channel
      dtype = 'int16'  # data type
      format_pcm = 'pcm'  # the format of the audio data
      block_size = 3200  # number of frames per buffer

      # Real-time speech recognition callback
      class Callback(RecognitionCallback):
        def on_open(self) -> None:
          global mic
          global stream
          print('RecognitionCallback open.')
          mic = pyaudio.PyAudio()
          stream = mic.open(format=pyaudio.paInt16,
                                channels=1,
                                rate=16000,
                                input=True)

        def on_close(self) -> None:
          global mic
          global stream
          print('RecognitionCallback close.')
          stream.stop_stream()
          stream.close()
          mic.terminate()
          stream = None
          mic = None

        def on_complete(self) -> None:
          print('RecognitionCallback completed.')  # recognition completed

        def on_error(self, message) -> None:
          print('RecognitionCallback task_id: ', message.request_id)
          print('RecognitionCallback error: ', message.message)
          # Stop and close the audio stream if it is running
          if 'stream' in globals() and stream.active:
            stream.stop()
            stream.close()
          # Forcefully exit the program
          sys.exit(1)

        def on_event(self, result: RecognitionResult) -> None:
          sentence = result.get_sentence()
          if 'text' in sentence:
            print('RecognitionCallback text: ', sentence['text'])
            if RecognitionResult.is_sentence_end(sentence):
              print(
                'RecognitionCallback sentence end, request_id:%s, usage:%s'
                % (result.get_request_id(), result.get_usage(sentence)))

      def signal_handler(sig, frame):
        print('Ctrl+C pressed, stop recognition ...')
        # Stop recognition
        recognition.stop()
        print('Recognition stopped.')
        print(
          '[Metric] requestId: {}, first package delay ms: {}, last package delay ms: {}'
          .format(
            recognition.get_last_request_id(),
            recognition.get_first_package_delay(),
            recognition.get_last_package_delay(),
          ))
        # Forcefully exit the program
        sys.exit(0)

      # main function
      if __name__ == '__main__':
        # If you have not configured an environment variable, replace the following line with your API key: dashscope.api_key = "sk-xxx"
        dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

        dashscope.base_websocket_api_url='wss://maas.qwencloudapi.com/api-ws/v1/inference'

        # Create the recognition callback
        callback = Callback()

        # Call recognition service by async mode, you can customize the recognition parameters, like model, format,
        # sample_rate
        recognition = Recognition(
          model='qwen-audio-3.0-asr-flash-streaming',
          format=format_pcm,
          # 'pcm', 'wav', 'opus', 'speex', 'aac', 'amr', you can check the supported formats in the document
          sample_rate=sample_rate,
          # support 8000, 16000
          semantic_punctuation_enabled=False,
          callback=callback)

        # Start recognition
        recognition.start()

        signal.signal(signal.SIGINT, signal_handler)
        print("Press 'Ctrl+C' to stop recording and recognition...")
        # Create a keyboard listener until "Ctrl+C" is pressed

        while True:
          if stream:
            data = stream.read(3200, exception_on_overflow=False)
            recognition.send_audio_frame(data)
          else:
            break

        recognition.stop()
      ```
    


    

       Antes de executar o exemplo Python, instale o kit de ferramentas de áudio de terceiros com `pip install pyaudio`Pyaudio requer a biblioteca do porto. Em Ubuntu/Debian: `sudo apt-get install libportaudio2 portaudio19-dev`. Em macOS: `brew install portaudio`.
    


    ### Reconheça um arquivo de áudio local.

    Reconheça um arquivo de áudio local e dê o resultado.  Isso se encaixa em cenários mais curtos, quase em tempo real, como conversas de bate-papo, comandos de voz, métodos de entrada de voz e busca de voz.

    

      ```java Java
      import com.alibaba.dashscope.api.GeneralApi;
      import com.alibaba.dashscope.audio.asr.recognition.Recognition;
      import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
      import com.alibaba.dashscope.audio.asr.recognition.RecognitionResult;
      import com.alibaba.dashscope.base.HalfDuplexParamBase;
      import com.alibaba.dashscope.common.GeneralListParam;
      import com.alibaba.dashscope.common.ResultCallback;
      import com.alibaba.dashscope.protocol.GeneralServiceOption;
      import com.alibaba.dashscope.protocol.HttpMethod;
      import com.alibaba.dashscope.protocol.Protocol;
      import com.alibaba.dashscope.protocol.StreamingMode;
      import com.alibaba.dashscope.utils.Constants;

      import java.io.FileInputStream;
      import java.nio.ByteBuffer;
      import java.nio.file.Path;
      import java.nio.file.Paths;
      import java.time.LocalDateTime;
      import java.time.format.DateTimeFormatter;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.TimeUnit;

      class TimeUtils {
        private static final DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

        public static String getTimestamp() {
          return LocalDateTime.now().format(formatter);
        }
      }

      public class Main {
        public static void main(String[] args) throws InterruptedException {
          Constants.baseWebsocketApiUrl = "wss://maas.qwencloudapi.com/api-ws/v1/inference";
          // In real applications, this method only needs to be executed once at the very beginning of the program; there is no need to execute it multiple times.
          warmUp();

          ExecutorService executorService = Executors.newSingleThreadExecutor();
          executorService.submit(new RealtimeRecognitionTask(Paths.get(System.getProperty("user.dir"), "{YOUR_AUDIO_FILE}")));
          executorService.shutdown();

          // Wait for all tasks to complete.
          executorService.awaitTermination(1, TimeUnit.MINUTES);
          System.exit(0);
        }

        public static void warmUp() {
          try {
            // Lightweight GET request to establish connection
            GeneralServiceOption warmupOption = GeneralServiceOption.builder()
                .protocol(Protocol.HTTP)
                .httpMethod(HttpMethod.GET)
                .streamingMode(StreamingMode.OUT)
                .path("assistants")
                .build();

            warmupOption.setBaseHttpUrl(Constants.baseHttpApiUrl);
            GeneralApi<HalfDuplexParamBase> api = new GeneralApi<>();
            api.get(GeneralListParam.builder().limit(1L).build(), warmupOption);
          } catch (Exception e) {
            // Reset flag to allow retry if pre-warming failed
          }
        }
      }

      class RealtimeRecognitionTask implements Runnable {
        private Path filepath;

        public RealtimeRecognitionTask(Path filepath) {
          this.filepath = filepath;
        }

        @Override
        public void run() {
          RecognitionParam param = RecognitionParam.builder()
              .model("qwen-audio-3.1-asr-flash-streaming")
              // If you have not configured an environment variable, replace the following line with your API key: .apiKey("sk-xxx")
              .apiKey(System.getenv("DASHSCOPE_API_KEY"))
              .format("wav")
              .sampleRate(16000)
              .build();
          Recognition recognizer = new Recognition();

          String threadName = Thread.currentThread().getName();

          ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
            @Override
            public void onEvent(RecognitionResult message) {
              if (message.isSentenceEnd()) {

                System.out.println(TimeUtils.getTimestamp()+" "+
                    "[process " + threadName + "] Final Result:" + message.getSentence().getText());
              } else {
                System.out.println(TimeUtils.getTimestamp()+" "+
                    "[process " + threadName + "] Intermediate Result: " + message.getSentence().getText());
              }
            }

            @Override
            public void onComplete() {
              System.out.println(TimeUtils.getTimestamp()+" "+"[" + threadName + "] Recognition complete");
            }

            @Override
            public void onError(Exception e) {
              System.out.println(TimeUtils.getTimestamp()+" "+
                  "[" + threadName + "] RecognitionCallback error: " + e.getMessage());
            }
          };

          try {
            recognizer.call(param, callback);
            // Please replace the path with your audio file path
            System.out.println(TimeUtils.getTimestamp()+" "+"[" + threadName + "] Input file_path is: " + this.filepath);
            // Read file and send audio by chunks
            FileInputStream fis = new FileInputStream(this.filepath.toFile());
            byte[] allData = new byte[fis.available()];
            int ret = fis.read(allData);
            fis.close();

            int sendFrameLength = 3200;
            for (int i = 0; i * sendFrameLength < allData.length; i ++) {
              int start = i * sendFrameLength;
              int end = Math.min(start + sendFrameLength, allData.length);
              ByteBuffer byteBuffer = ByteBuffer.wrap(allData, start, end - start);
              recognizer.sendAudioFrame(byteBuffer);
              Thread.sleep(100);
            }

            System.out.println(TimeUtils.getTimestamp()+" "+LocalDateTime.now());
            recognizer.stop();
          } catch (Exception e) {
            e.printStackTrace();
          } finally {
            // Close the WebSocket connection after the task is complete
            recognizer.getDuplexApi().close(1000, "bye");
          }

          System.out.println(
              "["
                  + threadName
                  + "][Metric] requestId: "
                  + recognizer.getLastRequestId()
                  + ", first package delay ms: "
                  + recognizer.getFirstPackageDelay()
                  + ", last package delay ms: "
                  + recognizer.getLastPackageDelay());
        }
      }
      ```

      ```python Python
      import os
      import time
      import dashscope
      from dashscope.audio.asr import *

      # If you have not set an environment variable, replace the next line with your API key: dashscope.api_key = "sk-xxx"
      dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

      dashscope.base_websocket_api_url='wss://maas.qwencloudapi.com/api-ws/v1/inference'

      from datetime import datetime

      def get_timestamp():
        now = datetime.now()
        formatted_timestamp = now.strftime("[%Y-%m-%d %H:%M:%S.%f]")
        return formatted_timestamp

      class Callback(RecognitionCallback):
        def on_complete(self) -> None:
          print(get_timestamp() + ' Recognition completed')  # recognition complete

        def on_error(self, message: str) -> None:
          print('Error occurred: ', message)
          print('Error details: ', message)
          exit(0)

        def on_event(self, result: RecognitionResult) -> None:
          sentence = result.get_sentence()
          if 'text' in sentence:
            print(get_timestamp() + ' RecognitionCallback text: ', sentence['text'])
          if RecognitionResult.is_sentence_end(sentence):
            print(get_timestamp() +
                        'RecognitionCallback sentence end, request_id:%s, usage:%s'
                        % (result.get_request_id(), result.get_usage(sentence)))

      callback = Callback()

      recognition = Recognition(model='qwen-audio-3.1-asr-flash-streaming',
                                format='wav',
                                sample_rate=16000,
                                callback=callback)

      try:
        audio_data: bytes = None
        f = open("{YOUR_AUDIO_FILE}", 'rb')
        if os.path.getsize("{YOUR_AUDIO_FILE}"):
          # Read all the file data into the buffer at once
          file_buffer = f.read()
          f.close()
          print("Start Recognition")
          recognition.start()

          # Send 3200 bytes from the buffer at a time
          buffer_size = len(file_buffer)
          offset = 0
          chunk_size = 3200

          while offset < buffer_size:
            # Calculate the size of the data chunk to send this time
            remaining_bytes = buffer_size - offset
            current_chunk_size = min(chunk_size, remaining_bytes)

            # Extract the current data chunk from the buffer
            audio_data = file_buffer[offset:offset + current_chunk_size]

            # Send the audio data frame
            recognition.send_audio_frame(audio_data)
            # Update the offset
            offset += current_chunk_size

            # Add a delay to simulate real-time transmission
            time.sleep(0.1)

          recognition.stop()
        else:
          raise Exception(
            'The supplied file was empty (zero bytes long)')
      except Exception as e:
        raise e

      print(
        '[Metric] requestId: {}, first package delay ms: {}, last package delay ms: {}'
        .format(
          recognition.get_last_request_id(),
          recognition.get_first_package_delay(),
          recognition.get_last_package_delay(),
        ))
      ```

WebSocket API

     Os exemplos a seguir demonstram como enviar um arquivo de áudio local e recuperar resultados de reconhecimento através de uma conexão WebSocket nativa.

    # Instalar dependências #

    

      ```bash Python
      pip uninstall websocket-client
      pip uninstall websocket
      pip install websocket-client
      ```

      ```xml Maven
      <dependency>
        <groupId>org.java-websocket</groupId>
        <artifactId>Java-WebSocket</artifactId>
        <version>1.5.6</version>
      </dependency>
      <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20240303</version>
      </dependency>
      ```

      ```gradle Gradle
      implementation 'org.java-websocket:Java-WebSocket:1.5.6'
      implementation 'org.json:json:20240303'
      ```
    


    

       Não diga o nome do seu arquivo de exemplo. `websocket.py`. Este nome está em conflito com o `websocket`  biblioteca e desencadeia o seguinte erro: `AttributeError: module 'websocket' has no attribute 'WebSocketApp'. Did you mean: 'WebSocket'?`
    


    

      ```python Python
      # pip install websocket-client
      import os
      import json
      import time
      import uuid
      import threading
      import websocket

      # If you have not configured the environment variable, replace the line below with your API Key: api_key = "sk-xxx"
      api_key = os.environ.get('DASHSCOPE_API_KEY')
      url = 'wss://maas.qwencloudapi.com/api-ws/v1/inference'
      audio_file = '{YOUR_AUDIO_FILE}'  # Replace with your audio file path

      TASK_ID = uuid.uuid4().hex[:32]
      task_started = False

      def send_run_task(ws):
        run_task_message = {
          'header': {
            'action': 'run-task',
            'task_id': TASK_ID,
            'streaming': 'duplex'
          },
          'payload': {
            'task_group': 'audio',
            'task': 'asr',
            'function': 'recognition',
            'model': 'qwen-audio-3.1-asr-flash-streaming',
            'parameters': {
              'sample_rate': 16000,
              'format': 'wav'
            },
            'input': {}
          }
        }
        ws.send(json.dumps(run_task_message))

      def send_finish_task(ws):
        finish_task_message = {
          'header': {
            'action': 'finish-task',
            'task_id': TASK_ID,
            'streaming': 'duplex'
          },
          'payload': {
            'input': {}
          }
        }
        ws.send(json.dumps(finish_task_message))

      def send_audio_stream(ws):
        chunk_size = 3200  # 100ms @ 16kHz 16bit mono
        try:
          with open(audio_file, 'rb') as f:
            while True:
              chunk = f.read(chunk_size)
              if not chunk:
                break
              ws.send(chunk, opcode=websocket.ABNF.OPCODE_BINARY)
              time.sleep(0.1)
          print('Audio stream ended')
          send_finish_task(ws)
        except Exception as e:
          print('Failed to read audio file: ', e)
          ws.close()

      def on_open(ws):
        print('Connected to server')
        send_run_task(ws)

      def on_message(ws, data):
        global task_started
        message = json.loads(data)
        event = message['header']['event']
        if event == 'task-started':
          print('Task started')
          task_started = True
          threading.Thread(target=send_audio_stream, args=(ws,), daemon=True).start()
        elif event == 'result-generated':
          print('Recognition result: ', message['payload']['output']['sentence']['text'])
          if message['payload'].get('usage'):
            print('Task billing duration (seconds): ', message['payload']['usage']['duration'])
        elif event == 'task-finished':
          print('Task finished')
          ws.close()
        elif event == 'task-failed':
          print('Task failed: ', message['header'].get('error_message'))
          ws.close()
        else:
          print('Unknown event: ', event)

      def on_close(ws, close_status_code, close_msg):
        if not task_started:
          print('Task not started, closing connection')

      def on_error(ws, error):
        print('WebSocket error: ', error)

      if __name__ == '__main__':
        ws = websocket.WebSocketApp(
          url,
          header={'Authorization': f'bearer {api_key}'},
          on_open=on_open,
          on_message=on_message,
          on_error=on_error,
          on_close=on_close
        )
        ws.run_forever()
      ```

      ```java Java
      import org.java_websocket.client.WebSocketClient;
      import org.java_websocket.handshake.ServerHandshake;
      import org.json.JSONObject;
      import java.net.URI;
      import java.nio.ByteBuffer;
      import java.nio.file.Files;
      import java.nio.file.Paths;
      import java.util.UUID;
      import java.util.concurrent.atomic.AtomicBoolean;

      public class FunASRRealtimeClient {
        // If you have not configured the environment variable, replace the line below with your API Key: private static final String API_KEY = "sk-xxx";
        private static final String API_KEY = System.getenv().getOrDefault("DASHSCOPE_API_KEY", "sk-xxx");
        private static final String URL = "wss://maas.qwencloudapi.com/api-ws/v1/inference";
        private static final String AUDIO_FILE = "{YOUR_AUDIO_FILE}";
        private static final String MODEL = "qwen-audio-3.1-asr-flash-streaming";
        private static final String TASK_ID = UUID.randomUUID().toString().replace("-", "").substring(0, 32);
        private static final AtomicBoolean taskStarted = new AtomicBoolean(false);
        private static WebSocketClient client;

        public static void main(String[] args) throws Exception {
          client = new WebSocketClient(new URI(URL)) {
            @Override
            public void onOpen(ServerHandshake handshake) {
              System.out.println("Connected to server");
              sendRunTask();
            }
            @Override
            public void onMessage(String data) {
              JSONObject message = new JSONObject(data);
              String event = message.getJSONObject("header").getString("event");
              switch (event) {
                case "task-started":
                  System.out.println("Task started");
                  taskStarted.set(true);
                  new Thread(FunASRRealtimeClient::sendAudioStream).start();
                  break;
                case "result-generated":
                  JSONObject payload = message.getJSONObject("payload");
                  String text = payload.getJSONObject("output").getJSONObject("sentence").getString("text");
                  System.out.println("Recognition result: " + text);
                  if (payload.has("usage")) {
                    System.out.println("Task billing duration (seconds): " + payload.getJSONObject("usage").get("duration"));
                  }
                  break;
                case "task-finished":
                  System.out.println("Task finished");
                  close();
                  break;
                case "task-failed":
                  String errMsg = message.getJSONObject("header").optString("error_message");
                  System.err.println("Task failed: " + errMsg);
                  close();
                  break;
                default:
                  System.out.println("Unknown event: " + event);
              }
            }
            @Override
            public void onClose(int code, String reason, boolean remote) {
              if (!taskStarted.get()) {
                System.err.println("Task not started, closing connection");
              }
            }
            @Override
            public void onError(Exception ex) {
              System.err.println("WebSocket error: " + ex.getMessage());
            }
          };
          client.addHeader("Authorization", "bearer " + API_KEY);
          client.connectBlocking();
        }

        private static void sendRunTask() {
          JSONObject runTask = new JSONObject()
            .put("header", new JSONObject()
              .put("action", "run-task")
              .put("task_id", TASK_ID)
              .put("streaming", "duplex"))
            .put("payload", new JSONObject()
              .put("task_group", "audio")
              .put("task", "asr")
              .put("function", "recognition")
              .put("model", MODEL)
              .put("parameters", new JSONObject()
                .put("sample_rate", 16000)
                .put("format", "wav"))
              .put("input", new JSONObject()));
          client.send(runTask.toString());
        }

        private static void sendAudioStream() {
          int chunkSize = 3200;
          try {
            byte[] audio = Files.readAllBytes(Paths.get(AUDIO_FILE));
            int offset = 0;
            while (offset < audio.length) {
              int end = Math.min(offset + chunkSize, audio.length);
              byte[] chunk = new byte[end - offset];
              System.arraycopy(audio, offset, chunk, 0, end - offset);
              client.send(ByteBuffer.wrap(chunk));
              offset = end;
              Thread.sleep(100);
            }
            System.out.println("Audio stream ended");
            sendFinishTask();
          } catch (Exception e) {
            System.err.println("Failed to read audio file: " + e.getMessage());
            client.close();
          }
        }

        private static void sendFinishTask() {
          JSONObject finishTask = new JSONObject()
            .put("header", new JSONObject()
              .put("action", "finish-task")
              .put("task_id", TASK_ID)
              .put("streaming", "duplex"))
            .put("payload", new JSONObject()
              .put("input", new JSONObject()));
          client.send(finishTask.toString());
        }
      }
      ```

Qwen3-ASR-Flash-Realtime

### - A disponibilidade do modelo.
Modelo Versão Preço unitário Quota livre(Nota)
qwen3-asr-flash-realtime Estável. US$ 0.00009/second 36 mil segundos (10 horas)
Válido por 90 dias.

DashScope SDK

Instale o SDK

        [Instalar o SDK] (/api-reference/preparation/install-sdk).  Certifique-se que a versão SDK DashScope seja 2.22.5 ou posterior (Java) ou 1.25.6 ou posterior (Python).

Get an API key

        [Pegue uma chave API] (/api-reference/preparation/api-key). Defina a chave API como uma variável de ambiente para evitar codificação difícil em seu código.

Execute o código de amostra.

          ```java Java
          import com.alibaba.dashscope.audio.omni.*;
          import com.alibaba.dashscope.exception.NoApiKeyException;
          import com.google.gson.JsonObject;
          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;

          import javax.sound.sampled.LineUnavailableException;
          import java.io.File;
          import java.io.FileInputStream;
          import java.util.Base64;
          import java.util.Collections;
          import java.util.concurrent.CountDownLatch;
          import java.util.concurrent.atomic.AtomicReference;

          public class Qwen3AsrRealtimeUsage {
            private static final Logger log = LoggerFactory.getLogger(Qwen3AsrRealtimeUsage.class);
            private static final int AUDIO_CHUNK_SIZE = 1024; // Audio chunk size in bytes
            private static final int SLEEP_INTERVAL_MS = 30;  // Sleep interval in milliseconds

            public static void main(String[] args) throws InterruptedException, LineUnavailableException {
              CountDownLatch finishLatch = new CountDownLatch(1);

              OmniRealtimeParam param = OmniRealtimeParam.builder()
                  .model("qwen3-asr-flash-realtime")
                  .url("wss://maas.qwencloudapi.com/api-ws/v1/realtime")
                  // If you have not configured an environment variable, replace the following line with your API key: .apikey("sk-xxx")
                  .apikey(System.getenv("DASHSCOPE_API_KEY"))
                  .build();

              OmniRealtimeConversation conversation = null;
              final AtomicReference<OmniRealtimeConversation> conversationRef = new AtomicReference<>(null);
              conversation = new OmniRealtimeConversation(param, new OmniRealtimeCallback() {
                @Override
                public void onOpen() {
                  System.out.println("connection opened");
                }
                @Override
                public void onEvent(JsonObject message) {
                  String type = message.get("type").getAsString();
                  switch(type) {
                    case "session.created":
                      System.out.println("start session: " + message.get("session").getAsJsonObject().get("id").getAsString());
                      break;
                    case "conversation.item.input_audio_transcription.completed":
                      System.out.println("transcription: " + message.get("transcript").getAsString());
                      finishLatch.countDown();
                      break;
                    case "input_audio_buffer.speech_started":
                      System.out.println("======VAD Speech Start======");
                      break;
                    case "input_audio_buffer.speech_stopped":
                      System.out.println("======VAD Speech Stop======");
                      break;
                    case "conversation.item.input_audio_transcription.text":
                      System.out.println("transcription: " + message.get("text").getAsString());
                      break;
                    default:
                      break;
                  }
                }
                @Override
                public void onClose(int code, String reason) {
                  System.out.println("connection closed code: " + code + ", reason: " + reason);
                }
              });
              conversationRef.set(conversation);
              try {
                conversation.connect();
              } catch (NoApiKeyException e) {
                throw new RuntimeException(e);
              }

              OmniRealtimeTranscriptionParam transcriptionParam = new OmniRealtimeTranscriptionParam();
              transcriptionParam.setLanguage("zh");
              transcriptionParam.setInputAudioFormat("pcm");
              transcriptionParam.setInputSampleRate(16000);

              OmniRealtimeConfig config = OmniRealtimeConfig.builder()
                  .modalities(Collections.singletonList(OmniRealtimeModality.TEXT))
                  .transcriptionConfig(transcriptionParam)
                  .build();
              conversation.updateSession(config);

              String filePath = "your_audio_file.pcm";
              File audioFile = new File(filePath);
              if (!audioFile.exists()) {
                log.error("Audio file not found: {}", filePath);
                return;
              }

              try (FileInputStream audioInputStream = new FileInputStream(audioFile)) {
                byte[] audioBuffer = new byte[AUDIO_CHUNK_SIZE];
                int bytesRead;
                int totalBytesRead = 0;

                log.info("Starting to send audio data from: {}", filePath);

                // Read and send audio data in chunks
                while ((bytesRead = audioInputStream.read(audioBuffer)) != -1) {
                  totalBytesRead += bytesRead;
                  String audioB64 = Base64.getEncoder().encodeToString(audioBuffer);
                  // Send audio chunk to conversation
                  conversation.appendAudio(audioB64);

                  // Add small delay to simulate real-time audio streaming
                  Thread.sleep(SLEEP_INTERVAL_MS);
                }

                log.info("Finished sending audio data. Total bytes sent: {}", totalBytesRead);

              } catch (Exception e) {
                log.error("Error sending audio from file: {}", filePath, e);
              }

              // Send session.finish, wait for the session to finish, and then close the connection.
              conversation.endSession();
              log.info("Task finished");

              System.exit(0);
            }
          }
          ```

          ```python Python
          import logging
          import os
          import base64
          import signal
          import sys
          import time
          import dashscope
          from dashscope.audio.qwen_omni import *
          from dashscope.audio.qwen_omni.omni_realtime import TranscriptionParams

          def setup_logging():
            """Configure logging."""
            logger = logging.getLogger('dashscope')
            logger.setLevel(logging.DEBUG)
            handler = logging.StreamHandler(sys.stdout)
            handler.setLevel(logging.DEBUG)
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.propagate = False
            return logger

          def init_api_key():
            """Initialize the API key."""
            # If you have not configured an environment variable, replace the following line with your API key: dashscope.api_key = "sk-xxx"
            dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY', 'YOUR_API_KEY')
            if dashscope.api_key == 'YOUR_API_KEY':
              print('[Warning] Using placeholder API key, set DASHSCOPE_API_KEY environment variable.')

          class MyCallback(OmniRealtimeCallback):
            """Handle real-time recognition callbacks."""
            def __init__(self, conversation):
              self.conversation = conversation
              self.handlers = {
                'session.created': self._handle_session_created,
                'conversation.item.input_audio_transcription.completed': self._handle_final_text,
                'conversation.item.input_audio_transcription.text': self._handle_stash_text,
                'input_audio_buffer.speech_started': lambda r: print('======Speech Start======'),
                'input_audio_buffer.speech_stopped': lambda r: print('======Speech Stop======')
              }

            def on_open(self):
              print('Connection opened')

            def on_close(self, code, msg):
              print(f'Connection closed, code: {code}, msg: {msg}')

            def on_event(self, response):
              try:
                handler = self.handlers.get(response['type'])
                if handler:
                  handler(response)
              except Exception as e:
                print(f'[Error] {e}')

            def _handle_session_created(self, response):
              print(f"Start session: {response['session']['id']}")

            def _handle_final_text(self, response):
              print(f"Final recognized text: {response['transcript']}")

            def _handle_stash_text(self, response):
              print(f"Got stash result: {response['stash']}")

          def read_audio_chunks(file_path, chunk_size=3200):
            """Read the audio file in chunks."""
            with open(file_path, 'rb') as f:
              while chunk := f.read(chunk_size):
                yield chunk

          def send_audio(conversation, file_path, delay=0.1):
            """Send audio data."""
            if not os.path.exists(file_path):
              raise FileNotFoundError(f"Audio file {file_path} does not exist.")

            print("Processing audio file... Press 'Ctrl+C' to stop.")
            for chunk in read_audio_chunks(file_path):
              audio_b64 = base64.b64encode(chunk).decode('ascii')
              conversation.append_audio(audio_b64)
              time.sleep(delay)

          def main():
            setup_logging()
            init_api_key()

            audio_file_path = "./your_audio_file.pcm"
            conversation = OmniRealtimeConversation(
              model='qwen3-asr-flash-realtime',
              url='wss://maas.qwencloudapi.com/api-ws/v1/realtime',
              callback=MyCallback(conversation=None)  # Temporarily pass None and inject it later.
            )

            # Inject self into the callback.
            conversation.callback.conversation = conversation

            def handle_exit(sig, frame):
              print('Ctrl+C pressed, exiting...')
              conversation.close()
              sys.exit(0)

            signal.signal(signal.SIGINT, handle_exit)

            conversation.connect()

            transcription_params = TranscriptionParams(
              language='zh',
              sample_rate=16000,
              input_audio_format="pcm"
            )

            conversation.update_session(
              output_modalities=[MultiModality.TEXT],
              enable_input_audio_transcription=True,
              transcription_params=transcription_params
            )

            try:
              send_audio(conversation, audio_file_path)
              # Send session.finish, wait for the session to finish, and then close the connection.
              conversation.end_session()
            except Exception as e:
              print(f"Error occurred: {e}")
            finally:
              conversation.close()
              print("Audio processing completed.")

          if __name__ == '__main__':
            main()
          ```

WebSocket API

    O exemplo a seguir mostra como enviar um arquivo de áudio local e recuperar resultados de reconhecimento sobre uma conexão WebSocket.

Get an API key

        [Pegue uma chave API] (/api-reference/preparation/api-key). Por segurança, defina a chave API como uma variável de ambiente.

Instalar dependências

        ?Python: ?

         Antes de executar o exemplo, instale as dependências:

        ```bash
        pip uninstall websocket-client
        pip uninstall websocket
        pip install websocket-client
        ```

        

           Não nomeie o arquivo de código de exemplo. `websocket.py`.  Caso contrário, o seguinte erro pode ocorrer: o módulo 'websocket' não tem nenhum atributo 'WebSocketApp'.  Você quis dizer: 'WebSocket'?
        


        Java:

         Adicione a dependência Java-WebSocket:

        

          ```xml Maven
          <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.5.6</version>
          </dependency>
          ```

          ```gradle Gradle
          implementation 'org.java-websocket:Java-WebSocket:1.5.6'
          ```
        


        #Node.js:#

        ```bash
        npm install ws
        ```

Escreva e execute o código.

        Implemente o fluxo completo de autenticação, conexão, envio de áudio e recebimento de resultados. Para mais informações, veja [ Fluxo de interação] (/developer-guides/speech/asr-realtime#interaction-flow-qwen3-asr-flash-realtime).

        

          ```python Python
          # pip install websocket-client
          import os
          import time
          import json
          import threading
          import base64
          import websocket
          import logging
          import logging.handlers
          from datetime import datetime

          logger = logging.getLogger(__name__)
          logger.setLevel(logging.DEBUG)

          # If you have not configured an environment variable, replace the following line with your API key: API_KEY="sk-xxx"
          API_KEY = os.environ.get("DASHSCOPE_API_KEY", "sk-xxx")
          QWEN_MODEL = "qwen3-asr-flash-realtime"
          baseUrl = "wss://maas.qwencloudapi.com/api-ws/v1/realtime"
          url = f"{baseUrl}?model={QWEN_MODEL}"
          print(f"Connecting to server: {url}")

          # Note: If you are not in VAD mode, the cumulative duration of continuously sent audio should not exceed 60s.
          enableServerVad = True
          is_running = True  # Add a running flag.

          headers = [
            "Authorization: Bearer " + API_KEY,
            "OpenAI-Beta: realtime=v1"
          ]

          def init_logger():
            formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(message)s')
            f_handler = logging.handlers.RotatingFileHandler(
              "omni_tester.log", maxBytes=100 * 1024 * 1024, backupCount=3
            )
            f_handler.setLevel(logging.DEBUG)
            f_handler.setFormatter(formatter)

            console = logging.StreamHandler()
            console.setLevel(logging.DEBUG)
            console.setFormatter(formatter)

            logger.addHandler(f_handler)
            logger.addHandler(console)

          def on_open(ws):
            logger.info("Connected to server.")

            # Session update event.
            event_manual = {
              "event_id": "event_123",
              "type": "session.update",
              "session": {
                "modalities": ["text"],
                "input_audio_format": "pcm",
                "sample_rate": 16000,
                "input_audio_transcription": {
                  # Language identifier, optional. If you have clear language information, set it.
                  "language": "zh"
                },
                "turn_detection": None
              }
            }
            event_vad = {
              "event_id": "event_123",
              "type": "session.update",
              "session": {
                "modalities": ["text"],
                "input_audio_format": "pcm",
                "sample_rate": 16000,
                "input_audio_transcription": {
                  "language": "zh"
                },
                "turn_detection": {
                  "type": "server_vad",
                  "threshold": 0.0,
                  "silence_duration_ms": 400
                }
              }
            }
            if enableServerVad:
              logger.info(f"Sending event: {json.dumps(event_vad, indent=2)}")
              ws.send(json.dumps(event_vad))
            else:
              logger.info(f"Sending event: {json.dumps(event_manual, indent=2)}")
              ws.send(json.dumps(event_manual))

          def on_message(ws, message):
            global is_running
            try:
              data = json.loads(message)
              logger.info(f"Received event: {json.dumps(data, ensure_ascii=False, indent=2)}")
              if data.get("type") == "session.finished":
                logger.info(f"Final transcript: {data.get('transcript')}")
                logger.info("Closing WebSocket connection after session finished...")
                is_running = False  # Stop the audio sending thread.
                ws.close()
            except json.JSONDecodeError:
              logger.error(f"Failed to parse message: {message}")

          def on_error(ws, error):
            logger.error(f"Error: {error}")

          def on_close(ws, close_status_code, close_msg):
            logger.info(f"Connection closed: {close_status_code} - {close_msg}")

          def send_audio(ws, local_audio_path):
            time.sleep(3)  # Wait for the session update to complete.
            global is_running

            with open(local_audio_path, 'rb') as audio_file:
              logger.info(f"Start reading the file: {datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]}")
              while is_running:
                audio_data = audio_file.read(3200)  # ~0.1s PCM16/16kHz
                if not audio_data:
                  logger.info(f"Finished reading the file: {datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]}")
                  if ws.sock and ws.sock.connected:
                    if not enableServerVad:
                      commit_event = {
                        "event_id": "event_789",
                        "type": "input_audio_buffer.commit"
                      }
                      ws.send(json.dumps(commit_event))
                    finish_event = {
                      "event_id": "event_987",
                      "type": "session.finish"
                    }
                    ws.send(json.dumps(finish_event))
                  break

                if not ws.sock or not ws.sock.connected:
                  logger.info("The WebSocket is closed. Stop sending audio.")
                  break

                encoded_data = base64.b64encode(audio_data).decode('utf-8')
                eventd = {
                  "event_id": f"event_{int(time.time() * 1000)}",
                  "type": "input_audio_buffer.append",
                  "audio": encoded_data
                }
                ws.send(json.dumps(eventd))
                logger.info(f"Sending audio event: {eventd['event_id']}")
                time.sleep(0.1)  # Simulate real-time collection.

          # Initialize the logger.
          init_logger()
          logger.info(f"Connecting to WebSocket server at {url}...")

          local_audio_path = "your_audio_file.pcm"
          ws = websocket.WebSocketApp(
            url,
            header=headers,
            on_open=on_open,
            on_message=on_message,
            on_error=on_error,
            on_close=on_close
          )

          thread = threading.Thread(target=send_audio, args=(ws, local_audio_path))
          thread.start()
          ws.run_forever()
          ```

          ```java Java
          import org.java_websocket.client.WebSocketClient;
          import org.java_websocket.handshake.ServerHandshake;
          import org.json.JSONObject;

          import java.net.URI;
          import java.nio.file.Files;
          import java.nio.file.Paths;
          import java.util.Base64;
          import java.util.concurrent.atomic.AtomicBoolean;
          import java.util.logging.*;

          public class QwenASRRealtimeClient {

            private static final Logger logger = Logger.getLogger(QwenASRRealtimeClient.class.getName());
            // If you have not configured an environment variable, replace the following line with your API key: private static final String API_KEY = "sk-xxx"
            private static final String API_KEY = System.getenv().getOrDefault("DASHSCOPE_API_KEY", "sk-xxx");
            private static final String MODEL = "qwen3-asr-flash-realtime";

            // Controls whether to use VAD mode.
            private static final boolean enableServerVad = true;

            private static final AtomicBoolean isRunning = new AtomicBoolean(true);
            private static WebSocketClient client;

            public static void main(String[] args) throws Exception {
              initLogger();

              String baseUrl = "wss://maas.qwencloudapi.com/api-ws/v1/realtime";
              String url = baseUrl + "?model=" + MODEL;
              logger.info("Connecting to server: " + url);

              client = new WebSocketClient(new URI(url)) {
                @Override
                public void onOpen(ServerHandshake handshake) {
                  logger.info("Connected to server.");
                  sendSessionUpdate();
                }

                @Override
                public void onMessage(String message) {
                  try {
                    JSONObject data = new JSONObject(message);
                    String eventType = data.optString("type");

                    logger.info("Received event: " + data.toString(2));

                    // When the finish event is received, stop the sending thread and close the connection.
                    if ("session.finished".equals(eventType)) {
                      logger.info("Final transcript: " + data.optString("transcript"));
                      logger.info("Closing WebSocket connection after session finished...");

                      isRunning.set(false); // Stop the audio sending thread.
                      if (this.isOpen()) {
                        this.close(1000, "ASR finished");
                      }
                    }
                  } catch (Exception e) {
                    logger.severe("Failed to parse message: " + message);
                  }
                }

                @Override
                public void onClose(int code, String reason, boolean remote) {
                  logger.info("Connection closed: " + code + " - " + reason);
                }

                @Override
                public void onError(Exception ex) {
                  logger.severe("Error: " + ex.getMessage());
                }
              };

              // Add request headers.
              client.addHeader("Authorization", "Bearer " + API_KEY);
              client.addHeader("OpenAI-Beta", "realtime=v1");

              client.connectBlocking(); // Block until the connection is established.

              // Replace with the path of the audio file to recognize.
              String localAudioPath = "your_audio_file.pcm";
              Thread audioThread = new Thread(() -> {
                try {
                  sendAudio(localAudioPath);
                } catch (Exception e) {
                  logger.severe("Audio sending thread error: " + e.getMessage());
                }
              });
              audioThread.start();
            }

            /** Session update event (enable/disable VAD). */
            private static void sendSessionUpdate() {
              JSONObject eventNoVad = new JSONObject()
                  .put("event_id", "event_123")
                  .put("type", "session.update")
                  .put("session", new JSONObject()
                      .put("modalities", new String[]{"text"})
                      .put("input_audio_format", "pcm")
                      .put("sample_rate", 16000)
                      .put("input_audio_transcription", new JSONObject()
                          .put("language", "zh"))
                      .put("turn_detection", JSONObject.NULL) // Manual mode.
                  );

              JSONObject eventVad = new JSONObject()
                  .put("event_id", "event_123")
                  .put("type", "session.update")
                  .put("session", new JSONObject()
                      .put("modalities", new String[]{"text"})
                      .put("input_audio_format", "pcm")
                      .put("sample_rate", 16000)
                      .put("input_audio_transcription", new JSONObject()
                          .put("language", "zh"))
                      .put("turn_detection", new JSONObject()
                          .put("type", "server_vad")
                          .put("threshold", 0.0)
                          .put("silence_duration_ms", 400))
                  );

              if (enableServerVad) {
                logger.info("Sending event (VAD):\n" + eventVad.toString(2));
                client.send(eventVad.toString());
              } else {
                logger.info("Sending event (Manual):\n" + eventNoVad.toString(2));
                client.send(eventNoVad.toString());
              }
            }

            /** Send the audio file stream. */
            private static void sendAudio(String localAudioPath) throws Exception {
              Thread.sleep(3000); // Wait for the session to be ready.
              byte[] allBytes = Files.readAllBytes(Paths.get(localAudioPath));
              logger.info("Start reading the file.");

              int offset = 0;
              while (isRunning.get() && offset < allBytes.length) {
                int chunkSize = Math.min(3200, allBytes.length - offset);
                byte[] chunk = new byte[chunkSize];
                System.arraycopy(allBytes, offset, chunk, 0, chunkSize);
                offset += chunkSize;

                if (client != null && client.isOpen()) {
                  String encoded = Base64.getEncoder().encodeToString(chunk);
                  JSONObject eventd = new JSONObject()
                      .put("event_id", "event_" + System.currentTimeMillis())
                      .put("type", "input_audio_buffer.append")
                      .put("audio", encoded);

                  client.send(eventd.toString());
                  logger.info("Sending audio event: " + eventd.getString("event_id"));
                } else {
                  break; // Avoid sending after disconnection.
                }

                Thread.sleep(100); // Simulate real-time sending.
              }

              logger.info("Finished reading the file.");

              if (client != null && client.isOpen()) {
                // A commit is required in non-VAD mode.
                if (!enableServerVad) {
                  JSONObject commitEvent = new JSONObject()
                      .put("event_id", "event_789")
                      .put("type", "input_audio_buffer.commit");
                  client.send(commitEvent.toString());
                  logger.info("Sent commit event for manual mode.");
                }

                JSONObject finishEvent = new JSONObject()
                    .put("event_id", "event_987")
                    .put("type", "session.finish");
                client.send(finishEvent.toString());
                logger.info("Sent finish event.");
              }
            }

            /** Initialize the logger. */
            private static void initLogger() {
              logger.setLevel(Level.ALL);
              Logger rootLogger = Logger.getLogger("");
              for (Handler h : rootLogger.getHandlers()) {
                rootLogger.removeHandler(h);
              }

              Handler consoleHandler = new ConsoleHandler();
              consoleHandler.setLevel(Level.ALL);
              consoleHandler.setFormatter(new SimpleFormatter());
              logger.addHandler(consoleHandler);
            }
          }
          ```

          ```javascript Node.js
          /**
           * Qwen-ASR Realtime WebSocket Client (Node.js version)
           * Features:
           * - Supports VAD and Manual modes.
           * - Sends session.update to start a session.
           * - Continuously sends input_audio_buffer.append audio chunks.
           * - Sends input_audio_buffer.commit in Manual mode.
           * - Sends a session.finish event.
           * - Closes the connection after receiving a session.finished event.
           */

          import WebSocket from 'ws';
          import fs from 'fs';

          // ===== Configuration =====
          // If you have not configured an environment variable, replace the following line with your API key: const API_KEY = "sk-xxx"
          const API_KEY = process.env.DASHSCOPE_API_KEY || 'sk-xxx';
          const MODEL = 'qwen3-asr-flash-realtime';
          const enableServerVad = true; // true for VAD mode, false for Manual mode
          const localAudioPath = 'your_audio_file.pcm'; // Path to the PCM16, 16 kHz audio file

          const baseUrl = 'wss://maas.qwencloudapi.com/api-ws/v1/realtime';
          const url = `${baseUrl}?model=${MODEL}`;

          console.log(`Connecting to server: ${url}`);

          // ===== Status Control =====
          let isRunning = true;

          // ===== Establish Connection =====
          const ws = new WebSocket(url, {
              headers: {
                  'Authorization': `Bearer ${API_KEY}`,
                  'OpenAI-Beta': 'realtime=v1'
              }
          });

          // ===== Event Binding =====
          ws.on('open', () => {
              console.log('[WebSocket] Connected to server.');
              sendSessionUpdate();
              // Start the audio sending thread.
              sendAudio(localAudioPath);
          });

          ws.on('message', (message) => {
              try {
                  const data = JSON.parse(message);
                  console.log('[Received Event]:', JSON.stringify(data, null, 2));

                  // Received finish event.
                  if (data.type === 'session.finished') {
                      console.log(`[Final Transcript] ${data.transcript}`);
                      console.log('[Action] Closing WebSocket connection after session finished...');

                      if (ws.readyState === WebSocket.OPEN) {
                          ws.close(1000, 'ASR finished');
                      }
                  }
              } catch (e) {
                  console.error('[Error] Failed to parse message:', message);
              }
          });

          ws.on('close', (code, reason) => {
              console.log(`[WebSocket] Connection closed: ${code} - ${reason}`);
          });

          ws.on('error', (err) => {
              console.error('[WebSocket Error]', err);
          });

          // ===== Session Update =====
          function sendSessionUpdate() {
              const eventNoVad = {
                  event_id: 'event_123',
                  type: 'session.update',
                  session: {
                      modalities: ['text'],
                      input_audio_format: 'pcm',
                      sample_rate: 16000,
                      input_audio_transcription: {
                          language: 'zh'
                      },
                      turn_detection: null
                  }
              };

              const eventVad = {
                  event_id: 'event_123',
                  type: 'session.update',
                  session: {
                      modalities: ['text'],
                      input_audio_format: 'pcm',
                      sample_rate: 16000,
                      input_audio_transcription: {
                          language: 'zh'
                      },
                      turn_detection: {
                          type: 'server_vad',
                          threshold: 0.0,
                          silence_duration_ms: 400
                      }
                  }
              };

              if (enableServerVad) {
                  console.log('[Send Event] VAD Mode:\n', JSON.stringify(eventVad, null, 2));
                  ws.send(JSON.stringify(eventVad));
              } else {
                  console.log('[Send Event] Manual Mode:\n', JSON.stringify(eventNoVad, null, 2));
                  ws.send(JSON.stringify(eventNoVad));
              }
          }

          // ===== Send Audio File Stream =====
          function sendAudio(audioPath) {
              setTimeout(() => {
                  console.log(`[File Read Start] ${audioPath}`);
                  const buffer = fs.readFileSync(audioPath);

                  let offset = 0;
                  const chunkSize = 3200; // Approx. 0.1s of PCM16 audio

                  function sendChunk() {
                      if (!isRunning) return;
                      if (offset >= buffer.length) {
                          isRunning = false; // Stop sending audio.
                          console.log('[File Read End]');
                          if (ws.readyState === WebSocket.OPEN) {
                              if (!enableServerVad) {
                                  const commitEvent = {
                                      event_id: 'event_789',
                                      type: 'input_audio_buffer.commit'
                                  };
                                  ws.send(JSON.stringify(commitEvent));
                                  console.log('[Send Commit Event]');
                              }

                              const finishEvent = {
                                  event_id: 'event_987',
                                  type: 'session.finish'
                              };
                              ws.send(JSON.stringify(finishEvent));
                              console.log('[Send Finish Event]');
                          }

                          return;
                      }

                      if (ws.readyState !== WebSocket.OPEN) {
                          console.log('[Stop] WebSocket is not open.');
                          return;
                      }

                      const chunk = buffer.slice(offset, offset + chunkSize);
                      offset += chunkSize;

                      const encoded = chunk.toString('base64');
                      const appendEvent = {
                          event_id: `event_${Date.now()}`,
                          type: 'input_audio_buffer.append',
                          audio: encoded
                      };

                      ws.send(JSON.stringify(appendEvent));
                      console.log(`[Send Audio Event] ${appendEvent.event_id}`);

                      setTimeout(sendChunk, 100); // Simulate real-time sending.
                  }

                  sendChunk();
              }, 3000); // Wait for session configuration to complete.
          }
          ```

Recursos avançados

Pegue as datas.

Qwen-Audio-3.x-ASR-Flash-Streaming e Fun-ASR-Realtime Tempos de saída no nível de sentença** e nível de palavras** por padrão, que suporta alinhamento de legendas, destaque de palavras-chave, leitura de karaoke e cenários semelhantes.Qwen3-ASR-Flash-Realtime (qwen3-asr-flash-realtimeSe você precisar de datas, use Qwen-Audio-3.1-ASR-Flash-Streaming, Qwen-Audio-3.0-ASR-Flash-Streaming, ou Fun-ASR-Realtime. Para transcrição de arquivos, o modelo de transcrição de arquivos de gravação qwen3-asr-flash-filetrans suporta horários de nível de palavras. Para detalhes, veja [Reconhecimento de fala em tempo real] (/developer-guides/speech/asr).

As datas são devolvidas em milissegundos em dois níveis:

O trecho a seguir mostra a estrutura de resposta:

{
  "payload": {
    "output": {
      "sentence": {
        "begin_time": 170,
        "end_time": 920,
        "text": "OK, I got it",
        "sentence_end": true,
        "words": [
          { "begin_time": 170, "end_time": 295, "text": "OK", "punctuation": "," },
          { "begin_time": 295, "end_time": 503, "text": "I", "punctuation": "" },
          { "begin_time": 503, "end_time": 711, "text": "got", "punctuation": "" },
          { "begin_time": 711, "end_time": 920, "text": "it", "punctuation": "" }
        ]
      }
    }
  }
}

Os nomes de campo acima seguem os caminhos do WebSocket JSON. Diferentes SDKs expõem esses campos com suas próprias convenções de nomes (chaves dicionárias, propriedades de objetos, métodos getter, e assim por diante). Para o mapeamento completo do campo, veja [Eventos de servidor] (/api-reference/speech-recognition/fun-asr-realtime/server-events).

Reconhecimento de emoções

Qwen3-ASR-Flash-Realtime (qwen3-asr-flash-realtime) pode incluir o estado emocional do falante no resultado da transcrição. Está sempre ligado e não requer nenhuma configuração. A emoção é devolvida através de um nível superior emotion campo em ambos os conversation.item.input_audio_transcription.text e conversation.item.input_audio_transcription.completed eventos. O valor é uma das sete emoções de grãos finos: surprised, neutral, happy, sad, disgusted, angry, e fearful.

{
  "type": "conversation.item.input_audio_transcription.text",
  "emotion": "neutral",
  "text": "The weather is nice today",
  "stash": ""
}

Os nomes de campo acima seguem os caminhos do WebSocket JSON. Diferentes SDKs expõem esses campos com suas próprias convenções de nomes (chaves dicionárias, propriedades de objetos, métodos getter, e assim por diante). Para as definições de campo completo, restrições de valor, e exemplos, veja [Eventos de servidor] (/api-reference/speech-recognition/qwen-asr-realtime/server-events).

Indo ao vivo

Reutilizar conexões (WebSocket)

Conexões WebSocket para Qwen-Audio-3.x-ASR-Flash-Streaming e Fun-ASR-Realtime Pode ser reutilizado: depois que uma tarefa de reconhecimento terminar, você pode começar a próxima tarefa sem estabelecer uma nova conexão.

O cliente envia finish-task. Depois que o servidor retornar task-finishedO cliente pode enviar run-task novamente para começar uma nova tarefa.

  1. Espere o servidor devolver o task-finished evento antes de começar uma nova tarefa.
  2. Diferentes tarefas em uma conexão reutilizada devem usar diferentes task_id Valores.
  3. Quando uma tarefa falha, o servidor retorna um evento de erro e fecha a conexão. Essa conexão não pode ser reutilizada.
  4. Se nenhuma nova tarefa começar em 60 segundos após o fim da tarefa, a conexão será fechada automaticamente.

Qwen3-ASR-Flash-Realtime usa um modelo de sessão. Você deve fechar a conexão depois que cada sessão terminar, e a reutilização da conexão não é suportada.

Para os eventos de cada modelo, veja a correspondente [referência API] (#api-reference).

Melhores práticas de alta concorrência.

O SDK DashScope inclui um mecanismo de agrupamento integrado que reutiliza conexões WebSocket e objetos de reconhecimento, evitando o aumento da criação e destruição frequentes.

Só o Java SDK suporta essa característica.

View high-concurrency best practices

Pré-requisitos

O Java SDK combina uma piscina de conexão com uma piscina de objetos personalizada para melhor desempenho:

Etapas de implementação

**1. Adicione dependências

Adicione Dashscope-sdk-java e Commons-pool2 ao seu arquivo de configuração de dependência, de acordo com sua ferramenta de construção.

Maven

   Adicione as seguintes dependências dentro do `<dependencies>` -Etiqueta de `pom.xml`, então corra `mvn clean install`  Ou `mvn compile` para atualizar as dependências.

  ```xml
  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>dashscope-sdk-java</artifactId>
      <!-- Replace 'the-latest-version' with 2.16.9 or later -->
      <version>the-latest-version</version>
  </dependency>

  <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <!-- Replace 'the-latest-version' with the latest version -->
      <version>the-latest-version</version>
  </dependency>
  ```

Gradle

   Adicione as seguintes dependências dentro do `dependencies`  Bloco de `build.gradle`, então corra `./gradlew build --refresh-dependencies` da raiz do projeto (`gradlew build --refresh-dependencies` - No Windows).

  ```groovy
  dependencies {
      // Replace 'the-latest-version' with 2.16.9 or later
      implementation group: 'com.alibaba', name: 'dashscope-sdk-java', version: 'the-latest-version'

      // Replace 'the-latest-version' with the latest version
      implementation group: 'org.apache.commons', name: 'commons-pool2', version: 'the-latest-version'
  }
  ```

**2. Configura a piscina de conexão

Configure os parâmetros de conjunto de conexão através de variáveis de ambiente:

Variável ambiente Descrição
DASHSCOPE_CONNECTION_POOL_SIZE Tamanho da piscina de conexão. Recomendado: pelo menos o dobro da sua concorrência. Padrão: 32.
DASHSCOPE_MAXIMUM_ASYNC_REQUESTS Número máximo de pedidos de sincronização. Recomendado: o mesmo queDASHSCOPE_CONNECTION_POOL_SIZE. Padrão: 32.
DASHSCOPE_MAXIMUM_ASYNC_REQUESTS_PER_HOST Número máximo de pedidos de sincronização por host. Recomendado: o mesmo queDASHSCOPE_CONNECTION_POOL_SIZE. Padrão: 32.

**3. Configura o conjunto de objetos

Configure o tamanho do pool de objetos através de uma variável de ambiente:

Variável ambiente Descrição
RECOGNITION_OBJECTPOOL_SIZE Tamanho da piscina de objetos. Recomendado: 1,5 a 2 vezes sua máxima concorrência. Predefinição: 500.
- O tamanho da piscina de objetos (`RECOGNITION_OBJECTPOOL_SIZE` Deve ser menor ou igual ao tamanho da piscina de conexão.`DASHSCOPE_CONNECTION_POOL_SIZE`).  Caso contrário, quando o objeto pede um objeto e o conjunto de conexão está cheio, os blocos de linha de chamada.
- O tamanho do conjunto de objetos não deve exceder o limite QPS da sua conta.

Crie o conjunto de objetos com o seguinte código:

class RecognitionObjectPool {
    // For the complete example, see the full code below
    public static GenericObjectPool<Recognition> getInstance() {
        lock.lock();
        if (recognitionGenericObjectPool == null) {
            int objectPoolSize = getObjectivePoolSize();
            RecognitionObjectFactory recognitionObjectFactory =
                    new RecognitionObjectFactory();
            GenericObjectPoolConfig<Recognition> config =
                    new GenericObjectPoolConfig<>();
            config.setMaxTotal(objectPoolSize);
            config.setMaxIdle(objectPoolSize);
            config.setMinIdle(objectPoolSize);
            recognitionGenericObjectPool =
                    new GenericObjectPool<>(recognitionObjectFactory, config);
        }
        lock.unlock();
        return recognitionGenericObjectPool;
    }
}

**4. Pegue um objeto de reconhecimento emprestado da piscina de objetos.

Quando o número de objetos não retornados excede o limite de agrupamento de objetos, o sistema cria mais Recognition objetos. Esses novos objetos devem estabelecer uma nova conexão WebSocket e não podem ser reutilizados.

recognizer = RecognitionObjectPool.getInstance().borrowObject();

**5. Correr reconhecimento de fala

Chame o call Ou streamCall método do Recognition Objeção para fazer reconhecimento de fala.

**6. Devolva o objeto de reconhecimento

Depois que a tarefa de reconhecimento terminar, devolva o objeto de reconhecimento para que possa ser reutilizado. Não devolva objetos cujas tarefas estão inacabadas ou falhadas.

RecognitionObjectPool.getInstance().returnObject(recognizer);

Código completo.

package com.example.speech;

import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionResult;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.ApiKey;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import com.alibaba.dashscope.utils.Constants;

public class Main {
    public static void checkoutEnv(String envName, int defaultSize) {
        if (System.getenv(envName) != null) {
            System.out.println("[ENV CHECK]: " + envName + " "
                    + System.getenv(envName));
        } else {
            System.out.println("[ENV CHECK]: " + envName
                    + " Using Default which is " + defaultSize);
        }
    }

    public static void main(String[] args)
            throws NoApiKeyException, InterruptedException {
        Constants.baseWebsocketApiUrl = "wss://maas.qwencloudapi.com/api-ws/v1/inference";
        checkoutEnv("DASHSCOPE_CONNECTION_POOL_SIZE", 32);
        checkoutEnv("DASHSCOPE_MAXIMUM_ASYNC_REQUESTS", 32);
        checkoutEnv("DASHSCOPE_MAXIMUM_ASYNC_REQUESTS_PER_HOST", 32);
        checkoutEnv(RecognitionObjectPool.RECOGNITION_OBJECTPOOL_SIZE_ENV,
                RecognitionObjectPool.DEFAULT_OBJECT_POOL_SIZE);

        int threadNums = 3;
        String currentDir = System.getProperty("user.dir");
        Path[] filePaths = {
                Paths.get(currentDir, "{YOUR_AUDIO_FILE}"),
                Paths.get(currentDir, "{YOUR_AUDIO_FILE}"),
                Paths.get(currentDir, "{YOUR_AUDIO_FILE}"),
        };
        ExecutorService executorService = Executors.newFixedThreadPool(threadNums);
        for (int i = 0; i < threadNums; i++) {
            executorService.submit(new RealtimeRecognizeTask(filePaths));
        }
        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.MINUTES);
        System.exit(0);
    }
}

class RecognitionObjectFactory extends BasePooledObjectFactory<Recognition> {
    public RecognitionObjectFactory() {
        super();
    }

    @Override
    public Recognition create() throws Exception {
        return new Recognition();
    }

    @Override
    public PooledObject<Recognition> wrap(Recognition obj) {
        return new DefaultPooledObject<>(obj);
    }
}

class RecognitionObjectPool {
    public static GenericObjectPool<Recognition> recognitionGenericObjectPool;
    public static String RECOGNITION_OBJECTPOOL_SIZE_ENV =
            "RECOGNITION_OBJECTPOOL_SIZE";
    public static int DEFAULT_OBJECT_POOL_SIZE = 500;
    private static Lock lock = new java.util.concurrent.locks.ReentrantLock();

    public static int getObjectivePoolSize() {
        try {
            Integer n = Integer.parseInt(
                    System.getenv(RECOGNITION_OBJECTPOOL_SIZE_ENV));
            return n;
        } catch (NumberFormatException e) {
            return DEFAULT_OBJECT_POOL_SIZE;
        }
    }

    public static GenericObjectPool<Recognition> getInstance() {
        lock.lock();
        if (recognitionGenericObjectPool == null) {
            int objectPoolSize = getObjectivePoolSize();
            System.out.println("RECOGNITION_OBJECTPOOL_SIZE: "
                    + objectPoolSize);
            RecognitionObjectFactory recognitionObjectFactory =
                    new RecognitionObjectFactory();
            GenericObjectPoolConfig<Recognition> config =
                    new GenericObjectPoolConfig<>();
            config.setMaxTotal(objectPoolSize);
            config.setMaxIdle(objectPoolSize);
            config.setMinIdle(objectPoolSize);
            recognitionGenericObjectPool =
                    new GenericObjectPool<>(recognitionObjectFactory, config);
        }
        lock.unlock();
        return recognitionGenericObjectPool;
    }
}

class RealtimeRecognizeTask implements Runnable {
    private static final Object lock = new Object();
    private Path[] filePaths;

    public RealtimeRecognizeTask(Path[] filePaths) {
        this.filePaths = filePaths;
    }

    private static String getDashScopeApiKey() throws NoApiKeyException {
        String dashScopeApiKey = null;
        try {
            ApiKey apiKey = new ApiKey();
            dashScopeApiKey = ApiKey.getApiKey(null);
        } catch (NoApiKeyException e) {
            System.out.println("No API key found in environment.");
        }
        if (dashScopeApiKey == null) {
            dashScopeApiKey = "your-dashscope-apikey";
        }
        return dashScopeApiKey;
    }

    public void runCallback() {
        for (Path filePath : filePaths) {
            RecognitionParam param = null;
            try {
                param = RecognitionParam.builder()
                        .model("fun-asr-realtime")
                        .format("pcm")
                        .sampleRate(16000)
                        .apiKey(getDashScopeApiKey())
                        .build();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            Recognition recognizer = null;
            final boolean[] hasError = {false};
            try {
                recognizer = RecognitionObjectPool.getInstance().borrowObject();
                String threadName = Thread.currentThread().getName();

                ResultCallback<RecognitionResult> callback =
                        new ResultCallback<RecognitionResult>() {
                            @Override
                            public void onEvent(RecognitionResult message) {
                                synchronized (lock) {
                                    if (message.isSentenceEnd()) {
                                        System.out.println("[process " + threadName
                                                + "] Fix:" + message.getSentence().getText());
                                    } else {
                                        System.out.println("[process " + threadName
                                                + "] Result: " + message.getSentence().getText());
                                    }
                                }
                            }

                            @Override
                            public void onComplete() {
                                System.out.println("[" + threadName
                                        + "] Recognition complete");
                            }

                            @Override
                            public void onError(Exception e) {
                                System.out.println("[" + threadName
                                        + "] RecognitionCallback error: " + e.getMessage());
                                hasError[0] = true;
                            }
                        };
                System.out.println("[" + threadName
                        + "] Input file_path is: " + filePath);
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(filePath.toFile());
                } catch (Exception e) {
                    System.out.println("Error when loading file: " + filePath);
                    e.printStackTrace();
                }
                recognizer.call(param, callback);

                // chunk size set to 100 ms for 16KHz sample rate
                byte[] buffer = new byte[3200];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    ByteBuffer byteBuffer;
                    if (bytesRead < buffer.length) {
                        byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead);
                    } else {
                        byteBuffer = ByteBuffer.wrap(buffer);
                    }
                    recognizer.sendAudioFrame(byteBuffer);
                    Thread.sleep(100);
                    buffer = new byte[3200];
                }
                System.out.println("[" + threadName + "] send audio done");
                recognizer.stop();
                System.out.println("[" + threadName + "] asr task finished");
            } catch (Exception e) {
                e.printStackTrace();
                hasError[0] = true;
            }
            if (recognizer != null) {
                try {
                    if (hasError[0] == true) {
                        recognizer.getDuplexApi().close(1000, "bye");
                        RecognitionObjectPool.getInstance()
                                .invalidateObject(recognizer);
                    } else {
                        RecognitionObjectPool.getInstance()
                                .returnObject(recognizer);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void run() {
        runCallback();
    }
}

Configuração recomendada

A seguinte configuração é baseada nos resultados dos testes de execução apenas do serviço de reconhecimento de fala em tempo real em servidores dos tamanhos especificados. A concorrência de uma máquina aqui significa o número de tarefas de reconhecimento de fala em tempo real que funcionam ao mesmo tempo (isto é, o número de linhas de trabalho).

Tamanho da máquina Max concorda com a máquina. Tamanho da piscina de objetos Tamanho da piscina de conexão
4 núcleos, 8 GiB 100 500 2000
8 núcleos, 16 GiB 200 500 2000
16 núcleos, 32 GiB. 400 500 2000

Gestão de recursos e manipulação de exceções

// Close the connection
recognizer.getDuplexApi().close(1000, "bye");
// Invalidate the failed recognizer in the object pool
RecognitionObjectPool.getInstance().invalidateObject(recognizer);

Medição de aquecimento e latência.

Quando você avalia o desempenho, como latência de chamadas simultâneas para o DashScope Java SDK, se aquece completamente antes do teste formal.

** Mecanismo de reaproveitamento da conexão **

O DashScope Java SDK gerencia e reutiliza conexões WebSocket através de uma rede global de conexão singleton. O mecanismo funciona como segue:

Por que o aquecimento importa?

Nos seguintes casos, o conjunto de conexões pode não ter conexão ativa reutilizável, então o pedido deve criar um novo:

Nesses casos, as primeiras ou primeiras solicitações desencadeiam a configuração completa do WebSocket (Aperto de mão TCP, negociação TLS e atualização de protocolo), então sua latência final a final é significativamente maior do que as solicitações que reutilizam uma conexão.

? Prática recomendada ?

Antes de testar a carga ou medir a latência, siga estes passos de aquecimento:

  1. Chamadas de emissão no nível de concorrência do teste formal com antecedência (por exemplo, por 1 a 2 minutos) para preencher o pool de conexão.
  2. Confirme que a conexão se estabeleceu e mantém conexões suficientes e comece a coletar dados formais de desempenho.

Melhore a precisão de reconhecimento.

Crie uma estratégia de tolerância a falhas.

Uso principal: preconceito de contexto.Qwen3-ASR-Flash-Realtime)

Ao fornecer contexto, você pode otimizar o reconhecimento do vocabulário específico de domínio, como nomes, lugares e termos de produto.

O conteúdo do contexto não pode exceder 10 mil fichas.

Usagem:

** Tipos de texto suportados:** Estes incluem, mas não se limitam a:

Exemplo:

A transcrição correta de um segmento de áudio deve ser: "Que jargão interno do círculo bancário de investimento você conhece? Primeiro, os nove maiores bancos de investimento estrangeiros, o Bulge Bracket, BB..."

Sem o realce do contexto Com o aprimoramento do contexto
Sem o aumento do contexto, alguns nomes de bancos de investimento podem ser mal reconhecidos. Por exemplo, "Pedra do Pássaro" deve ser "Bulge Bracket". Resultado do reconhecimento: "Que jargão interno do círculo bancário de investimento você conhece? Primeiro, os nove maiores bancos de investimento estrangeiros, Bird Rock, BB..." Com o aprimoramento do contexto, os nomes de bancos de investimento são reconhecidos corretamente. Resultado do reconhecimento: "Que jargão interno do círculo bancário de investimento você conhece? Primeiro, os nove maiores bancos de investimento estrangeiros, o Bulge Bracket, BB..."

Para alcançar o resultado acima, adicione qualquer um dos seguintes conteúdos ao contexto:

Bulge Bracket, Boutique, Middle Market, domestic securities firms
Bulge Bracket Boutique Middle Market domestic securities firms
['Bulge Bracket', 'Boutique', 'Middle Market', 'domestic securities firms']
Investment Banking Categories Revealed!
Recently, many friends from Australia have asked me, what exactly is an investment bank? Today, I'll explain it. For international students, investment banks can be mainly divided into four categories: Bulge Bracket, Boutique, Middle Market, and domestic securities firms.
Bulge Bracket Investment Banks: These are what we often call the nine major investment banks, including Goldman Sachs, Morgan Stanley, etc. These large banks are enormous in both business scope and scale.
Boutique Investment Banks: These banks are relatively small but highly specialized in their business areas. For example, Lazard, Evercore, etc., have deep professional knowledge and experience in specific fields.
Middle Market Investment Banks: This type of bank mainly serves medium-sized companies, providing services such as mergers and acquisitions, and IPOs. Although not as large as the major banks, they have a high influence in specific markets.
Domestic Securities Firms: With the rise of the Chinese market, domestic securities firms are also playing an increasingly important role in the international market.
In addition, there are some Position and business divisions, you can refer to the relevant charts. I hope this information helps you better understand investment banking and prepare for your future career!
Investment Banking Categories Revealed!
Recently, many friends from Australia have asked me, what exactly is an investment bank? Today, I'll explain it. For international students, investment banks can be mainly divided into four categories: Bulge Bracket, Boutique, Middle Market, and domestic securities firms.
Bulge Bracket Investment Banks: These are what we often call the nine major investment banks, including Goldman Sachs, Morgan Stanley, etc. These large banks are enormous in both business scope and scale.
Boutique Investment Banks: These banks are relatively small but highly specialized in their business areas. For example, Lazard, Evercore, etc., have deep professional knowledge and experience in specific fields.
Middle Market Investment Banks: This type of bank mainly serves medium-sized companies, providing services such as mergers and acquisitions, and IPOs. Although not as large as the major banks, they have a high influence in specific markets.
Domestic Securities Firms: With the rise of the Chinese market, domestic securities firms are also playing an increasingly important role in the international market.
In addition, there are some Position and business divisions, you can refer to the relevant charts. I hope this information helps you better understand investment banking and prepare for your future career!
Wang Haoxuan, Li Zihan, Zhang Jingxing, Liu Xinyi, Chen Junjie, Yang Siyuan, Zhao Yutong, Huang Zhiqiang, Zhou Zimo, Wu Yajing, Xu Ruoxi, Sun Haoran, Hu Jinyu, Zhu Chenxi, Guo Wenbo, He Jingshu, Gao Yuhang, Lin Yifei,
Zheng Xiaoyan, Liang Bowen, Luo Jiaqi, Song Mingzhe, Xie Wanting, Tang Ziqian, Han Mengyao, Feng Yiran, Cao Qinxue, Deng Zirui, Xiao Wangshu, Xu Jiashu,
Cheng Yinuo, Yuan Zhiruo, Peng Haoyu, Dong Simiao, Fan Jingyu, Su Zijin, Lv Wenxuan, Jiang Shihan, Ding Muchen,
Wei Shuyao, Ren Tianyou, Jiang Yichen, Hua Qingyu, Shen Xinghe, Fu Jinyu, Yao Xingchen, Zhong Lingyu, Yan Licheng, Jin Ruoshui, Taoranting, Qi Shaoshang, Xue Zhilan, Zou Yunfan, Xiong Ziang, Bai Wenfeng, Yi Qianfan

Uso principal: filtragem sensível de palavras (Qwen-Audio-3.x-ASR-Flash-Streaming/Fun-ASR-Realtime)

Filtragem sensível de palavras substitui ou remove palavras sensíveis no resultado do reconhecimento. Use-o para inspeção de qualidade, conformidade de conteúdo, revisão de legendas e cenários semelhantes.

Modelos apoiados: Qwen-Audio-3.x-ASR-Flash-Streaming e Fun-ASR-Realtime Só.

Você pode configurar até 32 palavras sensíveis.

** Como configurar:** special_word_filter É um objeto JSON com três subcampos:

Exemplo de configuração:

{
  "special_word_filter": {
    "filter_with_signed": {
      "word_list": ["test"]
    },
    "filter_with_empty": {
      "word_list": ["start", "occur"]
    },
    "system_reserved_filter": true
  }
}

Diferentes SDKs expõem esses parâmetros com suas próprias convenções de nomes (chaves dicionárias, propriedades de objetos, métodos, etc.). Para o mapeamento completo do campo, veja a referência da API.

Configuração de segmentação VAD

A detecção de atividade vocal determina quando um segmento contínuo de fala termina, o que desencadeia o reconhecimento final do evento. Todas as três famílias de modelos permitem VAD do lado do servidor por padrão, mas seus nomes de parâmetros e afinação de granularidade diferem:

Nomes dos parâmetros variam de acordo com o protocolo: o mesmo conceito é chamado max_sentence_silence Em Qwen-Audio-3.0-ASR-Flash-Streaming / Fun-ASR-Realtime - Paraformer, e silence_duration_ms Em Qwen3-ASR-Flash-Realtime. Para as definições de campo completo, veja a referência da API abaixo.

Reconhecimento de emoções

Qwen3-ASR-Flash-Realtime e alguns modelos Paraformer podem incluir o estado emocional do falante no resultado da transcrição, mas os dois diferem na granularidade de saída e em como o recurso é habilitado.

**Qwen3-ASR-Flash-Realtime (qwen3-asr-flash-realtime Sempre ligado, nenhuma configuração necessária. A emoção é devolvida através de um nível superior emotion campo em ambos os conversation.item.input_audio_transcription.text e conversation.item.input_audio_transcription.completed eventos. O valor é uma das sete emoções de grãos finos: surprised, neutral, happy, sad, disgusted, angry, e fearful.

{
  "type": "conversation.item.input_audio_transcription.text",
  "emotion": "neutral",
  "text": "The weather is nice today",
  "stash": ""
}

Referência da API

Qwen-Audio-3.x-ASR-Flash-Streaming/Fun-ASR-Realtime

- [Qwen-Audio-3.x-ASR-Flash-Streaming/Fun-ASR-Realtime REFERÊNCIA DA API DE RECONHECIMENTO DE LOGAÇÃO EM TEMPO Real/api-reference/speech-recognition/fun-asr-realtime/python-sdk)
- [AOQ Cliente SDK] (/api-reference/realtime-api/aoq-sdk-intro(para Qwen-Audio-3.x-ASR-Flash-Streaming/Fun-ASR-Realtime)

Qwen3-ASR-Flash-Realtime

[Referência API de reconhecimento de fala em tempo real] (/api-reference/speech-recognition/qwen-asr-realtime/python-sdk)

Fluxo de interação (Qwen3-ASR-Flash-Realtime)

Qwen Reconhecimento de fala em tempo real transmite áudio sobre WebSocket. Dois modos estão disponíveis: modo VAD (padrão) e [Modo manual] (#manual-mode).

URL

Substituir <model_name> com seu [modelo] (/developer-guides/speech/speech-to-text-models) nome.

wss://maas.qwencloudapi.com/api-ws/v1/realtime?model=<model_name>

Cabeçalhos

"Authorization": "Bearer $DASHSCOPE_API_KEY"

Modo VAD (padrão)

O servidor detecta limites de fala e segmenta frases. O cliente transmite áudio, e o servidor retorna os resultados quando cada frase termina. Melhor para conversas e transcrição de encontros.

** Ativar: ** Set session.turn_detection Em session.update.

[Modo de interação VAD] (https://help-static-aliyun-doc.aliyuncs.com/assets/img/en-US/5305458671/CAEQUxiBgMDxw_SV3hkiIDIxZDVlODkyYWRiNDQ0YWJiNWFkYjZhNTgwMzc1MjUw5812623_20251022102739.334.svg)

Modo manual

O cliente controla a segmentação da sentença enviando áudio para uma sentença completa, e depois enviando input_audio_buffer.commit. Melhor quando o cliente conhece limites de sentenças, por exemplo, em mensagens de voz de aplicativo de chat.

** Ativar: ** Set session.turn_detection para null Em session.update.

[Modo manual de interação flui] (https://help-static-aliyun-doc.aliyuncs.com/assets/img/en-US/5305458671/CAEQUxiBgID0ovyV3hkiIGQyZGZiNDJkMDVhOTQxYjBiMmM2OWJjY2M3MjFjNGVh5812623_20251022102739.334.svg)

FAQ

Que formatos de áudio é o suporte de reconhecimento de fala em tempo real?

Qwen-Audio-3.x-ASR-Flash-Streaming e Fun-ASR-Realtime Suporte Pcm, wav, mp3, opus, spex, aac, e amr. Qwen3-ASR-Flash-Realtime, use pcm ou opus ** Outros formatos, como wav, aac, e amr passar o session.update camada de validação, mas a decodificação do lado do servidor pode falhar. Confirme que o fluxo de áudio usa um formato recomendado antes de enviá-lo.

Qual a diferença entre o SDK e a API do WebSocket, e como eu escolho?

O DashScope SDK encapsula o gerenciamento de conexão WebSocket, autenticação, reconexão e outros detalhes, o que o torna adequado para uma integração rápida. Conectar-se à API WebSocket dá-lhe controle mais fino e combina com linguagens de programação que o SDK não cobre ou cenários que precisam de gerenciamento de conexão personalizado. Nós recomendamos o SDK.

Como melhoro a precisão de reconhecimento para substantivos adequados?

Use palavras quentes ou aprimoramento de contexto. Para métodos de configuração detalhados e notas de uso, veja [Melhorar precisão de reconhecimento] (/developer-guides/speech/improve-recognition-accuracy).

O que devo fazer quando a conexão cair com frequência?

Implemente a reconexão do lado do cliente e habilite o parâmetro batimento cardíaco (heartbeat=true) para evitar que a conexão caia quando não há áudio por um longo tempo. Para a estratégia de tolerância à falha, veja#set-up-a-fault-tolerance-strategy).