メインコンテンツまでスキップ

リアルタイム API(WebSocket)

音声・テキストのリアルタイム双方向対話に使用します。 Alibaba DashScope の Realtime API を透過プロキシします。

エンドポイント

wss://api.lykuro.ai/alibaba/api-ws/v1/realtime?model={model}
Authorization: Bearer sk-jp-YOUR_KEY

model には上流ネイティブのモデル名を指定します(プロバイダ alibaba は base_url 側で指定済み)。

対応モデル

model説明
qwen3.5-omni-plus-realtimeフラッグシップ・音声/テキスト/画像対応
qwen3.5-omni-flash-realtime軽量・低レイテンシ
qwen3-omni-flash-realtimeQwen3 軽量リアルタイム
qwen3-livetranslate-flash-realtimeリアルタイム同時翻訳(60言語)

音声フォーマット

方向フォーマットサンプリングレート
入力PCM1616 kHz
出力PCM1624 kHz

接続フロー

1. WSS 接続確立
wss://api.lykuro.ai/alibaba/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime
Authorization: Bearer sk-jp-YOUR_KEY

2. session.update イベント送信(セッション設定)

3. 音声/画像データ送信
input_audio_buffer.append — 音声データ(Base64)
input_image_buffer.append — 画像データ(Base64)
input_audio_buffer.commit — バッファ確定

4. response.create — 応答生成リクエスト

5. サーバーからレスポンス受信
response.text.delta — テキストチャンク
response.audio.delta — 音声チャンク(Base64)
response.done — 完了(usage 含む/この時点で課金)

クライアント送信イベント

イベント type説明主なパラメータ
session.updateセッション設定を更新modalities(text/audio)、input_audio_formatoutput_audio_formatinstructionsvoice
input_audio_buffer.append音声データをバッファに追加audio(Base64文字列)
input_image_buffer.append画像データをバッファに追加image(Base64文字列)
input_audio_buffer.commit音声バッファを確定(手動モード時)
response.create応答生成をリクエスト
response.cancel進行中の応答をキャンセル

session.update サンプル

{
"type": "session.update",
"session": {
"modalities": ["text", "audio"],
"input_audio_format": "pcm16",
"output_audio_format": "pcm16",
"instructions": "あなたは親切な日本語アシスタントです。",
"voice": "alloy"
}
}

サーバー受信イベント

イベント type説明
session.createdセッション確立完了
response.text.deltaテキストチャンク(逐次)
response.text.doneテキスト生成完了
response.audio.delta音声チャンク(Base64、逐次)
response.audio.done音声生成完了
response.audio_transcript.delta出力音声の書き起こし(逐次)
conversation.item.input_audio_transcription.completed入力音声の書き起こし完了
input_audio_buffer.speech_started発話開始検知(VAD)
input_audio_buffer.speech_stopped発話終了検知(VAD)
response.done応答完了(usage 含む)

サンプル — Python(音声リアルタイム対話)

import asyncio
import json
import base64
import websockets

async def realtime_chat():
url = "wss://api.lykuro.ai/alibaba/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime"
headers = {"Authorization": "Bearer sk-jp-YOUR_KEY"}

async with websockets.connect(url, extra_headers=headers) as ws:
# 1. セッション設定
await ws.send(json.dumps({
"type": "session.update",
"session": {
"modalities": ["text", "audio"],
"input_audio_format": "pcm16", # 16kHz PCM16
"output_audio_format": "pcm16", # 24kHz PCM16
"instructions": "あなたは親切な日本語アシスタントです。",
},
}))

# 2. 音声データ送信(16kHz PCM16)
with open("input.pcm", "rb") as f:
audio_data = base64.b64encode(f.read()).decode()

await ws.send(json.dumps({"type": "input_audio_buffer.append", "audio": audio_data}))
await ws.send(json.dumps({"type": "input_audio_buffer.commit"}))

# 3. 応答生成リクエスト
await ws.send(json.dumps({"type": "response.create"}))

# 4. レスポンス受信
async for message in ws:
event = json.loads(message)
if event["type"] == "response.text.delta":
print(event["delta"], end="", flush=True)
elif event["type"] == "response.audio.delta":
audio_chunk = base64.b64decode(event["audio"]) # 再生処理へ
elif event["type"] == "response.audio_transcript.delta":
print(f"[書き起こし] {event['delta']}", end="", flush=True)
elif event["type"] == "response.done":
print("\n[完了]")
break

asyncio.run(realtime_chat())

サンプル — Node.js(音声リアルタイム対話)

import WebSocket from "ws";
import fs from "fs";

const ws = new WebSocket(
"wss://api.lykuro.ai/alibaba/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime",
{ headers: { Authorization: "Bearer sk-jp-YOUR_KEY" } }
);

ws.on("open", () => {
ws.send(JSON.stringify({
type: "session.update",
session: {
modalities: ["text", "audio"],
input_audio_format: "pcm16",
output_audio_format: "pcm16",
instructions: "あなたは親切な日本語アシスタントです。",
},
}));

const audioData = fs.readFileSync("input.pcm").toString("base64");
ws.send(JSON.stringify({ type: "input_audio_buffer.append", audio: audioData }));
ws.send(JSON.stringify({ type: "input_audio_buffer.commit" }));
ws.send(JSON.stringify({ type: "response.create" }));
});

ws.on("message", (data) => {
const event = JSON.parse(data.toString());
if (event.type === "response.text.delta") {
process.stdout.write(event.delta);
} else if (event.type === "response.audio.delta") {
const audioChunk = Buffer.from(event.audio, "base64"); // 再生処理へ
} else if (event.type === "response.done") {
console.log("\n[完了]");
ws.close();
}
});

ws.on("error", (err) => console.error("WebSocket エラー:", err));
ws.on("close", () => console.log("接続終了"));

サンプル — リアルタイム翻訳(60言語)

async def live_translate():
url = "wss://api.lykuro.ai/alibaba/api-ws/v1/realtime?model=qwen3-livetranslate-flash-realtime"
headers = {"Authorization": "Bearer sk-jp-YOUR_KEY"}

async with websockets.connect(url, extra_headers=headers) as ws:
await ws.send(json.dumps({
"type": "session.update",
"session": {"modalities": ["text"], "instructions": "日本語を英語にリアルタイム翻訳してください。"},
}))
with open("japanese_speech.pcm", "rb") as f:
audio_data = base64.b64encode(f.read()).decode()
await ws.send(json.dumps({"type": "input_audio_buffer.append", "audio": audio_data}))
await ws.send(json.dumps({"type": "input_audio_buffer.commit"}))
await ws.send(json.dumps({"type": "response.create"}))
async for message in ws:
event = json.loads(message)
if event["type"] == "response.text.delta":
print(event["delta"], end="", flush=True)
elif event["type"] == "response.done":
break

asyncio.run(live_translate())

サンプル — wscat(接続テスト)

npm install -g wscat
wscat -c "wss://api.lykuro.ai/alibaba/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime" \
-H "Authorization: Bearer sk-jp-YOUR_KEY"

接続後にセッション設定を送信:

{"type":"session.update","session":{"modalities":["text"],"instructions":"こんにちは!"}}

中断時の動作

状況動作
クライアント切断上流 WSS 接続も即切断
上流切断クライアント WSS も切断。クライアント側で再接続
セッション継続非対応(再接続時は新規セッション)

課金は response.done イベントごとに実消費トークンで行われます。