Gunakan SSML untuk mengatur karakteristik suara seperti kecepatan, nada, dan volume, serta LaTeX untuk membaca rumus dalam bahasa Mandarin. Pelajari batasan, contoh API, tag, dan simbol yang didukung.
Pengenalan fitur
SSML adalah bahasa markup sintesis ucapan berbasis XML. SSML mengatur karakteristik suara seperti jenis suara, kecepatan, nada, dan volume, mengontrol jeda, menentukan pelafalan dan cara baca, serta menambahkan musik latar dan efek suara. Fitur LaTeX CosyVoice mengubah rumus matematika dalam teks menjadi ucapan bahasa Mandarin.
Gunakan fitur ini untuk buku audio, pengumuman layanan pelanggan, pelafalan multibahasa, dan pendidikan daring. Model, suara, dan API untuk setiap fitur dijelaskan di bawah. Untuk memilih model, lihat Sintesis ucapan.
Batasan penggunaan
SSML
-
Model yang didukung:
qwen-audio-3.1-tts-plus,qwen-audio-3.1-tts-flash,qwen-audio-3.0-tts-flash,qwen-audio-3.0-tts-plus,cosyvoice-v3.5-flash,cosyvoice-v3.5-plus,cosyvoice-v3-flash,cosyvoice-v3-plus,cosyvoice-v2 -
Suara: Hanya suara hasil kloning dan suara sistem yang ditandai mendukung SSML dalam daftar suara Qwen-Audio-TTS atau daftar suara CosyVoice yang didukung.
-
API:
- Java SDK (versi 2.20.3 atau lebih baru): panggilan non-streaming dan streaming unidireksional
- Python SDK (versi 1.23.4 atau lebih baru): panggilan non-streaming dan streaming unidireksional
- WebSocket API: atur parameter
enable_ssmlketrue, dan kirim satu event continue-task
LaTeX
-
Model yang didukung:
cosyvoice-v3.5-plus,cosyvoice-v3.5-flash,cosyvoice-v3-plus,cosyvoice-v3-flash,cosyvoice-v2 -
Bahasa: hanya bahasa Mandarin.
-
Konten: gunakan tag dan simbol yang didukung. Blok kode matematika Markdown, seperti blok bertanda
math, tidak didukung. Masukkan hanya rumus di dalam pembatas. Teks lain dapat dibaca secara keliru.
Penggunaan
SSML
Saat menggunakan SSML, ikuti aturan berikut:
- Apit seluruh teks dengan
<speak></speak>. Beberapa elemen<speak>dapat digunakan berurutan, tetapi tidak dapat bersarang. - Escape karakter khusus XML di dalam tag:
"→",'→',&→&,<→<, dan>→>.
Mulai cepat
Contoh berikut menggunakan SSML untuk mengatur laju ucapan selama sintesis. Sebelum menjalankan kode, lengkapi prasyarat berikut:
- Dapatkan Kunci API
- Instal DashScope SDK (Python 1.23.4 atau lebih baru, Java 2.20.3 atau lebih baru). Untuk detailnya, lihat 安装SDK.
PentingModel cosyvoice-v3.5-plus dan cosyvoice-v3.5-flash saat ini hanya tersedia di wilayah Beijing dan dirancang khusus untuk skenario kloning suara (tidak tersedia voice preset). Sebelum menggunakan model ini, buat voice target dengan mengikuti petunjuk di Kloning suara.
Java SDK
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.utils.Constants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Deskripsi fitur SSML:
* 1. Hanya panggilan non-streaming dan panggilan streaming unidireksional yang mendukung fitur SSML
* Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
*/
public class Main {
private static String model = "cosyvoice-v3-flash";
private static String voice = "longanyang";
public static void main(String[] args) {
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.exit(0);
}
public static void streamAudioDataToSpeaker() {
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model)
.voice(voice)
.build();
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
ByteBuffer audio = null;
try {
// Panggilan non-streaming, diblokir hingga audio dikembalikan
// Karakter khusus perlu di-escape
audio = synthesizer.call("<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Tutup koneksi WebSocket ketika tugas selesai
synthesizer.getDuplexApi().close(1000, "bye");
}
if (audio != null) {
// Simpan data audio ke file lokal "output.mp3"
File file = new File("output.mp3");
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(audio.array());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// Transmisi teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu penyiapan koneksi
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", latensi paket pertama (ms): "
+ synthesizer.getFirstPackageDelay());
}
}
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisAudioFormat;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.utils.Constants;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* Deskripsi fitur SSML:
* 1. Hanya panggilan non-streaming dan panggilan streaming unidireksional yang mendukung fitur SSML
* Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
*/
public class Main {
private static String model = "cosyvoice-v3-flash";
private static String voice = "longanyang";
public static void main(String[] args) {
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.out.println("Audio telah disimpan ke file output.mp3");
System.exit(0);
}
public static void streamAudioDataToSpeaker() {
CountDownLatch latch = new CountDownLatch(1);
final FileOutputStream[] fileOutputStream = new FileOutputStream[1];
try {
fileOutputStream[0] = new FileOutputStream("output.mp3");
} catch (IOException e) {
System.err.println("Gagal membuat file output: " + e.getMessage());
return;
}
// Implementasikan antarmuka ResultCallback
ResultCallback<SpeechSynthesisResult> callback = new ResultCallback<SpeechSynthesisResult>() {
@Override
public void onEvent(SpeechSynthesisResult result) {
if (result.getAudioFrame() != null) {
// Tulis data audio ke file lokal
try {
byte[] audioData = result.getAudioFrame().array();
fileOutputStream[0].write(audioData);
fileOutputStream[0].flush();
} catch (IOException e) {
System.err.println("Gagal menulis data audio: " + e.getMessage());
}
}
}
@Override
public void onComplete() {
System.out.println("Menerima Complete, sintesis ucapan selesai");
closeFileOutputStream(fileOutputStream[0]);
latch.countDown();
}
@Override
public void onError(Exception e) {
System.out.println("Terjadi kesalahan: " + e.toString());
closeFileOutputStream(fileOutputStream[0]);
latch.countDown();
}
};
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model)
.voice(voice)
.format(SpeechSynthesisAudioFormat.MP3_22050HZ_MONO_256KBPS)
.build();
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, callback);
try {
// Panggilan streaming unidireksional, langsung mengembalikan null (hasil aktual dikirimkan secara asinkron melalui antarmuka callback), ambil audio biner secara real-time dari metode onEvent pada antarmuka callback
// Karakter khusus perlu di-escape
synthesizer.call("<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>");
// Tunggu hingga sintesis selesai
latch.await();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Tutup koneksi WebSocket setelah tugas selesai
try {
synthesizer.getDuplexApi().close(1000, "bye");
} catch (Exception e) {
System.err.println("Gagal menutup koneksi WebSocket: " + e.getMessage());
}
// Pastikan aliran file ditutup
closeFileOutputStream(fileOutputStream[0]);
}
// Transmisi teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu penyiapan koneksi
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", latensi paket pertama (ms): "
+ synthesizer.getFirstPackageDelay());
}
private static void closeFileOutputStream(FileOutputStream fileOutputStream) {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
System.err.println("Gagal menutup aliran file: " + e.getMessage());
}
}
}
Python SDK
# coding=utf-8
# Deskripsi fitur SSML:
# 1. Hanya panggilan non-streaming dan panggilan streaming unidireksional yang mendukung fitur SSML
# Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
import dashscope
from dashscope.audio.tts_v2 import *
import os
# Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
# Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-flash"
# Voice
voice = "longanyang"
# Buat instance SpeechSynthesizer dan masukkan parameter permintaan seperti model dan voice di konstruktor
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# Panggilan non-streaming, diblokir hingga audio dikembalikan
# Karakter khusus perlu di-escape
audio = synthesizer.call("<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>")
# Simpan audio ke file lokal
with open('output.mp3', 'wb') as f:
f.write(audio)
# Transmisi teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu penyiapan koneksi
print('[Metric] requestId: {}, latensi paket pertama: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))
# coding=utf-8
# Deskripsi fitur SSML:
# 1. Hanya panggilan non-streaming dan panggilan streaming unidireksional yang mendukung fitur SSML
# Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
import dashscope
from dashscope.audio.tts_v2 import *
import os
from datetime import datetime
def get_timestamp():
now = datetime.now()
formatted_timestamp = now.strftime("[%Y-%m-%d %H:%M:%S.%f]")
return formatted_timestamp
# Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
# Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-flash"
# Voice
voice = "longanyang"
# Definisikan antarmuka callback
class Callback(ResultCallback):
_player = None
_stream = None
def on_open(self):
# Buka file output untuk menulis data audio
self.file = open("output.mp3", "wb")
print("Koneksi dibentuk: " + get_timestamp())
def on_complete(self):
print("Sintesis ucapan selesai, semua hasil telah diterima: " + get_timestamp())
if hasattr(self, 'file') and self.file:
self.file.close()
self
# Transmisi teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu penyiapan koneksi
print('[Metric] requestId: {}, latensi paket pertama: {} ms'.format(
self.synthesizer.get_last_request_id(),
self.synthesizer.get_first_package_delay()))
def on_error(self, message: str):
print(f"Terjadi kesalahan sintesis ucapan: {message}")
if hasattr(self, 'file') and self.file:
self.file.close()
def on_close(self):
print("Koneksi ditutup: " + get_timestamp())
if hasattr(self, 'file') and self.file:
self.file.close()
def on_event(self, message):
pass
def on_data(self, data: bytes) -> None:
print(get_timestamp() + " Panjang audio biner: " + str(len(data)))
# Tulis data audio ke file
self.file.write(data)
callback = Callback()
# Buat instance SpeechSynthesizer dan masukkan parameter permintaan seperti model dan voice di konstruktor
synthesizer = SpeechSynthesizer(
model=model,
voice=voice,
callback=callback,
)
# Tetapkan instance synthesizer ke callback untuk digunakan di on_complete
callback.synthesizer = synthesizer
# Panggilan streaming unidireksional, kirim teks untuk sintesis, ambil audio biner secara real-time dari metode on_data pada antarmuka callback
# Karakter khusus perlu di-escape
synthesizer.call("<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>")
WebSocket API
Java
Untuk pengembangan Java, gunakan Java DashScope SDK. Untuk detailnya, lihat Java SDK.
Contoh WebSocket Java ini memerlukan dependensi berikut:
Java-WebSocketjackson-databind
Kelola dependensi ini dengan Maven atau Gradle:
<dependencies>
<!-- WebSocket Client -->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.3</version>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
dependencies {
// WebSocket Client
implementation 'org.java-websocket:Java-WebSocket:1.5.3'
// JSON Processing
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
}
Kode Java:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.*;
/**
* Deskripsi fitur SSML:
* 1. Saat mengirim perintah run-task, atur parameter enable_ssml ke true untuk mengaktifkan dukungan SSML
* 2. Kirim teks yang berisi SSML melalui perintah continue-task, dan hanya satu perintah continue-task yang diizinkan
* Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
*/
public class TTSWebSocketClient extends WebSocketClient {
private final String taskId = UUID.randomUUID().toString();
private final String outputFile = "output_" + System.currentTimeMillis() + ".mp3";
private boolean taskFinished = false;
public TTSWebSocketClient(URI serverUri, Map<String, String> headers) {
super(serverUri, headers);
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
System.out.println("Koneksi dibentuk");
// Kirim perintah run-task
// Jika enable_ssml diatur ke true, hanya satu perintah continue-task yang diizinkan; jika tidak, kesalahan "Text request limit violated, expected 1." akan dikembalikan
String runTaskCommand = "{ \"header\": { \"action\": \"run-task\", \"task_id\": \"" + taskId + "\", \"streaming\": \"duplex\" }, \"payload\": { \"task_group\": \"audio\", \"task\": \"tts\", \"function\": \"SpeechSynthesizer\", \"model\": \"cosyvoice-v3-flash\", \"parameters\": { \"text_type\": \"PlainText\", \"voice\": \"longanyang\", \"format\": \"mp3\", \"sample_rate\": 22050, \"volume\": 50, \"rate\": 1, \"pitch\": 1, \"enable_ssml\": true }, \"input\": {} }}";
send(runTaskCommand);
}
@Override
public void onMessage(String message) {
System.out.println("Menerima pesan dari server: " + message);
try {
// Uraikan pesan JSON
Map<String, Object> messageMap = new ObjectMapper().readValue(message, Map.class);
if (messageMap.containsKey("header")) {
Map<String, Object> header = (Map<String, Object>) messageMap.get("header");
if (header.containsKey("event")) {
String event = (String) header.get("event");
if ("task-started".equals(event)) {
System.out.println("Menerima event task-started dari server");
// Kirim perintah continue-task. Saat menggunakan SSML, perintah ini hanya dapat dikirim sekali
// Karakter khusus perlu di-escape
sendContinueTask("<speak rate=\\\"2\\\">Laju bicara saya lebih cepat daripada orang biasa.</speak>");
// Kirim perintah finish-task
sendFinishTask();
} else if ("task-finished".equals(event)) {
System.out.println("Menerima event task-finished dari server");
taskFinished = true;
closeConnection();
} else if ("task-failed".equals(event)) {
System.out.println("Tugas gagal: " + message);
closeConnection();
}
}
}
} catch (Exception e) {
System.err.println("Terjadi kesalahan: " + e.getMessage());
}
}
@Override
public void onMessage(ByteBuffer message) {
System.out.println("Menerima data audio biner, ukuran: " + message.remaining());
try (FileOutputStream fos = new FileOutputStream(outputFile, true)) {
byte[] buffer = new byte[message.remaining()];
message.get(buffer);
fos.write(buffer);
System.out.println("Data audio ditulis ke file lokal " + outputFile);
} catch (IOException e) {
System.err.println("Gagal menulis data audio ke file lokal: " + e.getMessage());
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("Koneksi ditutup: " + reason + " (" + code + ")");
}
@Override
public void onError(Exception ex) {
System.err.println("Kesalahan: " + ex.getMessage());
ex.printStackTrace();
}
private void sendContinueTask(String text) {
String command = "{ \"header\": { \"action\": \"continue-task\", \"task_id\": \"" + taskId + "\", \"streaming\": \"duplex\" }, \"payload\": { \"input\": { \"text\": \"" + text + "\" } }}";
send(command);
}
private void sendFinishTask() {
String command = "{ \"header\": { \"action\": \"finish-task\", \"task_id\": \"" + taskId + "\", \"streaming\": \"duplex\" }, \"payload\": { \"input\": {} }}";
send(command);
}
private void closeConnection() {
if (!isClosed()) {
close();
}
}
public static void main(String[] args) {
try {
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: String apiKey = "sk-xxx"
String apiKey = System.getenv("DASHSCOPE_API_KEY");
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("Harap atur variabel lingkungan DASHSCOPE_API_KEY");
return;
}
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "bearer " + apiKey);
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
TTSWebSocketClient client = new TTSWebSocketClient(new URI("wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference/"), headers);
client.connect();
while (!client.isClosed() && !client.taskFinished) {
Thread.sleep(1000);
}
} catch (Exception e) {
System.err.println("Gagal terhubung ke layanan WebSocket: " + e.getMessage());
e.printStackTrace();
}
}
}
Python
Untuk pengembangan Python, gunakan Python DashScope SDK. Untuk detailnya, lihat Python SDK.
Berikut adalah contoh WebSocket Python. Sebelum menjalankannya, instal dependensi yang diperlukan:
pip uninstall websocket-client
pip uninstall websocket
pip install websocket-client
PentingFile contoh Python tidak boleh diberi nama websocket.py karena nama ini menyebabkan konflik penamaan yang menghasilkan kesalahan (AttributeError: module 'websocket' has no attribute 'WebSocketApp'. Did you mean: 'WebSocket'?).
# Deskripsi fitur SSML:
# 1. Saat mengirim perintah run-task, atur parameter enable_ssml ke true untuk mengaktifkan dukungan SSML
# 2. Kirim teks yang berisi SSML melalui perintah continue-task, dan hanya satu perintah continue-task yang diizinkan
# Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
import websocket
import json
import uuid
import os
import time
class TTSClient:
def __init__(self, api_key, uri):
"""
Menginisialisasi instans TTSClient
Parameter:
api_key (str): Kunci API untuk otentikasi
uri (str): Alamat layanan WebSocket
"""
self.api_key = api_key # Ganti dengan Kunci API Anda
self.uri = uri # Ganti dengan alamat WebSocket Anda
self.task_id = str(uuid.uuid4()) # Membuat ID tugas yang unik
self.output_file = f"output_{int(time.time())}.mp3" # Jalur file audio output
self.ws = None # Instans WebSocketApp
self.task_started = False # Apakah task-started telah diterima
self.task_finished = False # Apakah task-finished / task-failed telah diterima
def on_open(self, ws):
"""
Callback saat koneksi WebSocket dibuat
Mengirim perintah run-task untuk memulai tugas sintesis suara
"""
print("WebSocket terhubung")
# Membuat perintah run-task
run_task_cmd = {
"header": {
"action": "run-task",
"task_id": self.task_id,
"streaming": "duplex"
},
"payload": {
"task_group": "audio",
"task": "tts",
"function": "SpeechSynthesizer",
"model": "cosyvoice-v3-flash",
"parameters": {
"text_type": "PlainText",
"voice": "longanyang",
"format": "mp3",
"sample_rate": 22050,
"volume": 50,
"rate": 1,
"pitch": 1,
# Jika enable_ssml diatur ke True, hanya satu perintah continue-task yang diizinkan; jika tidak, error "Text request limit violated, expected 1." akan dikembalikan
"enable_ssml": True
},
"input": {}
}
}
# Mengirim perintah run-task
ws.send(json.dumps(run_task_cmd))
print("perintah run-task terkirim")
def on_message(self, ws, message):
"""
Callback saat pesan diterima
Menangani pesan teks dan biner secara terpisah
"""
if isinstance(message, str):
# Memproses pesan teks JSON
try:
msg_json = json.loads(message)
print(f"Menerima pesan JSON: {msg_json}")
if "header" in msg_json:
header = msg_json["header"]
if "event" in header:
event = header["event"]
if event == "task-started":
print("Tugas dimulai")
self.task_started = True
# Mengirim perintah continue-task. Saat menggunakan SSML, perintah ini hanya dapat dikirim sekali
# Karakter khusus perlu di-escape
self.send_continue_task("<speak rate=\"2\">My speaking rate is faster than a normal person's.</speak>")
# Mengirim finish-task setelah continue-task dikirim
self.send_finish_task()
elif event == "task-finished":
print("Tugas selesai")
self.task_finished = True
self.close(ws)
elif event == "task-failed":
error_msg = msg_json.get("error_message", "Error tidak diketahui")
print(f"Tugas gagal: {error_msg}")
self.task_finished = True
self.close(ws)
except json.JSONDecodeError as e:
print(f"Penguraian JSON gagal: {e}")
else:
# Memproses pesan biner (data audio)
print(f"Menerima pesan biner, ukuran: {len(message)} byte")
with open(self.output_file, "ab") as f:
f.write(message)
print(f"Data audio ditulis ke file lokal {self.output_file}")
def on_error(self, ws, error):
"""Callback saat terjadi error"""
print(f"Error WebSocket: {error}")
def on_close(self, ws, close_status_code, close_msg):
"""Callback saat koneksi ditutup"""
print(f"WebSocket ditutup: {close_msg} ({close_status_code})")
def send_continue_task(self, text):
"""Mengirim perintah continue-task dengan konten teks untuk disintesis"""
cmd = {
"header": {
"action": "continue-task",
"task_id": self.task_id,
"streaming": "duplex"
},
"payload": {
"input": {
"text": text
}
}
}
self.ws.send(json.dumps(cmd))
print(f"perintah continue-task terkirim, konten teks: {text}")
def send_finish_task(self):
"""Mengirim perintah finish-task untuk mengakhiri tugas sintesis suara"""
cmd = {
"header": {
"action": "finish-task",
"task_id": self.task_id,
"streaming": "duplex"
},
"payload": {
"input": {}
}
}
self.ws.send(json.dumps(cmd))
print("perintah finish-task terkirim")
def close(self, ws):
"""Menutup koneksi secara aktif"""
if ws and ws.sock and ws.sock.connected:
ws.close()
print("Koneksi ditutup secara aktif")
def run(self):
"""Memulai klien WebSocket"""
# Mengatur header permintaan (otentikasi)
header = {
"Authorization": f"bearer {self.api_key}",
"X-DashScope-DataInspection": "enable"
}
# Membuat instans WebSocketApp
self.ws = websocket.WebSocketApp(
self.uri,
header=header,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close
)
print("Mendengarkan pesan WebSocket...")
self.ws.run_forever() # Memulai pendengar koneksi persisten
# Contoh penggunaan
if __name__ == "__main__":
# Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
# Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: API_KEY = "sk-xxx"
API_KEY = os.environ.get("DASHSCOPE_API_KEY")
# URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja Anda yang sebenarnya. URL bervariasi menurut wilayah.
SERVER_URI = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference/"
client = TTSClient(API_KEY, SERVER_URI)
client.run()
Go
// Deskripsi fitur SSML:
// 1. Saat mengirim perintah run-task, atur parameter enable_ssml ke true untuk mengaktifkan dukungan SSML
// 2. Kirim teks yang berisi SSML melalui perintah continue-task, dan hanya satu perintah continue-task yang diizinkan
// Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"time"
"github.com/google/uuid"
"github.com/gorilla/websocket"
)
const (
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
wsURL = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference/"
outputFile = "output.mp3"
)
func main() {
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: apiKey := "sk-xxx"
apiKey := os.Getenv("DASHSCOPE_API_KEY")
// Hapus file output
os.Remove(outputFile)
os.Create(outputFile)
// Hubungkan ke WebSocket
header := make(http.Header)
header.Add("X-DashScope-DataInspection", "enable")
header.Add("Authorization", fmt.Sprintf("bearer %s", apiKey))
conn, resp, err := websocket.DefaultDialer.Dial(wsURL, header)
if err != nil {
if resp != nil {
fmt.Printf("Koneksi gagal, kode status HTTP: %d\n", resp.StatusCode)
}
fmt.Println("Koneksi gagal:", err)
return
}
defer conn.Close()
// Hasilkan ID tugas
taskID := uuid.New().String()
fmt.Printf("ID tugas yang dihasilkan: %s\n", taskID)
// Kirim perintah run-task
runTaskCmd := map[string]interface{}{
"header": map[string]interface{}{
"action": "run-task",
"task_id": taskID,
"streaming": "duplex",
},
"payload": map[string]interface{}{
"task_group": "audio",
"task": "tts",
"function": "SpeechSynthesizer",
"model": "cosyvoice-v3-flash",
"parameters": map[string]interface{}{
"text_type": "PlainText",
"voice": "longanyang",
"format": "mp3",
"sample_rate": 22050,
"volume": 50,
"rate": 1,
"pitch": 1,
// Jika enable_ssml diatur ke true, hanya satu perintah continue-task yang diizinkan; jika tidak, kesalahan "Text request limit violated, expected 1." akan dikembalikan
"enable_ssml": true,
},
"input": map[string]interface{}{},
},
}
runTaskJSON, _ := json.Marshal(runTaskCmd)
fmt.Printf("Mengirim perintah run-task: %s\n", string(runTaskJSON))
err = conn.WriteMessage(websocket.TextMessage, runTaskJSON)
if err != nil {
fmt.Println("Gagal mengirim run-task:", err)
return
}
textSent := false
// Proses pesan
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
fmt.Println("Gagal membaca pesan:", err)
break
}
// Proses pesan biner
if messageType == websocket.BinaryMessage {
fmt.Printf("Menerima pesan biner, panjang: %d\n", len(message))
file, _ := os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
file.Write(message)
file.Close()
continue
}
// Proses pesan teks
messageStr := string(message)
fmt.Printf("Menerima pesan teks: %s\n", strings.ReplaceAll(messageStr, "\n", ""))
// Penguraian JSON sederhana untuk mendapatkan jenis event
var msgMap map[string]interface{}
if json.Unmarshal(message, &msgMap) == nil {
if header, ok := msgMap["header"].(map[string]interface{}); ok {
if event, ok := header["event"].(string); ok {
fmt.Printf("Jenis event: %s\n", event)
switch event {
case "task-started":
fmt.Println("=== Menerima event task-started ===")
if !textSent {
// Kirim perintah continue-task. Saat menggunakan SSML, perintah ini hanya dapat dikirim sekali
continueTaskCmd := map[string]interface{}{
"header": map[string]interface{}{
"action": "continue-task",
"task_id": taskID,
"streaming": "duplex",
},
"payload": map[string]interface{}{
"input": map[string]interface{}{
// Karakter khusus perlu di-escape
"text": "<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>",
},
},
}
continueTaskJSON, _ := json.Marshal(continueTaskCmd)
fmt.Printf("Mengirim perintah continue-task: %s\n", string(continueTaskJSON))
err = conn.WriteMessage(websocket.TextMessage, continueTaskJSON)
if err != nil {
fmt.Println("Gagal mengirim continue-task:", err)
return
}
textSent = true
// Tunda sebelum mengirim finish-task
time.Sleep(500 * time.Millisecond)
// Kirim perintah finish-task
finishTaskCmd := map[string]interface{}{
"header": map[string]interface{}{
"action": "finish-task",
"task_id": taskID,
"streaming": "duplex",
},
"payload": map[string]interface{}{
"input": map[string]interface{}{},
},
}
finishTaskJSON, _ := json.Marshal(finishTaskCmd)
fmt.Printf("Mengirim perintah finish-task: %s\n", string(finishTaskJSON))
err = conn.WriteMessage(websocket.TextMessage, finishTaskJSON)
if err != nil {
fmt.Println("Gagal mengirim finish-task:", err)
return
}
}
case "task-finished":
fmt.Println("=== Tugas selesai ===")
return
case "task-failed":
fmt.Println("=== Tugas gagal ===")
if header["error_message"] != nil {
fmt.Printf("Pesan kesalahan: %s\n", header["error_message"])
}
return
case "result-generated":
fmt.Println("Menerima event result-generated")
}
}
}
}
}
}
C#
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
// Deskripsi fitur SSML:
// 1. Saat mengirim perintah run-task, atur parameter enable_ssml ke true untuk mengaktifkan dukungan SSML
// 2. Kirim teks yang berisi SSML melalui perintah continue-task, dan hanya satu perintah continue-task yang diizinkan
// Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
class Program {
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: private static readonly string ApiKey = "sk-xxx"
private static readonly string ApiKey = Environment.GetEnvironmentVariable("DASHSCOPE_API_KEY") ?? throw new InvalidOperationException("Variabel lingkungan DASHSCOPE_API_KEY belum diatur.");
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
private const string WebSocketUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference/";
// Jalur file output
private const string OutputFilePath = "output.mp3";
// Klien WebSocket
private static ClientWebSocket _webSocket = new ClientWebSocket();
// Sumber token pembatalan
private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
// ID tugas
private static string? _taskId;
// Apakah tugas telah dimulai
private static TaskCompletionSource<bool> _taskStartedTcs = new TaskCompletionSource<bool>();
static async Task Main(string[] args) {
try {
// Hapus file output
ClearOutputFile(OutputFilePath);
// Hubungkan ke layanan WebSocket
await ConnectToWebSocketAsync(WebSocketUrl);
// Mulai tugas penerimaan pesan
Task receiveTask = ReceiveMessagesAsync();
// Kirim perintah run-task
_taskId = GenerateTaskId();
await SendRunTaskCommandAsync(_taskId);
// Tunggu event task-started
await _taskStartedTcs.Task;
// Kirim perintah continue-task. Saat menggunakan SSML, perintah ini hanya dapat dikirim sekali
// Karakter khusus perlu di-escape
await SendContinueTaskCommandAsync("<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>");
// Kirim perintah finish-task
await SendFinishTaskCommandAsync(_taskId);
// Tunggu hingga tugas penerimaan selesai
await receiveTask;
Console.WriteLine("Tugas selesai, koneksi ditutup.");
} catch (OperationCanceledException) {
Console.WriteLine("Tugas dibatalkan.");
} catch (Exception ex) {
Console.WriteLine($"Terjadi kesalahan: {ex.Message}");
} finally {
_cancellationTokenSource.Cancel();
_webSocket.Dispose();
}
}
private static void ClearOutputFile(string filePath) {
if (File.Exists(filePath)) {
File.WriteAllText(filePath, string.Empty);
Console.WriteLine("File output dihapus.");
} else {
Console.WriteLine("File output tidak ada, tidak perlu dihapus.");
}
}
private static async Task ConnectToWebSocketAsync(string url) {
var uri = new Uri(url);
if (_webSocket.State == WebSocketState.Connecting || _webSocket.State == WebSocketState.Open) {
return;
}
// Atur header koneksi WebSocket
_webSocket.Options.SetRequestHeader("Authorization", $"bearer {ApiKey}");
_webSocket.Options.SetRequestHeader("X-DashScope-DataInspection", "enable");
try {
await _webSocket.ConnectAsync(uri, _cancellationTokenSource.Token);
Console.WriteLine("Berhasil terhubung ke layanan WebSocket.");
} catch (OperationCanceledException) {
Console.WriteLine("Koneksi WebSocket dibatalkan.");
} catch (Exception ex) {
Console.WriteLine($"Koneksi WebSocket gagal: {ex.Message}");
throw;
}
}
private static async Task SendRunTaskCommandAsync(string taskId) {
var command = CreateCommand("run-task", taskId, "duplex", new {
task_group = "audio",
task = "tts",
function = "SpeechSynthesizer",
model = "cosyvoice-v3-flash",
parameters = new
{
text_type = "PlainText",
voice = "longanyang",
format = "mp3",
sample_rate = 22050,
volume = 50,
rate = 1,
pitch = 1,
// Jika enable_ssml diatur ke true, hanya satu perintah continue-task yang diizinkan; jika tidak, kesalahan "Text request limit violated, expected 1." akan dikembalikan
enable_ssml = true
},
input = new { }
});
await SendJsonMessageAsync(command);
Console.WriteLine("Perintah run-task dikirim.");
}
private static async Task SendContinueTaskCommandAsync(string text) {
if (_taskId == null) {
throw new InvalidOperationException("ID tugas belum diinisialisasi.");
}
var command = CreateCommand("continue-task", _taskId, "duplex", new {
input = new {
text
}
});
await SendJsonMessageAsync(command);
Console.WriteLine("Perintah continue-task dikirim.");
}
private static async Task SendFinishTaskCommandAsync(string taskId) {
var command = CreateCommand("finish-task", taskId, "duplex", new {
input = new { }
});
await SendJsonMessageAsync(command);
Console.WriteLine("Perintah finish-task dikirim.");
}
private static async Task SendJsonMessageAsync(string message) {
var buffer = Encoding.UTF8.GetBytes(message);
try {
await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, _cancellationTokenSource.Token);
} catch (OperationCanceledException) {
Console.WriteLine("Pengiriman pesan dibatalkan.");
}
}
private static async Task ReceiveMessagesAsync() {
while (_webSocket.State == WebSocketState.Open) {
var response = await ReceiveMessageAsync();
if (response != null) {
var eventStr = response.RootElement.GetProperty("header").GetProperty("event").GetString();
switch (eventStr) {
case "task-started":
Console.WriteLine("Tugas dimulai.");
_taskStartedTcs.TrySetResult(true);
break;
case "task-finished":
Console.WriteLine("Tugas selesai.");
_cancellationTokenSource.Cancel();
break;
case "task-failed":
Console.WriteLine("Tugas gagal: " + response.RootElement.GetProperty("header").GetProperty("error_message").GetString());
_cancellationTokenSource.Cancel();
break;
default:
// result-generated dapat ditangani di sini
break;
}
}
}
}
private static async Task<JsonDocument?> ReceiveMessageAsync() {
var buffer = new byte[1024 * 4];
var segment = new ArraySegment<byte>(buffer);
try {
WebSocketReceiveResult result = await _webSocket.ReceiveAsync(segment, _cancellationTokenSource.Token);
if (result.MessageType == WebSocketMessageType.Close) {
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", _cancellationTokenSource.Token);
return null;
}
if (result.MessageType == WebSocketMessageType.Binary) {
// Proses data biner
Console.WriteLine("Menerima data biner...");
// Simpan data biner ke file
using (var fileStream = new FileStream(OutputFilePath, FileMode.Append)) {
fileStream.Write(buffer, 0, result.Count);
}
return null;
}
string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
return JsonDocument.Parse(message);
} catch (OperationCanceledException) {
Console.WriteLine("Penerimaan pesan dibatalkan.");
return null;
}
}
private static string GenerateTaskId() {
return Guid.NewGuid().ToString("N").Substring(0, 32);
}
private static string CreateCommand(string action, string taskId, string streaming, object payload) {
var command = new {
header = new {
action,
task_id = taskId,
streaming
},
payload
};
return JsonSerializer.Serialize(command);
}
}
PHP
Struktur direktori kode contoh adalah:
my-php-project/
├── composer.json
├── vendor/
└── index.php
File composer.json berisi dependensi berikut. Sesuaikan nomor versi sesuai kebutuhan:
{
"require": {
"react/event-loop": "^1.3",
"react/socket": "^1.11",
"react/stream": "^1.2",
"react/http": "^1.1",
"ratchet/pawl": "^0.4"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
File index.php berisi kode berikut:
<!-- Deskripsi fitur SSML: -->
<!-- 1. Saat mengirim perintah run-task, atur parameter enable_ssml ke true untuk mengaktifkan dukungan SSML -->
<!-- 2. Kirim teks yang berisi SSML melalui perintah continue-task, dan hanya satu perintah continue-task yang diizinkan -->
<!-- 3. Hanya voice hasil kloning dari model cosyvoice-v3-flash, cosyvoice-v3-plus, dan cosyvoice-v2, serta voice sistem yang ditandai mendukung SSML dalam daftar voice, yang mendukung fitur SSML (misalnya, voice longanyang dari model cosyvoice-v3-flash) -->
<?php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\Client\Connector;
use React\EventLoop\Loop;
use React\Socket\Connector as SocketConnector;
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: $api_key = "sk-xxx"
$api_key = getenv("DASHSCOPE_API_KEY");
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
$websocket_url = 'wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference/'; // Alamat server WebSocket
$output_file = 'output.mp3'; // Jalur file output
$loop = Loop::get();
if (file_exists($output_file)) {
// Hapus isi file
file_put_contents($output_file, '');
}
// Buat konektor kustom
$socketConnector = new SocketConnector($loop, [
'tcp' => [
'bindto' => '0.0.0.0:0',
],
'tls' => [
'verify_peer' => false,
'verify_peer_name' => false,
],
]);
$connector = new Connector($loop, $socketConnector);
$headers = [
'Authorization' => 'bearer ' . $api_key,
'X-DashScope-DataInspection' => 'enable'
];
$connector($websocket_url, [], $headers)->then(function ($conn) use ($loop, $output_file) {
echo "Terhubung ke server WebSocket\n";
// Hasilkan ID tugas
$taskId = generateTaskId();
// Kirim perintah run-task
sendRunTaskMessage($conn, $taskId);
// Definisikan fungsi untuk mengirim perintah continue-task
$sendContinueTask = function() use ($conn, $loop, $taskId) {
// Kirim perintah continue-task. Saat menggunakan SSML, perintah ini hanya dapat dikirim sekali
$continueTaskMessage = json_encode([
"header" => [
"action" => "continue-task",
"task_id" => $taskId,
"streaming" => "duplex"
],
"payload" => [
"input" => [
// Karakter khusus perlu di-escape
"text" => "<speak rate=\"2\">Laju bicara saya lebih cepat daripada orang biasa.</speak>"
]
]
]);
$conn->send($continueTaskMessage);
// Kirim perintah finish-task
sendFinishTaskMessage($conn, $taskId);
};
// Bendera apakah event task-started telah diterima
$taskStarted = false;
// Dengarkan pesan
$conn->on('message', function($msg) use ($conn, $sendContinueTask, $loop, &$taskStarted, $taskId, $output_file) {
if ($msg->isBinary()) {
// Tulis data biner ke file lokal
file_put_contents($output_file, $msg->getPayload(), FILE_APPEND);
} else {
// Proses pesan non-biner
$response = json_decode($msg, true);
if (isset($response['header']['event'])) {
handleEvent($conn, $response, $sendContinueTask, $loop, $taskId, $taskStarted);
} else {
echo "Format pesan tidak dikenal\n";
}
}
});
// Dengarkan penutupan koneksi
$conn->on('close', function($code = null, $reason = null) {
echo "Koneksi ditutup\n";
if ($code !== null) {
echo "Kode tutup: " . $code . "\n";
}
if ($reason !== null) {
echo "Alasan tutup: " . $reason . "\n";
}
});
}, function ($e) {
echo "Tidak dapat terhubung: {$e->getMessage()}\n";
});
$loop->run();
/**
* Hasilkan ID tugas
* @return string
*/
function generateTaskId(): string {
return bin2hex(random_bytes(16));
}
/**
* Kirim perintah run-task
* @param $conn
* @param $taskId
*/
function sendRunTaskMessage($conn, $taskId) {
$runTaskMessage = json_encode([
"header" => [
"action" => "run-task",
"task_id" => $taskId,
"streaming" => "duplex"
],
"payload" => [
"task_group" => "audio",
"task" => "tts",
"function" => "SpeechSynthesizer",
"model" => "cosyvoice-v3-flash",
"parameters" => [
"text_type" => "PlainText",
"voice" => "longanyang",
"format" => "mp3",
"sample_rate" => 22050,
"volume" => 50,
"rate" => 1,
"pitch" => 1,
// Jika enable_ssml diatur ke true, hanya satu perintah continue-task yang diizinkan; jika tidak, kesalahan "Text request limit violated, expected 1." akan dikembalikan
"enable_ssml" => true
],
"input" => (object) []
]
]);
echo "Bersiap mengirim perintah run-task: " . $runTaskMessage . "\n";
$conn->send($runTaskMessage);
echo "Perintah run-task dikirim\n";
}
/**
* Baca file audio
* @param string $filePath
* @return bool|string
*/
function readAudioFile(string $filePath) {
$voiceData = file_get_contents($filePath);
if ($voiceData === false) {
echo "Tidak dapat membaca file audio\n";
}
return $voiceData;
}
/**
* Pisahkan data audio
* @param string $data
* @param int $chunkSize
* @return array
*/
function splitAudioData(string $data, int $chunkSize): array {
return str_split($data, $chunkSize);
}
/**
* Kirim perintah finish-task
* @param $conn
* @param $taskId
*/
function sendFinishTaskMessage($conn, $taskId) {
$finishTaskMessage = json_encode([
"header" => [
"action" => "finish-task",
"task_id" => $taskId,
"streaming" => "duplex"
],
"payload" => [
"input" => (object) []
]
]);
echo "Bersiap mengirim perintah finish-task: " . $finishTaskMessage . "\n";
$conn->send($finishTaskMessage);
echo "Perintah finish-task dikirim\n";
}
/**
* Tangani event
* @param $conn
* @param $response
* @param $sendContinueTask
* @param $loop
* @param $taskId
* @param $taskStarted
*/
function handleEvent($conn, $response, $sendContinueTask, $loop, $taskId, &$taskStarted) {
switch ($response['header']['event']) {
case 'task-started':
echo "Tugas dimulai, mengirim perintah continue-task...\n";
$taskStarted = true;
// Kirim perintah continue-task
$sendContinueTask();
break;
case 'result-generated':
// Abaikan event result-generated
break;
case 'task-finished':
echo "Tugas selesai\n";
$conn->close();
break;
case 'task-failed':
echo "Tugas gagal\n";
echo "Kode kesalahan: " . $response['header']['error_code'] . "\n";
echo "Pesan kesalahan: " . $response['header']['error_message'] . "\n";
$conn->close();
break;
case 'error':
echo "Kesalahan: " . $response['payload']['message'] . "\n";
break;
default:
echo "Event tidak dikenal: " . $response['header']['event'] . "\n";
break;
}
// Jika tugas selesai, tutup koneksi
if ($response['header']['event'] == 'task-finished') {
// Tunggu 1 detik untuk memastikan semua data telah ditransmisikan
$loop->addTimer(1, function() use ($conn) {
$conn->close();
echo "Klien menutup koneksi\n";
});
}
// Jika event task-started belum diterima, tutup koneksi
if (!$taskStarted && in_array($response['header']['event'], ['task-failed', 'error'])) {
$conn->close();
}
}
Node.js
Instal dependensi yang diperlukan:
npm install ws
npm install uuid
Kode contoh:
// Deskripsi fitur SSML:
// 1. Saat mengirim perintah run-task, atur parameter enable_ssml ke true untuk mengaktifkan dukungan SSML
// 2. Kirim teks yang berisi SSML melalui perintah continue-task, dan hanya satu perintah continue-task yang diizinkan
// Gunakan suara kloning atau preset yang mendukung SSML (misalnya longanyang untuk cosyvoice-v3-flash). Lihat model yang didukung di halaman ini.
import fs from 'fs';
import WebSocket from 'ws';
import { v4 as uuid } from 'uuid'; // Untuk menghasilkan UUID
// Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
// Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: const apiKey = "sk-xxx"
const apiKey = process.env.DASHSCOPE_API_KEY;
// URL wilayah Singapura. Ganti WorkspaceId dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayah.
const url = 'wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference/';
// Jalur file output
const outputFilePath = 'output.mp3';
// Hapus file output
fs.writeFileSync(outputFilePath, '');
// Buat klien WebSocket
const ws = new WebSocket(url, {
headers: {
Authorization: `bearer ${apiKey}`,
'X-DashScope-DataInspection': 'enable'
}
});
let taskStarted = false;
let taskId = uuid();
ws.on('open', () => {
console.log('Terhubung ke server WebSocket');
// Kirim perintah run-task
const runTaskMessage = JSON.stringify({
header: {
action: 'run-task',
task_id: taskId,
streaming: 'duplex'
},
payload: {
task_group: 'audio',
task: 'tts',
function: 'SpeechSynthesizer',
model: 'cosyvoice-v3-flash',
parameters: {
text_type: 'PlainText',
voice: 'longanyang', // Voice
format: 'mp3', // Format audio
sample_rate: 22050, // Laju sampel
volume: 50, // Volume
rate: 1, // Laju ucapan
pitch: 1, // Pitch
enable_ssml: true // Apakah akan mengaktifkan SSML. Jika enable_ssml diatur ke true, hanya satu perintah continue-task yang diizinkan; jika tidak, kesalahan "Text request limit violated, expected 1." akan dikembalikan
},
input: {}
}
});
ws.send(runTaskMessage);
console.log('Pesan run-task dikirim');
});
const fileStream = fs.createWriteStream(outputFilePath, { flags: 'a' });
ws.on('message', (data, isBinary) => {
if (isBinary) {
// Tulis data biner ke file
fileStream.write(data);
} else {
const message = JSON.parse(data);
switch (message.header.event) {
case 'task-started':
taskStarted = true;
console.log('Tugas dimulai');
// Kirim perintah continue-task
sendContinueTasks(ws);
break;
case 'task-finished':
console.log('Tugas selesai');
ws.close();
fileStream.end(() => {
console.log('Aliran file ditutup');
});
break;
case 'task-failed':
console.error('Tugas gagal:', message.header.error_message);
ws.close();
fileStream.end(() => {
console.log('Aliran file ditutup');
});
break;
default:
// result-generated dapat ditangani di sini
break;
}
}
});
function sendContinueTasks(ws) {
if (taskStarted) {
// Kirim perintah continue-task. Saat menggunakan SSML, perintah ini hanya dapat dikirim sekali
const continueTaskMessage = JSON.stringify({
header: {
action: 'continue-task',
task_id: taskId,
streaming: 'duplex'
},
payload: {
input: {
// Karakter khusus perlu di-escape
text: '<speak rate="2">Laju bicara saya lebih cepat daripada orang biasa.</speak>'
}
}
});
ws.send(continueTaskMessage);
// Kirim perintah finish-task
const finishTaskMessage = JSON.stringify({
header: {
action: 'finish-task',
task_id: taskId,
streaming: 'duplex'
},
payload: {
input: {}
}
});
ws.send(finishTaskMessage);
}
}
ws.on('close', () => {
console.log('Terputus dari server WebSocket');
});
LaTeX
Penggunaan
Apit rumus matematika dengan pembatas, lalu panggil API sintesis ucapan.
Pembatas yang didukung (pilih salah satu; efeknya sama):
$...$$$...$$\(...\)\[...\]
Contoh input:
这是一道分数:$\frac{1}{2}$。
Pecahan dibaca dalam bahasa Mandarin sebagai “二分之一” (setengah).
Gunakan pembatas yang sama untuk rumus dengan beberapa operator, misalnya:
这是一道一元二次方程的求根公式:$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$,请仔细计算。
Dalam JSON dan string biasa pada bahasa seperti Python, Java, dan JavaScript, tulis garis miring terbalik \ sebagai \\. Misalnya, tulis perintah LaTeX \frac sebagai \\frac dalam string biasa.
Mulai cepat
Contoh Python ini menyintesis teks Mandarin yang berisi pecahan dan menyimpannya sebagai output.mp3. Lihat mulai cepat SSML untuk pengaturan kunci API dan SDK.
# coding=utf-8
import os
import dashscope
from dashscope.audio.tts_v2 import *
# Jika variabel lingkungan belum diatur, ganti baris berikut dengan dashscope.api_key = "sk-xxx".
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# Ganti WorkspaceId dengan ID ruang kerja Anda. Gunakan URL untuk wilayah Anda.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
model = "cosyvoice-v3-flash"
voice = "longanyang"
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# Escape setiap garis miring terbalik sebagai \\ dalam string biasa.
audio = synthesizer.call("这是一道分数:$\\frac{1}{2}$。")
with open('output.mp3', 'wb') as f:
f.write(audio)
print('requestId: {}'.format(synthesizer.get_last_request_id()))
Tag SSML
CatatanImplementasi ini berdasarkan spesifikasi W3C SSML 1.0. Hanya tag yang tercantum di bawah yang didukung.
<speak>: Elemen akar
<speak> adalah elemen root untuk semua konten SSML. Semua teks harus diapit oleh tag <speak></speak>.
<speak>Teks yang memerlukan pemrosesan SSML</speak>
Atribut
Atribut | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| String | Tidak | Menentukan voice. Atribut ini memiliki prioritas lebih tinggi daripada parameter
|
| String | Tidak | Menentukan laju ucapan. Atribut ini memiliki prioritas lebih tinggi daripada parameter
|
| String | Tidak | Menentukan pitch. Atribut ini memiliki prioritas lebih tinggi daripada parameter
|
| String | Tidak | Menentukan volume. Atribut ini memiliki prioritas lebih tinggi daripada parameter
|
| String | Tidak | Menentukan efek audio.
|
| String | Tidak | Mengonfigurasi perilaku spesifik efek audio (parameter
|
| String | Tidak | Menambahkan musik latar pada ucapan yang disintesis. Simpan file audio di Alibaba Cloud OSS dan pastikan dapat diakses melalui URL Internet. Lihat Unggah objek. Untuk objek privat, gunakan URL bertanda tangan yang masih berlaku. Escape karakter khusus XML pada URL, misalnya mengganti
PentingPengunggah bertanggung jawab secara hukum atas hak cipta audio yang diunggah. |
| String | Tidak | Menentukan volume musik latar. Gunakan atribut ini bersama dengan atribut |
Contoh
Tanpa atribut
<speak>
Teks yang memerlukan tag SSML
</speak>
Atribut gabungan (dipisahkan spasi)
<speak rate="1.5" pitch="0.8" volume="80">
Jadi ketika digabungkan, suara saya terdengar seperti ini.
</speak>
voice
<speak voice="longcheng_v2">
Saya adalah voice pria.
</speak>
rate
<speak rate="2">
Laju ucapan saya lebih cepat daripada normal.
</speak>
pitch
<speak pitch="0.5">
Namun, pitch saya lebih rendah daripada orang lain.
</speak>
volume
<speak volume="80">
Volume saya juga sangat tinggi.
</speak>
effect
<speak effect="robot">
Apakah Anda menyukai robot WALL-E?
</speak>
effectValue
<speak effect="eq" effectValue="1 -20 1 1 1 1 20 1">
Apakah Anda menyukai robot WALL-E?
</speak>
<speak effect="lpfilter" effectValue="1200">
Apakah Anda menyukai robot WALL-E?
</speak>
<speak effect="hpfilter" effectValue="1200">
Apakah Anda menyukai robot WALL-E?
</speak>
bgm
<speak bgm="https://nls.alicdn.com/bgm/2.wav" backgroundMusicVolume="30" rate="0.8" volume="40">
<break time="2s"/>
Pohon-pohon tua di tebing yang teduh diselimuti kabut
<break time="700ms"/>
Suara hujan masih terdengar di hutan bambu
<break time="700ms"/>
Saya tahu bahwa kapas berkontribusi pada rencana negara
<break time="700ms"/>
Pemandangan Mianzhou selalu menyedihkan
<break time="2s"/>
</speak>
Hubungan tag
Tag <speak> dapat berisi teks dan tag anak berikut:
<break>: Kontrol durasi jeda<sub>: Ganti teks<phoneme>: Tentukan pelafalan (pinyin/fonetik)<soundEvent>: Sisipkan suara eksternal (nada dering, suara kucing, dll.)<say-as>: Atur interpretasi teks (angka, tanggal, nomor telepon, dll.)
<break>: Kontrol jeda
Menyisipkan jeda diam selama sintesis ucapan untuk mensimulasikan jeda alami dalam percakapan. Mendukung satuan waktu detik (s) dan milidetik (ms).
<!-- Tanpa atribut -->
<break/>
<!-- Dengan atribut time -->
<break time="string"/>
Atribut
Atribut | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| String | Tidak | Menentukan durasi jeda, dalam detik atau milidetik (misalnya, "2s" atau "50ms").
Saat beberapa tag |
Tanpa atribut, <break> menyisipkan jeda 1 detik.
Contoh
time
<speak>
Silakan tutup mata Anda dan beristirahat.<break time="500ms"/>Baiklah, silakan buka mata Anda.
</speak>
Tiga tag <break> berurutan di bawah menetapkan total jeda 15 detik. Jeda aktual dibatasi hingga 10 detik.
<speak>
Silakan tutup mata Anda dan beristirahat.<break time="5s"/><break time="5s"/><break time="5s"/>Baiklah, silakan buka mata Anda.
</speak>
Hubungan tag
<break> adalah elemen self-closing dan tidak dapat berisi elemen anak.
<sub>: Ganti teks
Mengganti teks tertentu dengan konten yang lebih cocok untuk ucapan. Misalnya, membaca "W3C" sebagai "World Wide Web Consortium."
<sub alias="string"></sub>
Atribut
Atribut | Type | Wajib | Deskripsi |
|---|---|---|---|
| String | Ya | Menentukan teks pengganti yang akan dibaca keras. |
Contoh
alias
<speak>
<sub alias="protokol jaringan">W3C</sub>
</speak>
Hubungan tag
Tag <sub> hanya dapat berisi teks biasa.
<phoneme>: Tentukan pelafalan
Memberikan kontrol tepat atas cara teks dilafalkan. Teks Tionghoa mendukung notasi pinyin, dan teks Inggris mendukung notasi fonetik CMU. Ini berguna untuk menghilangkan ambiguitas karakter polifonik dan menangani pelafalan bahasa asing.
<phoneme alphabet="string" ph="string">Teks</phoneme>
Atribut
Atribut | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| String | Ya | Menentukan jenis pelafalan: pinyin (untuk Tionghoa) atau simbol fonetik (untuk Inggris). Nilai valid:
|
| String | Ya | Menentukan notasi pinyin atau fonetik yang tepat. Aturan penggunaan:
|
Contoh
ph
<speak>
去<phoneme alphabet="py" ph="dian3 dang4 hang2">典当行</phoneme>把这个玩意<phoneme alphabet="py" ph="dang4 diao4">当掉</phoneme>
</speak>
<speak>
How to spell <phoneme alphabet="cmu" ph="S AY N">sin</phoneme>?
</speak>
Hubungan tag
Tag <phoneme> hanya dapat berisi teks biasa.
<soundEvent>: Sisipkan efek suara
Menyisipkan file efek suara (seperti nada peringatan atau suara latar) pada titik tertentu dalam ucapan untuk memperkaya output audio.
<soundEvent src="URL"/>
Atribut
Atribut | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| String | Ya | Menentukan URL file audio eksternal. Simpan file audio di Alibaba Cloud OSS dan pastikan dapat diakses melalui URL Internet. Lihat Unggah objek. Untuk objek privat, gunakan URL bertanda tangan yang masih berlaku. Escape karakter khusus XML pada URL, misalnya mengganti
PentingPengunggah bertanggung jawab secara hukum atas hak cipta audio yang diunggah. |
Contoh
src
<speak>
Seekor kuda ketakutan<soundEvent src="https://nls.alicdn.com/sound-event/horse-neigh.wav"/>dan orang-orang tersebar untuk menghindarinya.
</speak>
Hubungan tag
<soundEvent> adalah elemen self-closing dan tidak dapat berisi elemen anak.
<say-as>: Atur cara membaca teks
Menentukan jenis konten teks (seperti angka, tanggal, atau nomor telepon) sehingga sistem membacanya sesuai aturan yang sesuai untuk jenis tersebut.
<say-as interpret-as="string">Teks</say-as>
Atribut
Atribut | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| String | Ya | Menentukan jenis konten teks di dalam tag. Nilai valid:
|
Lihat format say-as yang didukung
cardinal
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
String digit | 145 | 一百四十五 | Bilangan bulat positif dan negatif hingga 20 digit: [-99999999999999999999,99999999999999999999]. Tidak ada batas khusus untuk jumlah angka desimal; disarankan maksimal 10. |
Tanda minus+String digit | -145 | 负一百四十五 | |
Kelompok 3 digit dipisahkan koma | 10,000 | 一万 | |
Tanda minus+Kelompok 3 digit dipisahkan koma | -10,124 | 负一万一百二十四 | |
String digit+Titik desimal+Dua nol | 10.00 | 十 | |
Tanda minus+String digit+Titik desimal+Dua nol | -110.00 | 负一百一十 | |
String digit+Titik desimal+String digit | 79.090 | 七十九点零九零 | |
Tanda minus+String digit+Titik desimal+String digit | -79.001 | 负七十九点零零一 |
Inggris
Format | Contoh | English output | Catatan |
|---|---|---|---|
String digit | 145 | one hundred forty five | Rentang integer: bilangan bulat positif dan negatif hingga 13 digit, [-999999999999,999999999999]. Rentang desimal: tidak ada batas spesifik tempat desimal, tetapi disarankan 10 atau kurang. |
String digit diawali nol | 0145 | one hundred forty five | |
Tanda minus + string digit | -145 | minus hundred forty five | |
String digit dengan koma memisahkan setiap 3 digit | 60,000 | sixty thousand | |
Tanda minus + string digit dipisahkan koma | -208,000 | minus two hundred eight thousand | |
String digit + titik desimal + nol | 12.00 | twelve | |
String digit + titik desimal + string digit | 12.34 | twelve point three four | |
String digit dipisahkan koma + titik desimal + string digit | 1,000.1 | one thousand point one | |
Tanda minus + string digit + titik desimal + string digit | -12.34 | minus twelve point three four | |
Tanda minus + string digit dipisahkan koma + titik desimal + string digit | -1,000.1 | minus one thousand point one | |
(String digit dipisahkan koma) + tanda hubung + (string digit dipisahkan koma) | 1-1,000 | one to one thousand | |
Pembacaan default lainnya | 012.34 | twelve point three four | Tidak ada |
1/2 | one half | ||
-3/4 | minus three quarters | ||
5.1/6 | five point one over six | ||
-3 1/2 | minus three and a half | ||
1,000.3^3 | one thousand point three to the power of three | ||
3e9.1 | three times ten to the power of nine point one | ||
23.10% | twenty three point one percent |
digits
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
String digit | 129090909 | 一二九零九零九零九 | Panjang string digit tidak dibatasi secara khusus; disarankan maksimal 20 digit. Jika melebihi 10 digit, jeda disisipkan setelah setiap digit. |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
String digit | 12034 | one two zero three four | Tidak ada batas spesifik panjang string digit, tetapi disarankan 20 digit atau kurang. Saat string digit dikelompokkan dengan spasi atau tanda hubung, jeda koma disisipkan antar grup. Maksimal 5 grup didukung. |
String digit + spasi/tanda hubung + string digit + spasi/tanda hubung + string digit + spasi/tanda hubung + string digit | 1-23-456 7890 | one, two three, four five six, seven eight nine zero |
telephone
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
Nomor telepon tetap | 4930286 | 四九三 零二八六 | Mendukung nomor telepon tetap 7 atau 8 digit dengan pemisah spasi atau tanda hubung (-). Kelompokkan 7 digit sebagai 3-4 dan 8 digit sebagai 4-4. |
493 0286 | 四九三 零二八六 | ||
493-0286 | 四九三 零二八六 | ||
62552560 | 六二五五 二五六零 | ||
6255 2560 | 六二五五 二五六零 | ||
6255-2560 | 六二五五 二五六零 | ||
Nomor telepon tetap+Nomor ekstensi | 4930286-109 | 四九三 零二八六 转幺零九 | Mendukung nomor ekstensi 1 hingga 4 digit. |
4930286转109 | 四九三 零二八六 转幺零九 | ||
4930286分机109 | 四九三 零二八六 分机幺零九 | ||
4930286分机号109 | 四九三 零二八六 分机号幺零九 | ||
Kode area+Nomor telepon tetap | 01062552560 | 零幺零 六二五五 二五六零 | Kode area: 010, 02x, 03xx, 04xx, 05xx, 07xx, 08xx, 09xx. |
010 62552560 | 零幺零 六二五五 二五六零 | ||
010 6255 2560 | 零幺零 六二五五 二五六零 | ||
010 6255-2560 | 零幺零 六二五五 二五六零 | ||
010-62552560 | 零幺零 六二五五 二五六零 | ||
010-6255-2560 | 零幺零 六二五五 二五六零 | ||
(010)62552560 | 零幺零 六二五五 二五六零 | ||
03198907098 | 零三幺九 八九零 七零九八 | ||
0319-8907098 | 三幺九 八九零 七零九八 | ||
Kode area+Nomor telepon tetap+Nomor ekstensi | 010 62552560-109 | 零幺零 六二五五 二五六零 转幺零九 | Tidak ada |
010-62552560-109 | 零幺零 六二五五 二五六零 转幺零九 | ||
(010)62552560-109 | 零幺零 六二五五 二五六零 转幺零九 | ||
(010)62552560转109 | 零幺零 六二五五 二五六零 转幺零九 | ||
(010)62552560分机109 | 零幺零 六二五五 二五六零 分机幺零九 | ||
(010)62552560分机号109 | 零幺零 六二五五 二五六零 分机号幺零九 | ||
Kode negara+Kode area+Nomor telepon tetap | 86-010-62791627 | 八六 零幺零 六二七九 幺六二七 | Kode negara 86, (86), +86, (+86), dan 0086 semuanya dibaca “八六” (delapan enam). |
(86)10-62791627 | 八六 幺零 六二七九 幺六二七 | ||
+86-010-62791627 | 八六 零幺零 六二七九 幺六二七 | ||
0086-10-62791627 | 八六 幺零 六二七九 幺六二七 | ||
(+86)-10-6279 1627 | 八六 幺零 六二七九 幺六二七 | ||
Kode negara+Kode area+Nomor telepon tetap+Nomor ekstensi | (86)21-58118818-207 | 八六 二幺 五八幺幺 八八幺八 转二零七 | Tidak ada |
(86)021-5811-8818-207 | 八六 零二幺 五八幺幺 八八幺八 转二零七 | ||
(86)021-58118818转207 | 八六 零二幺 五八幺幺 八八幺八 转二零七 | ||
(86)21-5811-8818分机207 | 八六 二幺 五八幺幺 八八幺八 分机二零七 | ||
+86-021-58118818分机号207 | 八六 零二幺 五八幺幺 八八幺八分机号二零七 | ||
Nomor ponsel | 139 0000 5678 | 幺三九 零零零零 五六七八 | Mendukung nomor ponsel 11 digit dengan pengelompokan 3-3-5 atau 3-4-4. |
139-000-05678 | 幺三九 零零零 零五六七八 | ||
139 000 05678 | 幺三九 零零零 零五六七八 | ||
Kode negara+Nomor ponsel | +86-13900005678 | 八六 幺三九 零零零零 五六七八 | Tidak ada |
(+86)-139-0000-5678 | 八六 幺三九 零零零零 五六七八 | ||
+8613900005678 | 八六 幺三九 零零零零 五六七八 | ||
0086-139 000 05678 | 八六 幺三九 零零零 零五六七八 | ||
Nomor layanan | 123 | 幺二三 | Mendukung nomor layanan umum, nomor 10 digit berawalan 400/800 yang dikelompokkan sebagai 3-3-4, dan nomor 16 digit berawalan 12530/17951/12593. |
95678 | 九五六七八 | ||
4008110510 | 四零零 八幺幺 零五幺零 | ||
800-810-8888 | 八零零 八幺零 八八八八 | ||
1253013520638377 | 幺二五三零 幺三五 二零六三 八三七七 | ||
Lainnya | (86)(21)9899-80800-0909 | 八六 二幺 九八九九 八零八零零 零九零九 | Mendukung string digit dengan pemisah (tanda kurung atau tanda hubung). |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
String digit | 12034 | one two oh three four | Tidak ada batas spesifik panjang string digit, tetapi disarankan 20 digit atau kurang.Saat string digit dikelompokkan dengan spasi atau tanda hubung, jeda koma disisipkan antar grup. Maksimal 5 grup didukung. |
String digit + spasi/tanda hubung + string digit + spasi/tanda hubung + string digit | 1-23-456 7890 | one, two three, four five six, seven eight nine oh | |
Tanda plus + string digit + spasi/tanda hubung + string digit | +43-211-0567 | plus four three, two one, oh five six seven | |
Tanda kurung kiri + string digit + tanda kurung kanan + spasi + string digit + spasi/tanda hubung + string digit | (21) 654-3210 | (two one) six five four, three two one oh |
address
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
Format alamat umum | 元和镇嘉元30-9 | 元和镇嘉元三十杠九 | Mendukung format alamat umum. Alamat di sini berarti alamat pos standar. |
市台路388弄1107-1108号 | 市台路三八八弄幺幺零七杠幺幺零八号 | ||
华润二十四城六期锦云府3-1-3205 | 华润二十四城六期锦云府三杠一杠三二零五 | ||
圣华名都大厦2幢2006室 | 圣华名都大厦二幢二零零六室 | ||
五常街道庭院5幢4单元201 | 五常街道庭院五幢四单元二零幺 | ||
芙蓉江路150弄19号 | 芙蓉江路幺五零弄十九号 |
Inggris
Jenis ini tidak didukung untuk teks bahasa Inggris.
id
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
String | dell0101 | D E L L 零 一 零 一 | Mendukung huruf Inggris besar dan kecil, digit 0-9, serta garis bawah. Spasi pada output menunjukkan jeda saat karakter dibaca satu per satu. |
myid_1998 | M Y I D 下划线 一 九 九 八 | ||
AiTest | A I T E S T |
Inggris
Untuk teks bahasa Inggris, jenis ini bekerja sama seperti characters.
characters
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
String | ISBN 1-001-099098-1 | I S B N 一 杠 零 零 一 杠 零 九 九 零 九 八 杠 一 | Mendukung karakter Mandarin, huruf Inggris besar dan kecil, digit 0-9, serta sebagian karakter lebar penuh dan setengah lebar. Spasi menunjukkan jeda antar karakter yang dibaca satu per satu. Escape karakter khusus XML. |
x10b2345_u | x 一 零 b 二 三 四 五 下划线 u | ||
v1.0.1 | v 一 点 零 点 一 | ||
版本号2.0 | 版本号二 点 零 | ||
苏M MA000 | 苏M M A 零 零 零 | ||
空中客车A330 | 空中客车A 三 三 零 | ||
型号s01 s02和s03 | 型号s 零 一 s 零二 和s 零 三 | ||
空中客车A330 | 空中客车A 三 三 零 | ||
αβγ | 阿尔法 贝塔 伽玛 |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
String | *b+3$.c-0'=α | asterisk B plus three dollar dot C dash zero apostrophe equals alpha | Mendukung karakter Tionghoa, huruf besar dan kecil, digit 0-9, dan beberapa karakter full-width dan half-width. Spasi dalam output menunjukkan jeda antar karakter, artinya setiap karakter dibaca secara individual. Jika teks di dalam tag berisi karakter khusus XML, escape karakter tersebut. |
punctuation
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
Tanda baca | … | 省略号 | Mendukung tanda baca Mandarin dan Inggris yang umum. Spasi menunjukkan jeda antar karakter yang dibaca satu per satu. Escape karakter khusus XML. |
…… | 省略号 | ||
!"#$%& | 叹号 双引号 井号 dollar 百分号 and | ||
‘()*+ | 单引号 左括号 右括号 星号 加号 | ||
,-./:; | 逗号 杠 点 斜杠 冒号 分号 | ||
<=>?@ | 小于 等号 大于 问号 at | ||
[\]^_ | 左方括号 反斜线 右方括号 脱字符 下划线 |
Inggris
Untuk teks bahasa Inggris, jenis ini bekerja sama seperti characters.
date
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
xx年 | 71年 | 七一年 | Mendukung tahun 2 digit dalam rentang 60-99, 00-09, dan 10-19, serta tahun 4 digit dalam rentang 1000-1999 dan 2000-2099. |
04年 | 零四年 | ||
19年 | 一九年 | ||
1011年 | 一零一一年 | ||
1998年 | 一九九八年 | ||
2008年 | 二零零八年 | ||
xx年xx月 | 98年4月 | 九八年四月 | Bulan 1-9 dapat menggunakan atau menghilangkan nol di depan, misalnya “1908年4月” dan “1908年04月”. |
1998年04月 | 一九九八年四月 | ||
08年8月 | 零八年八月 | ||
2008年8月 | 二零零八年八月 | ||
xx年xx月xx日xx年xx月xx号 | 98年4月23日 | 九八年四月二十三日 | Hari 1-9 dapat menggunakan atau menghilangkan nol di depan, misalnya “1908年4月8日” dan “1908年04月08日”. |
1998年04月23日 | 一九九八年四月二十三日 | ||
08年8月8号 | 零八年八月八号 | ||
2008年08月08号 | 二零零八年八月八号 | ||
xx年xx月xx日xx年xx月xx号 | 98年4月23日 | 九八年四月二十三日 | Hari 1-9 dapat menggunakan atau menghilangkan nol di depan, misalnya “1908年4月8日” dan “1908年04月08日”. |
1998年04月23日 | 一九九八年四月二十三日 | ||
08年8月8号 | 零八年八月八号 | ||
2008年08月08号 | 二零零八年八月八号 | ||
xx月xx号 | 3月20日 | 三月二十日 | Tidak ada |
08月07号 | 八月七号 | ||
Singkatan tahun/bulan | 2018/08 | 二零一八年八月 | Mendukung /, -, dan . sebagai pemisah. |
2018-08 | 二零一八年八月 | ||
2018.08 | 二零一八年八月 | ||
Singkatan tahun/bulan/hari | 2018/08/08 | 二零一八年八月八日 | |
2018-8-8 | 二零一八年八月八日 | ||
2018.08.08 | 二零一八年八月八日 | ||
xx年xx月xx日~xx年xx月xx日xx年xx月xx号~xx年xx月xx号 | 04年9月1日~30日 | 零四年九月一日至三十日 | Mendukung ~ dan - untuk menunjukkan “hingga”. |
2004年09月01号-2008年06月08号 | 二零零四年九月一号至二零零八年六月八号 | ||
xx年xx月xx日~xx日xx年xx月xx号~xx号 | 04年9月1日~30日 | 零四年九月一日至三十日 | |
2004年09月01号-2008年06月08号 | 二零零四年九月一号至二零零八年六月八号 | ||
xx年xx月~xx年xx月 | 01年04月~10年04月 | 零一年四月至一零年四月 | |
2001年04月~2010年04月 | 二零零一年四月至二零一零年四月 | ||
xx月xx日~xx月xx日xx月xx号~xx月xx号 | 10月1日~10月7日 | 十月一日至十月七日 | |
10月01号~10月07号 | 十月一号至十月七号 | ||
xx月xx日~xx日xx月xx号~xx号 | 10月1日~7日 | 十月一日至七日 | |
10月01号~07号 | 十月一号至七号 | ||
Singkatan tahun/bulan/hari~Singkatan tahun/bulan/hari | 2018/03/03~2019/01/01 | 二零一八年三月三日至二零一九年一月一日 | Mendukung / dan . sebagai pemisah, serta ~ dan - untuk menunjukkan “hingga”. |
1997.9.9~1998.9.9 | 一九九七年九月九日至一九九八年九月九日 | ||
Singkatan bulan/hari~Singkatan bulan/hari | 10/20~10/31 | 十月二十日至十月三十一日 | |
xx~xx月xx月~xx月 | 1~10月 | 一至十月 | |
1月~10月 | 一月至十月 | ||
Singkatan bulan/hari/tahun | 10/20/2018 | 二零一八年十月二十日 | Hanya mendukung tahun 4 digit, pemisah /, dan urutan bulan/hari/tahun. |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
Empat digit/dua digit atau empat digit-dua digit | 2000/01 | two thousand, oh one | Mencakup beberapa tahun. |
1900-01 | nineteen hundred, oh one | ||
2001-02 | twenty oh one, oh two | ||
2019-20 | twenty nineteen, twenty | ||
1998-99 | nineteen ninety eight, ninety nine | ||
1999-00 | nineteen ninety nine, oh oh | ||
Bilangan empat digit diawali 1 atau 2 | 2000 | two thousand | Tahun 4 digit. |
1900 | nineteen hundred | ||
1905 | nineteen oh five | ||
2021 | twenty one | ||
Hari - hari dalam minggu (tanda hubung) atau Hari - hari dalam minggu atau Hari & hari dalam minggu | mon-wed | monday to wednesday | Jika teks dalam tag rentang hari dalam minggu berisi karakter XML khusus, escape karakter tersebut. |
tue~fri | tuesday to friday | ||
sat&sun | saturday and sunday | ||
DD-DD MMM, YYYY atau DD~DD MMM, YYYY atau DD&DD MMM, YYYY | 19-20 Jan, 2000 | the nineteen to the twentieth of january two thousand | DD: Hari 2 digit. MMM: Singkatan bulan 3 huruf atau kata lengkap. YYYY: Tahun 4 digit diawali 1 atau 2. |
01 ~ 10 Jul, 2020 | the first to the tenth of july twenty | ||
05&06 Apr, 2009 | the fifth and the sixth of april two thousand nine | ||
MMM DD-DD atau MMM DD~DD atau MMM DD&DD | Feb 01 - 03 | feburary the first to the third | MMM: Singkatan bulan 3 huruf atau kata lengkap. DD: Hari 2 digit. |
Aug 10~20 | august the tenth to the twentieth | ||
Dec 11&12 | december the eleventh and the twelfth | ||
MMM-MMM atau MMM~MMM atau MMM&MMM | Jan-Jun | january to june | MMM: Singkatan bulan 3 huruf atau kata lengkap. |
jul ~ dec | july to december | ||
sep&oct | september and october | ||
YYYY-YYYY atau YYYY~YYYY | 1990 - 2000 | nineteen ninety to two thousand | YYYY: Tahun 4 digit diawali 1 atau 2. |
2001~2021 | two thousand one to twenty one | ||
WWW DD MMM YYYY | Sun 20 Nov 2011 | sunday the twentieth of november twenty eleven | WWW adalah singkatan 3 huruf atau nama lengkap hari dalam minggu. DD adalah hari 2 digit. MMM adalah singkatan 3 huruf atau nama lengkap bulan. MM adalah bulan 2 digit (atau singkatan 3 huruf atau nama lengkap bulan). YYYY adalah tahun 4 digit diawali 1 atau 2. |
WWW DD MMM | Sun 20 Nov | sunday the twentieth of november | |
WWW MMM DD YYYY | Sun Nov 20 2011 | sunday november the twentieth twenty eleven | |
WWW MMM DD | Sun Nov 20 | sunday november the twentieth | |
WWW YYYY-MM-DD | Sat 2010-10-01 | aturday october the first twenty ten | |
WWW YYYY/MM/DD | Sat 2010/10/01 | saturday october the first twenty ten | |
WWW MM/DD/YYYY | Sun 11/20/2011 | sunday november the twentieth twenty eleven | |
MM/DD/YYYY | 11/20/2011 | november the twentieth twenty eleven | |
YYYY | 1998 | nineteen ninety eight | |
Pembacaan default lainnya | 10 Mar, 2001 | the tenth of march two thousand one | Tidak ada |
10 Mar | the tenth of march | ||
Mar 2001 | march two thousand one | ||
Fri. 10/Mar/2001 | friday the tenth of march two thousand one | ||
Mar 10th, 2001 | march the tenth two thousand one | ||
Mar 10 | march the tenth | ||
2001/03/10 | march the tenth two thousand one | ||
2001-03-10 | march the tenth two thousand one | ||
2000s | two thousands | ||
2010's | twenty tens | ||
1900's | nineteen hundreds | ||
1990s | nineteen nineties |
time
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
Waktu | 12:00 | 十二点 | Mendukung format waktu dan rentang waktu umum. |
12:00:00点 | 十二点 | ||
10:20分 | 十点二十分 | ||
10:20:30 | 十点二十分三十秒 | ||
09:18:14 | 九点十八分十四秒 | ||
Waktu~Waktu | 11:00~12:00 | 十一点到十二点 | |
09:00-14:00 | 九点到十四点 | ||
11:00~11:30 | 十一点到十一点三十分 | ||
11:00-12:18 | 十一点到十二点十八分 | ||
10:30~11:00 | 十点三十分到十一点 | ||
09:28-10:00 | 九点二十八分到十点 | ||
10:20~11:20 | 十点二十分到十一点二十分 | ||
06:00~08:00 | 六点到八点 | ||
上午10:20~下午13:30 | 上午十点二十分到下午十三点三十分 | ||
Singkatan waktu | 5:00 am | 凌晨五点整 | |
5:30 am | 凌晨五点半 | ||
5:20:12 am | 凌晨五点二十分十二秒 | ||
7:00 am | 上午七点整 | ||
7:30 AM | 上午七点半 | ||
7:20:12 a.m. | 上午七点二十分十二秒 | ||
07:08:12 A.M. | 上午七点零八分十二秒 | ||
5:00 pm | 下午五点整 | ||
5:30 PM | 下午五点半 | ||
5:20:12 p.m. | 下午五点二十分十二秒 | ||
05:09:12 P.M. | 下午五点零九分十二秒 | ||
9:00 pm | 晚上九点整 | ||
9:30 pm | 晚上九点半 | ||
9:20:12 PM | 晚上九点二十分十二秒 | ||
9:02:12 P.M. | 晚上九点零二分十二秒 | ||
12:00 pm | 中午十二点整 | ||
12:30 p.m. | 中午十二点半 | ||
12:20:12 PM | 中午十二点二十分十二秒 |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
HH:MM AM atau PM | 09:00 AM | nine A M | HH: Jam 1 atau 2 digit. MM: Menit 2 digit. AM/PM: pagi/sore. |
09:03 PM | nine oh three P M | ||
09:13 p.m. | nine thirteen p m | ||
HH:MM | 21:00 | twenty one hundred | |
HHMM | 100 | one oclock | |
Titik waktu-Titik waktu | 8:00 am - 05:30 pm | eight a m to five p m | Mendukung format waktu umum dan rentang. |
7:05~10:15 AM | seven oh five to ten fifteen A M | ||
09:00-13:00 | nine oclock to thirteen hundred |
currency
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
Angka+Penanda mata uang | 12.00 RMB | 十二人民币 | Mendukung AUD (dolar Australia), CAD (dolar Kanada), HKD (dolar Hong Kong), JPY (yen Jepang), USD (dolar AS), CHF (franc Swiss), NOK (krone Norwegia), SEK (krona Swedia), GBP (pound Inggris), RMB (renminbi), CNY (yuan), dan EUR (euro). Angka dapat berupa bilangan bulat, desimal, atau notasi internasional dengan pemisah koma. |
12.50 RMB | 十二点五零人民币 | ||
12,000,000 RMB | 一千二百万人民币 | ||
12,000,000.00 RMB | 一千二百万人民币 | ||
12,000.35 RMB | 一万两千点三五人民币 | ||
Penanda mata uang+Angka | $12 | 十二美元 | Mendukung CAD (dolar Kanada), $ (dolar AS), Fr (franc), kr (krone Denmark), £ (pound Inggris), ¥ (yuan), dan € (euro). Angka dapat berupa bilangan bulat, desimal, atau notasi internasional dengan pemisah koma. |
$12.00 | 十二美元 | ||
$12.12 | 二点一二美元 | ||
$12,000 | 一万两千美元 | ||
$12,000.00 | 一万两千美元 | ||
$12,000.99 | 一万两千点九九美元 | ||
Pembacaan default lainnya | 1213 | 一千二百一十三 | Tidak ada |
1213 KML | 一千二百一十三K M L | ||
1213.00 KML | 一千二百一十三K M L | ||
1213.9 KML | 一千二百一十三点九K M L | ||
1,000 KML | 一千K M L | ||
1,000.00 KML | 一千K M L | ||
1,000.98 KML | 一千点九八K M L | ||
12,000 | 一万两千 |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
Angka + identifikasi mata uang | 1.00 RMB | one yuan | Format angka yang didukung: bilangan bulat, desimal, dan notasi internasional dipisahkan koma. Identifikasi mata uang yang didukung: CN¥ (yuan) CNY (yuan) RMB (yuan) AUD (dolar Australia) CAD (dolar Kanada) CHF (franc Swiss) DKK (krone Denmark) EUR (euro) GBP (pound sterling Inggris) HKD (dolar Hong Kong(China)) JPY (yen Jepang) NOK (krone Norwegia) SEK (krona Swedia) SGD (dolar Singapura) USD (dolar Amerika Serikat) |
2.02 CNY | two point zero two yuan | ||
1,000.23 CN¥ | one thousand point two three yuan | ||
1.01 SGD | one singapore dollar and one cent | ||
2.01 CAD | two canadian dollars and one cent | ||
3.1 HKD | three hong kong dollars and ten cents | ||
1,000.00 EUR | one thousand euros | ||
Identifikasi mata uang + angka | US$ 1.00 | one US dollar | Format angka yang didukung: bilangan bulat, desimal, dan notasi internasional dipisahkan koma. Identifikasi mata uang yang didukung: US$ (dolar AS) CA$ (dolar Kanada) AU$ (dolar Australia) SG$ (dolar Singapura) HK$ (dolar Hong Kong) C$ (dolar Kanada) A$ (dolar Australia) $ (dolar) £ (pound) € (euro) CN¥ (yuan) CNY (yuan) RMB (yuan) AUD (dolar Australia) CAD (dolar Kanada) CHF (franc Swiss) DKK (krone Denmark) EUR (euro) GBP (pound sterling Inggris) HKD (dolar Hong Kong(China)) JPY (yen Jepang) NOK (krone Norwegia) SEK (krona Swedia) SGD (dolar Singapura) USD (dolar Amerika Serikat) |
$0.01 | one cent | ||
JPY 1.01 | one japanese yen and one sen | ||
£1.1 | one pound and ten pence | ||
€2.01 | two euros and one cent | ||
USD 1,000 | one thousand united states dollars | ||
Angka + klasifikasi + identifikasi mata uang atau Identifikasi mata uang + angka+Kuantifier | 1.23 Tn RMB | one point two three trillion yuan | Format klasifikasi yang didukung: thousand million billion trillion Mil (million) mil (million) Bil (billion) bil (billion) MM (million) Bn (billion) bn (billion) Tn (trillion) tn (trillion) K(thousand) k (thousand) M (million) m (million) |
$1.2 K | one point two thousand dollars |
measure
Mandarin
Format | Contoh | Output Mandarin | Catatan |
|---|---|---|---|
Angka+Satuan Mandarin | 2片 | 两片 | Mendukung satuan Mandarin umum dan singkatan satuan. |
120公顷 | 一百二十公顷 | ||
100多毫克 | 一百多毫克 | ||
100来米 | 一百来米 | ||
100余人 | 一百余人 | ||
1厘米20毫米 | 一厘米二十毫米 | ||
120.00平方公里 | 一百二十平方公里 | ||
Angka+Singkatan satuan | 120.56 cm² | 一百二十点五六平方厘米 | |
120 ㎡ 56 cm² | 一百二十平方米五十六平方厘米 | ||
100 m 12 cm 6 mm | 一百米十二厘米六毫米 | ||
Rentang | 10~15 kg | 十至十五千克 | |
10.24~789.82亩 | 十点二四至七百八十九点八二亩 | ||
10米~15米 | 十米至十五米 | ||
10.24 cm~19.08 cm | 十点二四厘米至十九点零八厘米 | ||
Angka+Satuan+"/"+Satuan | 10元/斤 | 十元每斤 | |
199~299元/件 | 一百九十九至二百九十九元每件 | ||
299.99元/g~399.99元/g | 二百九十九点九九元每克至三百九十九点九九元每克 | ||
Pembacaan default lainnya | 12扎 | 十二扎 | |
30 rm | 三十r m | ||
4万万同胞 | 四万万同胞 | ||
12.897微克 | 十二点八九七微克 |
Inggris
Format | Contoh | Output Inggris | Catatan |
|---|---|---|---|
Angka + satuan ukuran | 1.0 kg | one kilogram | Format angka yang didukung: bilangan bulat, desimal, dan notasi internasional dipisahkan koma. Mendukung singkatan satuan umum. |
1,234.01 km | one thousand two hundred thirty four point zero one kilometres. | ||
Satuan ukuran | mm2 | square millimetre |
Simbol umum
Simbol | Pembacaan Mandarin | Pembacaan Inggris |
|---|---|---|
! | 叹号 | exclamation mark |
“ | 双引号 | double quote |
# | 井号 | pound |
$ | dollar | dollar |
% | 百分号 | percent |
& | and | and |
‘ | 单引号 | left quote |
( | 左括号 | left parenthesis |
) | 右括号 | right parenthesis |
* | 星 | asterisk |
+ | 加 | plus |
, | 逗号 | comma |
- | 杠 | dash |
. | 点 | dot |
/ | 斜杠 | slash |
: | 零冒号 | solon |
; | 分号 | semicolon |
< | 小于 | less than |
= | 等号 | equals |
> | 大于 | greater than |
? | 问号 | question mark |
@ | at | at |
[ | 左方括号 | left bracket |
\ | 反斜线 | back slash |
] | 右方括号 | right bracket |
^ | 脱字符 | caret |
_ | 下划线 | underscore |
` | 反引号 | back quote |
{ | 左花括号 | left brace |
| | 竖线 | vertical bar |
} | 右花括号 | right brace |
~ | 波浪线 | tilde |
! | 叹号 | exclamation mark |
“ | 左双引号 | left double quote |
” | 右双引号 | right double qute |
‘ | 左单引号 | left quote |
’ | 右单引号 | right quote |
( | 左括号 | left parenthesis |
) | 右括号 | right parenthesis |
, | 逗号 | comma |
。 | 句号 | full stop |
— | 杠 | em dash |
: | 冒号 | colon |
; | 分号 | semicolon |
? | 问号 | question mark |
、 | 顿号 | enumeration comma |
… | 省略号 | ellipsis |
…… | 省略号 | ellipsis |
《 | 左书名号 | left guillemet |
》 | 右书名号 | right guillemet |
¥ | 人民币符号 | yuan |
≥ | 大于等于 | greater than or equal to |
≤ | 小于等于 | less than or equal to |
≠ | 不等于 | not equal |
≈ | 约等于 | approximately equal |
± | 加减 | plus or minus |
× | 乘 | times |
π | 派 | pi |
Α | 阿尔法 | alpha |
Β | 贝塔 | beta |
Γ | 伽玛 | gamma |
Δ | 德尔塔 | delta |
Ε | 艾普西龙 | epsilon |
Ζ | 捷塔 | zeta |
Θ | 西塔 | theta |
Ι | 艾欧塔 | iota |
Κ | 喀帕 | kappa |
∧ | 拉姆达 | lambda |
Μ | 缪 | mu |
Ν | 拗 | nu |
Ξ | 克西 | ksi |
Ο | 欧麦克轮 | omicron |
∏ | 派 | pi |
Ρ | 柔 | rho |
∑ | 西格玛 | sigma |
Τ | 套 | tau |
Υ | 宇普西龙 | upsilon |
Φ | fai | phi |
Χ | 器 | chi |
Ψ | 普赛 | psi |
Ω | 欧米伽 | omega |
α | 阿尔法 | alpha |
β | 贝塔 | beta |
γ | 伽玛 | gamma |
δ | 德尔塔 | delta |
ε | 艾普西龙 | epsilon |
ζ | 捷塔 | zeta |
η | 依塔 | eta |
θ | 西塔 | theta |
ι | 艾欧塔 | iota |
κ | 喀帕 | kappa |
λ | 拉姆达 | lambda |
μ | 缪 | mu |
ν | 拗 | nu |
ξ | 克西 | ksi |
ο | 欧麦克轮 | omicron |
π | 派 | pi |
ρ | 柔 | rho |
σ | 西格玛 | sigma |
τ | 套 | tau |
υ | 宇普西龙 | upsilon |
φ | fai | phi |
χ | 器 | chi |
ψ | 普赛 | psi |
ω | 欧米伽 | omega |
Satuan umum
Format | Kategori | Contoh Mandarin | Contoh Inggris |
|---|---|---|---|
Singkatan | Panjang | nm(纳米)、μm(微米)、 mm(毫米)、cm(厘米)、m(米)、km(千米)、ft(英尺)、in(英寸) | nm (nanometre), μm (micrometre), mm (millimetre), cm (centimetre), m (metre), km (kilometre), ft (foot), in (inch) |
Luas | cm²(平方厘米)、㎡(平方米)、km²(平方千米)、SqFt(平方英尺) | cm² (square centimetre), ㎡ (square metre), km2 (square kilometre), SqFt (square foot) | |
Volume | cm³(立方厘米)、m³(立方米)、km³(立方千米)、mL(毫升)、L(升)、gallon(加仑) | cm³ (cubic centimetre), m³ (cubic metre), km3 (cubic kilometre), mL (millilitre), L (millilitre), gal (gallon) | |
Berat | μg(微克)、mg(毫克)、g(克)、kg(千克) | μg (microgram), mg (microgram), g (gram), kg (kilogram) | |
Waktu | min(分)、sec(秒)、ms(毫秒) | min (minute), sec (second), ms (millisecond) | |
Elektromagnetisme | μA(微安)、mA(毫安)、Ω(欧姆)、Hz(赫兹)、kHz(千赫兹)、MHz(兆赫兹)、GHz(吉赫兹)、V(伏)、kV(千伏)、kWh(千瓦时) | μA (microamp), mA (milliamp), Hz (hertz), kHz (kilohertz), MHz (megahertz), GHz (gigahertz), V (volt), kV (kilovolt), kWh (kilowatt hour) | |
Suara | dB(分贝) | dB (decibel) | |
Tekanan | Pa(帕)、kPa(千帕)、Mpa(兆帕) | Pa (pascal), kPa (kilopascal), MPa (megapascal) | |
Satuan umum lainnya | Juga mendukung satuan Mandarin di luar kategori ini, seperti “米”, “秒”, “美元”, dan “毫升每瓶”, serta kata penggolong Mandarin seperti “架”, “场”, “头”, “部”, dan “盆”. | Juga mendukung satuan lain, seperti tsp (teaspoon), rpm (round per minute), KB (kilobyte), dan mmHg (millimetre of mercury). | |
Contoh
cardinal
<speak>
<say-as interpret-as="cardinal">12345</say-as>
</speak>
<speak>
<say-as interpret-as="cardinal">10234</say-as>
</speak>
digits
<speak>
<say-as interpret-as="digits">12345</say-as>
</speak>
<speak>
<say-as interpret-as="digits">10234</say-as>
</speak>
telephone
<speak>
<say-as interpret-as="telephone">12345</say-as>
</speak>
<speak>
<say-as interpret-as="telephone">10234</say-as>
</speak>
name
<speak>
她的曾用名是<say-as interpret-as="name">曾小凡</say-as>
</speak>
address
<speak>
<say-as interpret-as="address">富路国际1号楼3单元304</say-as>
</speak>
id
<speak>
<say-as interpret-as="id">myid_1998</say-as>
</speak>
characters
<speak>
<say-as interpret-as="characters">希腊字母αβ</say-as>
</speak>
<speak>
<say-as interpret-as="characters">*b+3.c$=α</say-as>
</speak>
punctuation
<speak>
<say-as interpret-as="punctuation"> -./:;</say-as>
</speak>
date
<speak>
<say-as interpret-as="date">1000-10-10</say-as>
</speak>
<speak>
<say-as interpret-as="date">10-01-2020</say-as>
</speak>
time
<speak>
<say-as interpret-as="time">5:00am</say-as>
</speak>
<speak>
<say-as interpret-as="time">0500</say-as>
</speak>
currency
<speak>
<say-as interpret-as="currency">13,000,000.00RMB</say-as>
</speak>
<speak>
<say-as interpret-as="currency">$1,000.01</say-as>
</speak>
measure
<speak>
<say-as interpret-as="measure">100m12cm6mm</say-as>
</speak>
<speak>
<say-as interpret-as="measure">1,000.01kg</say-as>
</speak>
Hubungan tag
Tag <say-as> dapat berisi teks.
Tag dan simbol LaTeX
Pilih kategori untuk melihat tag dan simbol yang didukung. Contoh teks input menyertakan pembatas. Contoh pembacaan tetap dalam bahasa Mandarin karena fitur ini menghasilkan ucapan bahasa Mandarin.
Matematika dasar
Tag atau simbol | Makna | Contoh sumber rumus | Contoh teks input | Contoh pembacaan |
|---|---|---|---|---|
| Penjumlahan |
|
| 二加三等于五 |
| Pengurangan |
|
| 三减二等于一 |
| Plus atau minus |
|
| 正负一加减二 |
Positif atau negatif | ||||
| Perkalian |
|
| 二乘三等于六 |
|
|
| ||
|
|
| ||
| Pembagian |
|
| 六除二等于三 |
|
|
| ||
|
|
| ||
| Sama dengan |
|
| 三加五等于八 |
| Kurang dari |
|
| 一小于二 |
| Kurang dari atau sama dengan |
|
| 三小于等于五 |
|
|
| ||
|
|
| ||
|
|
| ||
|
|
| ||
|
|
| ||
| Lebih dari |
|
| 二大于一 |
| Lebih dari atau sama dengan |
|
| 五大于等于三 |
|
|
| ||
|
|
| ||
|
|
| ||
|
|
| ||
|
|
| ||
| Pecahan |
|
| 三分之二 |
| Pangkat |
|
| 二的一次方 |
| Akar |
|
| 根号下九等于三 |
|
| 三次根号下八等于二 | ||
| Persentase |
|
| 百分之五 |
| Nilai mutlak |
|
| 绝对值三的绝对值等于三 |
|
|
| 绝对值三绝对值等于三 | |
| Logaritma |
|
| log十 |
| Logaritma |
|
| log五 |
| Logaritma natural |
|
| LN十 |
| Faktorial |
|
| 五的阶乘 |
| Tanda kurung |
|
| 括号内二加一 |
|
| 大括号二加一反大括号 |
Simbol matematika khusus
Tag atau simbol | Makna | Contoh sumber rumus | Contoh teks input | Contoh pembacaan |
|---|---|---|---|---|
| alpha |
|
| α |
|
|
| ||
| beta |
|
| β |
|
|
| ||
| gamma |
|
| γ |
|
|
| ||
| delta |
|
| Δ |
|
|
| ||
| Tak hingga (Mandarin) |
|
| 无穷大 |
| infty (Inggris) |
|
|
Geometri
Tag atau simbol | Makna | Contoh sumber rumus | Contoh teks input | Contoh pembacaan |
|---|---|---|---|---|
| Pi |
|
| 派等于三点一四一五九 |
| Fungsi trigonometri |
|
| sine三十度等于二分之一 |
|
|
| cosine四十五度等于二分之根号下二 | |
|
|
| tangent三十度等于cosine三十度分之sine三十度 | |
|
|
| cosecant A | |
|
|
| secant A | |
|
|
| cotangent A | |
| Sudut |
|
| 角A B |
|
|
| ||
| Derajat |
|
| 角A B 等于三十度 |
| Lingkaran |
|
| 圆 |
| Busur |
|
| 弧BC |
| Sudut siku-siku |
|
| 因为直角三角形ABC |
|
|
| 所以AB垂直于BC | |
| Segitiga |
|
| 三角形ABC |
|
|
| ||
| Jajar genjang |
|
| 平行四边形ABCD |
| Tegak lurus |
|
| A B 垂直于 B C |
|
|
| ||
|
|
| ||
| Sejajar |
|
| A平行于B |
| Sejajar dan sama |
|
| A平行且相等于B |
| Kongruen |
|
| 三角形ABC全等于三角形DEF |
Kondisi
Tag atau simbol | Makna | Contoh sumber rumus | Contoh teks input | Contoh pembacaan |
|---|---|---|---|---|
| Mengimplikasikan |
|
| 推出一加一等于二 |
| Ekuivalen |
|
| p等价q |
| Karena |
|
| 因为a等于b所以b等于a |
| Oleh karena itu |
Satuan
Apit satuan dengan \unit, \quantity, \mathit, \mathrm, atau \rm, misalnya \unit{cm}.
Tag atau simbol | Makna | Contoh sumber rumus | Contoh teks input | Contoh pembacaan |
|---|---|---|---|---|
| Milimeter |
|
| 五毫米 |
| Sentimeter |
|
| 五厘米 |
| Desimeter |
|
| 五分米 |
| Meter |
|
| 五米 |
| Kilometer |
|
| 五千米 |
| Gram |
|
| 五克 |
| Kilogram |
|
| 五千克 |
| Ton |
|
| 五吨 |
| Milimeter persegi |
|
| 五平方毫米 |
| Sentimeter persegi |
|
| 五平方厘米 |
| Desimeter persegi |
|
| 五平方分米 |
| Meter persegi |
|
| 五平方米 |
| Kilometer persegi |
|
| 五平方千米 |
| Milimeter kubik |
|
| 五立方毫米 |
| Sentimeter kubik |
|
| 五立方厘米 |
| Desimeter kubik |
|
| 五立方分米 |
| Meter kubik |
|
| 五立方米 |
| Kilometer kubik |
|
| 五立方千米 |
| Mililiter |
|
| 五毫升 |
| Detik |
|
| 五秒 |
| Menit |
|
| 五分 |
| Jam |
|
| 五小时 |
| Kilometer per jam |
|
| 五千米每小时 |
| Gram per liter |
|
| 五克每升 |
FAQ
Mengapa rumus tidak dibaca dengan benar?
- Periksa apakah rumus diapit oleh
$...$,$$...$$,\(...\), atau\[...\]. - Periksa tag atau simbol yang tidak didukung.
- Pastikan setiap
\di-escape sebagai\\dalam string permintaan.
Bagaimana menangani garis miring terbalik dalam kode?
Lihat petunjuk escape di Penggunaan. Sumber rumus dan string kode menggunakan notasi berbeda: tulis \frac sebagai \\frac dalam string biasa.