All Products
Search
Document Center

Alibaba Cloud Model Studio:Transkripsikan ucapan real-time dengan fun-asr-realtime melalui AOQ

Last Updated:Sep 02, 2026

Gunakan AOQ untuk terhubung ke fun-asr-realtime, mengalirkan audio dari mikrofon, dan menerima hasil transkripsi secara real time. Kode klien menggunakan Android Java, dan platform lain yang didukung AOQ menyediakan antarmuka yang serupa.

Solusi ikhtisar

fun-asr-realtime mentranskripsikan aliran audio menjadi teks ber-tanda baca secara real time. SDK AOQ mengangkut media dan event melalui track terpisah: klien mengirim audio melalui Audio track dan menggunakan Data track untuk mengirim event kontrol serta menerima event pengenalan. Model ini menggunakan protokol event Inferensi, bukan protokol event Realtime.

Solusi ini cocok untuk takarir langsung, transkripsi rapat, input suara, dan asisten cerdas. Audio track menghilangkan kebutuhan untuk mengencode audio dalam pesan event, sedangkan Data track mempertahankan semantik tugas seperti run-task, result-generated, dan finish-task.

  1. Klien meminta kredensial koneksi AOQ sementara dari server aplikasi.
  2. Server aplikasi menggunakan Kunci API untuk meminta token dari Model Studio dan mengembalikan field koneksi ke klien.
  3. Klien menetapkan koneksi AOQ dan mengirim run-task. Setelah task-started diterima, klien mulai mengirim audio dari mikrofon.
  4. Server terus-menerus mengembalikan event result-generated. Setelah klien mengirim finish-task, klien menunggu hasil akhir dan task-finished.

Prasyarat

  1. Aktifkan Alibaba Cloud Model Studio dan buat Kunci API seperti dijelaskan dalam Memperoleh dan mengonfigurasi Kunci API. Simpan Kunci API hanya di server aplikasi. Jangan sertakan dalam kode klien atau commit ke repositori kode.
  2. Pilih titik akhir AOQ untuk wilayah tempat aplikasi Anda diterapkan. Untuk pemilihan titik akhir, lihat Pilih wilayah, cakupan penerapan, dan titik akhir.
  3. Unduh SDK AOQ Client terbaru seperti dijelaskan dalam Unduhan SDK. Tutorial ini mengangkut audio PCM dan tidak memerlukan plugin Opus opsional.
  4. Siapkan server aplikasi seperti dijelaskan dalam Otentikasi token dan implementasikan otentikasi proxy sisi server untuk protokol Inferensi AOQ. Sebelum setiap koneksi baru, klien harus memperoleh kredensial koneksi baru dari server aplikasi.

Impor SDK

Pilih instruksi integrasi SDK untuk platform pengembangan Anda. Implementasi klien menggunakan Android Java; platform lain mengikuti desain API dan alur event yang sama.

Android

  1. Letakkan AoqClientSdk-release.aar di app/libs dan konfigurasikan dependensi serta ABIs di app/build.gradle:
android {
    defaultConfig {
        minSdk 21
        ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.aar'])
}
  1. Deklarasikan izin jaringan dan perekaman di AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
  1. Minta izin runtime RECORD_AUDIO sebelum perekaman dimulai. Pengenalan suara tidak memerlukan izin CAMERA.

iOS

  1. Tarik AoqClientSdk.framework ke dalam proyek Xcode. Di Target > General > Frameworks, Libraries, and Embedded Content, pilih Embed & Sign. SDK mendukung perangkat arm64 yang menjalankan iOS 13.0 atau lebih baru.
  2. Tambahkan NSMicrophoneUsageDescription ke Info.plist. Pengenalan suara tidak memerlukan NSCameraUsageDescription.
  3. Gunakan import AoqClientSdk di Swift, atau #import <AoqClientSdk/AoqClientSdk.h> di Objective-C.

HarmonyOS

  1. Letakkan AoqClientSdk.har di entry/libs dan deklarasikan dependensi di entry/oh-package.json5. SDK kompatibel dengan API 12 dan mendukung arm64-v8a:
{
  "dependencies": {
    "@aoq/client-sdk": "file:./libs/AoqClientSdk.har"
  }
}
  1. Deklarasikan izin jaringan dan mikrofon di entry/src/main/module.json5:
"requestPermissions": [
  { "name": "ohos.permission.INTERNET" },
  {
    "name": "ohos.permission.MICROPHONE",
    "reason": "$string:perm_mic_reason",
    "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
  }
]
  1. Sebelum perekaman dimulai, panggil abilityAccessCtrl.createAtManager().requestPermissionsFromUser untuk meminta akses mikrofon.

Linux (Python)

  1. Ekstrak SDK dan simpan aoq_client_sdk.py, libAoqClientSdk.so, dan libonnxruntime.so.1.16.3 dalam direktori yang sama.
  2. Tambahkan direktori SDK ke jalur pencarian modul Python dan pustaka bersama:
export PYTHONPATH="$PWD/AoqClientSdk:$PYTHONPATH"
export LD_LIBRARY_PATH="$PWD/AoqClientSdk:$LD_LIBRARY_PATH"
  1. Gunakan import aoq_client_sdk di Python. Anda juga dapat mengatur AOQ_CLIENT_SDK_LIB ke jalur mutlak libAoqClientSdk.so.

Coba demo

Gunakan demo Android dari Alibaba Cloud Model Studio untuk memverifikasi konektivitas AOQ dengan cepat. Unduh APK dan konfigurasikan Kunci API dan workspaceId untuk mencoba model yang dipilih.

Pindai kode QR berikut untuk mengunduh demo:

QR code for downloading the demo

Alur implementasi

  1. Server aplikasi menggunakan URL token Inferensi untuk memperoleh parameter koneksi AOQ untuk fun-asr-realtime.
  2. Klien memetakan respons token ke AoqConnectConfig, memublikasikan Audio dan Data track, serta berlangganan Data track.
  3. Klien mengonfigurasi parameter pengkodean audio berdasarkan kebutuhan bisnis dan model, memulai tangkapan mikrofon dengan pengiriman audio dinonaktifkan, dan menetapkan koneksi AOQ.
  4. Setelah koneksi ditetapkan, klien mengirim run-task dan mengaktifkan pengiriman Audio-track setelah task-started diterima.
  5. Klien menangani result-generated di onDataMsg. Untuk menghentikan pengenalan, klien pertama-tama menonaktifkan pengiriman Audio-track lalu mengirim finish-task.
  6. Setelah task-finished diterima, klien dapat memulai tugas lain pada koneksi yang sama dengan task_id baru, atau memutuskan koneksi dan menghapus engine.
Sequence diagram for real-time speech recognition with fun-asr-realtime over AOQ

Peroleh token di server aplikasi

Atur DASHSCOPE_API_KEY di server aplikasi dan kirim permintaan ke titik akhir untuk wilayah yang dipilih. clientIp adalah Alamat IP publik aktual perangkat klien. Field ini opsional, tetapi kami menyarankan Anda menyediakannya agar layanan dapat memilih titik akhir relay yang sesuai.

curl -X POST \
  "https://{endpoint}/api/v1/webrtc/inference?model=fun-asr-realtime" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
  -H "x-dashscope-rtc-transport: moq" \
  -d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"

CatatanJika server aplikasi tidak dapat memperoleh Alamat IP publik aktual perangkat klien, hilangkan clientIp dari badan permintaan alih-alih meneruskan string kosong.

Kembalikan field respons berikut ke klien. Jangan pernah mengembalikan Kunci API ke klien. Untuk semua field permintaan dan respons, lihat Otentikasi token.

Field respons

SDK Field

aoqTokenForClient

AoqConnectConfig.token

sid

AoqConnectConfig.sid

clientRelayCertFingerprint

AoqConnectConfig.certFingerprint

clientRelayEndpoints

AoqConnectConfig.relayEndpoints

extraInfo.workspaceIdHash

AoqConnectConfig.workspaceIdHash

Implementasikan klien Android

Langkah-langkah berikut membagi kode klien Android Java sesuai urutan koneksi dan tugas aktual. Setiap cuplikan diambil dari contoh lengkap di bagian akhir topik ini.

1. Buat engine dan daftarkan callback

Buat engine klien AOQ dan daftarkan callback untuk perubahan status koneksi dan event Data-track. Implementasikan logika callback untuk aplikasi Anda, dan mulai pengenalan hanya setelah koneksi ditetapkan.

AoqClientListener listener = new AoqClientListener() {
    @Override
    public void onConnectionStatusChange(AoqClientEngine.AoqConnectionStatus status) {
        connected = status == AoqClientEngine.AoqConnectionStatus
                .AoqConnectionStatusConnected;
        if (connected) {
            beginRecognition();
        }
    }

    @Override
    public void onDataMsg(AoqClientEngine.AoqDataMsg msg) {
        handleServerEvent(msg);
    }
};

AoqClientEngine.AoqCreateConfig createConfig = new AoqClientEngine.AoqCreateConfig();
createConfig.workDir = context.getFilesDir().getAbsolutePath();
engine = AoqClientEngine.createEngine(context, createConfig, listener);

2. Konfigurasikan pengkodean audio

Konfigurasikan pengkodean audio yang dikirim ke model. Atur format, laju sampel, dan jumlah channel berdasarkan kebutuhan aplikasi dan model Anda. Kode berikut menggunakan PCM mono 16 kHz sebagai contoh. Untuk nilai yang didukung, lihat parameter run-task di Event klien.

AoqClientEngine.AoqAudioCodecConfig encoder =
        new AoqClientEngine.AoqAudioCodecConfig();
encoder.trackType = AoqClientEngine.AoqTrackType.AoqTrackTypeAudio;
encoder.codecType = AoqClientEngine.AoqEncoderType.AoqEncoderTypeAudioPCM;
encoder.sampleRate = 16000;
encoder.channel = 1;
encoder.bitrate = 24000;
engine.setAudioEncoderConfig(encoder);

3. Konfigurasikan koneksi dan track transport

Konfigurasikan koneksi AOQ dengan kredensial yang dikembalikan oleh server aplikasi, dan pilih track yang akan dipublikasikan dan dilangganan berdasarkan aplikasi Anda. Untuk pengenalan ucapan real-time, contoh ini memublikasikan Audio dan Data track serta berlangganan Data track.

addTrack(connectConfig, true,
        AoqClientEngine.AoqTrackType.AoqTrackTypeAudio);
addTrack(connectConfig, true,
        AoqClientEngine.AoqTrackType.AoqTrackTypeData);
addTrack(connectConfig, false,
        AoqClientEngine.AoqTrackType.AoqTrackTypeData);

4. Mulai tangkapan audio dan tetapkan koneksi

Konfigurasikan tangkapan audio dan tetapkan koneksi AOQ. Pilih tangkapan bawaan atau eksternal, apakah akan mengaktifkan mode VoIP, dan jumlah channel berdasarkan aplikasi Anda. Pertahankan pengiriman Audio-track dinonaktifkan hingga task-started diterima.

AoqClientEngine.AoqAudioCaptureConfig capture =
        new AoqClientEngine.AoqAudioCaptureConfig();
capture.isExternal = false;
capture.isVoipMode = true;
capture.channel = 1;
engine.startAudioCapture(capture);

// Jangan kirim audio hingga task-started diterima.
engine.enableSendMediaStream(
        AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
engine.connect(connectConfig);

5. Mulai tugas pengenalan

Setelah koneksi ditetapkan, hasilkan ID tugas dan kirim run-task untuk memulai pengenalan. Konfigurasikan parameter tugas seperti model, format, sample_rate, dan lainnya sesuai model dan input audio yang Anda gunakan. Untuk detailnya, lihat Event klien.

taskId = UUID.randomUUID().toString();
JSONObject header = createHeader("run-task");
JSONObject parameters = new JSONObject()
        .put("format", "pcm")
        .put("sample_rate", 16000);
JSONObject payload = new JSONObject()
        .put("task_group", "audio")
        .put("task", "asr")
        .put("function", "recognition")
        .put("model", "fun-asr-realtime")
        .put("parameters", parameters)
        .put("input", new JSONObject());
send(new JSONObject().put("header", header).put("payload", payload));

6. Tangani event server

Tangani status tugas, hasil pengenalan, dan error, lalu teruskan hasilnya ke aplikasi Anda. Implementasikan callback berdasarkan kebutuhan UI dan manajemen status Anda. Kirim audio hanya setelah task-started diterima, dan jangan tampilkan event heartbeat dalam transkrip. Untuk skema respons lengkap, lihat Event server.

String eventName = header.optString("event", "");
if ("task-started".equals(eventName)) {
    taskStarted = true;
    engine.enableSendMediaStream(
            AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, true);
} else if ("result-generated".equals(eventName)) {
    JSONObject payload = event.optJSONObject("payload");
    JSONObject output = payload == null ? null : payload.optJSONObject("output");
    JSONObject sentence = output == null ? null : output.optJSONObject("sentence");
    if (sentence != null && !sentence.optBoolean("heartbeat", false)) {
        String text = sentence.optString("text", "");
        if (!text.isEmpty()) {
            resultListener.onResult(
                    text, sentence.optBoolean("sentence_end", false));
        }
    }
} else if ("task-finished".equals(eventName)) {
    resetTaskState();
    resultListener.onTaskFinished();
} else if ("task-failed".equals(eventName)) {
    String message = header.optString("error_message", "Recognition failed");
    resetTaskState();
    resultListener.onError(message);
}

7. Akhiri tugas pengenalan

Ketika pengguna menyelesaikan perekaman saat ini, hentikan pengiriman audio dan kirim finish-task. Pertahankan koneksi terbuka hingga transkrip akhir dan task-finished tiba. Anda kemudian dapat memulai tugas lain atau melepaskan koneksi berdasarkan alur aplikasi Anda. Untuk format event, lihat Event klien.

engine.enableSendMediaStream(
        AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
JSONObject payload = new JSONObject().put("input", new JSONObject());
send(new JSONObject()
        .put("header", createHeader("finish-task"))
        .put("payload", payload));

8. Putuskan koneksi dan hapus engine

Lepaskan tangkapan audio, koneksi AOQ, dan resource engine ketika halaman dihancurkan atau pengenalan tidak lagi diperlukan. Pilih titik pelepasan berdasarkan siklus hidup aplikasi Anda, dan jangan lepaskan resource segera setelah finish-task dikirim.

engine.enableSendMediaStream(
        AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
engine.stopAudioCapture();
engine.disconnect();
AoqClientEngine.destroy();

Contoh lengkap

Kelas Android Java ini memetakan respons JSON dari server aplikasi ke AoqConnectConfig dan menggabungkan logika koneksi, tangkapan, tugas, dan pelepasan resource sebelumnya.

import android.content.Context;

import com.alibaba.aoq.clientsdk.AoqClientEngine;
import com.alibaba.aoq.clientsdk.AoqClientListener;

import org.json.JSONArray;
import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

public final class AsrClient {
    public interface ResultListener {
        void onResult(String text, boolean sentenceEnd);

        void onTaskFinished();

        void onError(String message);
    }

    private final AoqClientEngine engine;
    private final ResultListener resultListener;
    private String taskId;
    private boolean connected;
    private boolean taskStarted;

    public AsrClient(Context context, AoqClientEngine.AoqConnectConfig connectConfig,
                     ResultListener resultListener) {
        this.resultListener = resultListener;
        AoqClientListener listener = new AoqClientListener() {
            @Override
            public void onConnectionStatusChange(AoqClientEngine.AoqConnectionStatus status) {
                connected = status == AoqClientEngine.AoqConnectionStatus
                        .AoqConnectionStatusConnected;
                if (connected) {
                    beginRecognition();
                }
            }

            @Override
            public void onDataMsg(AoqClientEngine.AoqDataMsg msg) {
                handleServerEvent(msg);
            }
        };

        AoqClientEngine.AoqCreateConfig createConfig = new AoqClientEngine.AoqCreateConfig();
        createConfig.workDir = context.getFilesDir().getAbsolutePath();
        engine = AoqClientEngine.createEngine(context, createConfig, listener);

        configureAudioEncoder();
        configureTracks(connectConfig);
        startAudioCapture();
        engine.connect(connectConfig);
    }

    private void configureAudioEncoder() {
        AoqClientEngine.AoqAudioCodecConfig encoder = new AoqClientEngine.AoqAudioCodecConfig();
        encoder.trackType = AoqClientEngine.AoqTrackType.AoqTrackTypeAudio;
        encoder.codecType = AoqClientEngine.AoqEncoderType.AoqEncoderTypeAudioPCM;
        encoder.sampleRate = 16000;
        encoder.channel = 1;
        encoder.bitrate = 24000;
        engine.setAudioEncoderConfig(encoder);
    }

    private static void configureTracks(AoqClientEngine.AoqConnectConfig connectConfig) {
        addTrack(connectConfig, true, AoqClientEngine.AoqTrackType.AoqTrackTypeAudio);
        addTrack(connectConfig, true, AoqClientEngine.AoqTrackType.AoqTrackTypeData);
        addTrack(connectConfig, false, AoqClientEngine.AoqTrackType.AoqTrackTypeData);
    }

    private void startAudioCapture() {
        AoqClientEngine.AoqAudioCaptureConfig capture =
                new AoqClientEngine.AoqAudioCaptureConfig();
        capture.isExternal = false;
        capture.isVoipMode = true;
        capture.channel = 1;
        engine.startAudioCapture(capture);
        engine.enableSendMediaStream(AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
    }

    /** Memulai tugas pengenalan lain pada koneksi AOQ yang ada. */
    public void beginRecognition() {
        if (!connected || taskStarted || taskId != null) {
            return;
        }
        taskId = UUID.randomUUID().toString();
        JSONObject header = createHeader("run-task");
        JSONObject parameters = new JSONObject()
                .put("format", "pcm")
                .put("sample_rate", 16000);
        JSONObject payload = new JSONObject()
                .put("task_group", "audio")
                .put("task", "asr")
                .put("function", "recognition")
                .put("model", "fun-asr-realtime")
                .put("parameters", parameters)
                .put("input", new JSONObject());
        send(new JSONObject().put("header", header).put("payload", payload));
    }

    /** Menghentikan tugas saat ini. Tunggu task-finished sebelum menutup koneksi. */
    public void finishRecognition() {
        if (taskId == null) {
            return;
        }
        engine.enableSendMediaStream(AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
        JSONObject payload = new JSONObject().put("input", new JSONObject());
        send(new JSONObject()
                .put("header", createHeader("finish-task"))
                .put("payload", payload));
    }

    public void close() {
        engine.enableSendMediaStream(AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
        engine.stopAudioCapture();
        engine.disconnect();
        AoqClientEngine.destroy();
    }

    private void handleServerEvent(AoqClientEngine.AoqDataMsg msg) {
        if (msg == null || msg.data == null) {
            return;
        }
        JSONObject event = new JSONObject(new String(msg.data, StandardCharsets.UTF_8));
        JSONObject header = event.optJSONObject("header");
        if (header == null) {
            return;
        }

        String eventName = header.optString("event", "");
        if ("task-started".equals(eventName)) {
            taskStarted = true;
            engine.enableSendMediaStream(
                    AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, true);
        } else if ("result-generated".equals(eventName)) {
            handleRecognitionResult(event);
        } else if ("task-finished".equals(eventName)) {
            resetTaskState();
            resultListener.onTaskFinished();
        } else if ("task-failed".equals(eventName)) {
            String message = header.optString("error_message", "Recognition failed");
            resetTaskState();
            resultListener.onError(message);
        }
    }

    private void handleRecognitionResult(JSONObject event) {
        JSONObject payload = event.optJSONObject("payload");
        JSONObject output = payload == null ? null : payload.optJSONObject("output");
        JSONObject sentence = output == null ? null : output.optJSONObject("sentence");
        if (sentence == null || sentence.optBoolean("heartbeat", false)) {
            return;
        }
        String text = sentence.optString("text", "");
        if (!text.isEmpty()) {
            resultListener.onResult(text, sentence.optBoolean("sentence_end", false));
        }
    }

    private void resetTaskState() {
        engine.enableSendMediaStream(AoqClientEngine.AoqTrackType.AoqTrackTypeAudio, false);
        taskStarted = false;
        taskId = null;
    }

    private JSONObject createHeader(String action) {
        return new JSONObject()
                .put("action", action)
                .put("task_id", taskId)
                .put("streaming", "duplex");
    }

    private void send(JSONObject event) {
        AoqClientEngine.AoqDataMsg msg = new AoqClientEngine.AoqDataMsg();
        msg.data = event.toString().getBytes(StandardCharsets.UTF_8);
        engine.sendDataMsg(msg);
    }

    private static void addTrack(AoqClientEngine.AoqConnectConfig config, boolean publish,
                                 AoqClientEngine.AoqTrackType type) {
        AoqClientEngine.AoqTrackParam track = new AoqClientEngine.AoqTrackParam();
        track.trackType = type;
        if (publish) {
            config.publishTracks.add(track);
        } else {
            config.subscribeTracks.add(track);
        }
    }

    /** Memetakan respons token AppServer ke konfigurasi koneksi SDK. */
    public static AoqClientEngine.AoqConnectConfig parseConnectConfig(String responseText) {
        JSONObject response = new JSONObject(responseText);
        AoqClientEngine.AoqConnectConfig config = new AoqClientEngine.AoqConnectConfig();
        config.token = response.optString("aoqTokenForClient", "");
        config.sid = response.optString("sid", "");
        config.certFingerprint = response.optString("clientRelayCertFingerprint", "");

        JSONArray endpoints = response.optJSONArray("clientRelayEndpoints");
        if (endpoints != null) {
            for (int i = 0; i < endpoints.length(); i++) {
                JSONObject item = endpoints.optJSONObject(i);
                if (item == null) {
                    continue;
                }
                AoqClientEngine.AoqRelayEndpoint endpoint =
                        new AoqClientEngine.AoqRelayEndpoint();
                endpoint.routeIndex = item.has("route_index")
                        ? item.optInt("route_index", i) : i;
                endpoint.endpoint = item.optString("endpoint", "");
                endpoint.port = item.optInt("port", 0);
                config.relayEndpoints.add(endpoint);
            }
        }

        JSONObject extraInfo = response.optJSONObject("extraInfo");
        config.workspaceIdHash = extraInfo == null
                ? "" : extraInfo.optString("workspaceIdHash", "");
        return config;
    }
}

Contoh penggunaan

Teruskan respons token dari server aplikasi ke parseConnectConfig dan buat klien. Tugas pengenalan pertama dimulai secara otomatis setelah koneksi ditetapkan. Tombol stop hanya mengakhiri tugas saat ini. Lepaskan koneksi dan resource lokal ketika halaman dihancurkan.

private AsrClient client;

void startRecognition(Context context, String tokenResponseText) {
    AoqClientEngine.AoqConnectConfig config =
            AsrClient.parseConnectConfig(tokenResponseText);

    client = new AsrClient(context, config, new AsrClient.ResultListener() {
        @Override
        public void onResult(String text, boolean sentenceEnd) {
            // Perbarui UI dengan kalimat parsial atau akhir.
        }

        @Override
        public void onTaskFinished() {
            // Aktifkan tombol mulai atau panggil beginRecognition() untuk tugas lain.
        }

        @Override
        public void onError(String message) {
            // Tampilkan atau catat error.
        }
    });
}

void onStopButtonClick() {
    // Akhiri tugas dan pertahankan koneksi AOQ terbuka hingga task-finished tiba.
    client.finishRecognition();
}

void onPageDestroyed() {
    // Lepaskan resource lokal hanya saat halaman ditutup.
    client.close();
}

Jalankan dan verifikasi

  1. Jalankan server aplikasi. Pastikan permintaan token mengembalikan HTTP 200 dan mencakup sid, aoqTokenForClient, clientRelayEndpoints, clientRelayCertFingerprint, dan extraInfo.workspaceIdHash.
  2. Instal dan jalankan aplikasi di perangkat Android, berikan akses mikrofon, dan berbicara.
  3. Amati callback. Urutan event normal adalah:
task-started
result-generated (sentence_end=false)
result-generated (sentence_end=true)
task-finished

Transkrip parsial dikembalikan selama Anda berbicara. Setelah finishRecognition dipanggil, transkrip akhir untuk kalimat saat ini dan task-finished dikembalikan. Jangan putuskan koneksi segera setelah finish-task dikirim.

Skenario umum

Beberapa tugas pengenalan melalui satu koneksi

Setelah task-finished diterima, panggil beginRecognition untuk memulai tugas lain melalui koneksi AOQ yang sama. Setiap tugas memerlukan task_id baru. Anda tidak perlu meminta token lain atau terhubung ulang selama koneksi tetap aktif. Jika koneksi ditutup, peroleh kredensial koneksi baru.

Pengenalan latar belakang di Android

Di Android 10 atau lebih baru, gunakan layanan foreground dengan foregroundServiceType=microphone untuk melanjutkan tangkapan mikrofon saat aplikasi berada di latar belakang. Mulai layanan saat aplikasi masih terlihat oleh pengguna.

Troubleshooting

Masalah

Solusi

Koneksi gagal

Pastikan token valid, titik akhir sesuai dengan wilayah aplikasi, dan server aplikasi meneruskan Alamat IP publik aktual perangkat klien. Jangan gunakan kembali token setelah koneksi ditutup.

Tugas dimulai tetapi tidak ada transkrip yang dikembalikan

Aktifkan pengiriman Audio-track hanya setelah task-started diterima. Periksa format input, laju sampel, dan parameter lainnya terhadap Event klien untuk model tersebut.

Transkrip akhir tidak dikembalikan

Nonaktifkan pengiriman Audio-track sebelum mengirim finish-task. Tunggu event result-generated akhir dan task-finished alih-alih memutuskan koneksi segera.

SDK Android gagal dimuat

Pastikan AAR disertakan sebagai dependensi dan aplikasi mengemas ABI yang didukung SDK: armeabi-v7a atau arm64-v8a.

Tugas berikutnya melalui koneksi yang sama ditolak

Pastikan task-finished telah diterima untuk tugas sebelumnya dan hasilkan task_id baru untuk event run-task berikutnya.

Topik terkait

Untuk semua parameter, field event, dan API untuk platform lain, lihat: