すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Model Studio:モデルとアプリケーションへの接続

最終更新日:Aug 26, 2026

AOQ、WebRTC、WebSocket プロトコルを使用して、リアルタイム API のモデルとアプリケーションに接続します。このトピックでは、各プロトコルの接続フロー、シーケンス図、およびコード例について説明します。

前提条件

デモの試用

Alibaba Cloud Model Studio の Android デモを使用すると、AOQ 接続性を迅速に検証できます。APK をダウンロードし、API キーと workspaceId を設定して、選択したモデルを試すことができます。

次の QR コードをスキャンして、デモをダウンロードしてください。

QR code for downloading the demo

AOQ 接続

AOQ は QUIC プロトコルを基盤に深くカスタマイズされています。ネイティブモバイルアプリに適しており、オーディオ、ビデオ、データの混在送信をサポートし、劣悪なネットワークへの耐性が組み込まれています。次の例では、Real-time omni (Omni) iOS デモを使用して、AOQ 接続フローを説明します。AOQ SDK API の詳細については、「AOQクライアントSDK」をご参照ください。

全体的なシーケンス図

AOQ sequence diagram

エンジンの作成とコールバックの設定

let config = AoqCreateConfig()
config.workDir = workDir
config.enableDumpAudio = false
engine = AoqClientEngine.createEngine(config, delegate: self)

AoqEngineDelegate プロトコルを実装して、onConnectionStatusChangeonDataMsgonError などのコールバックをリッスンします。

オーディオキャプチャと再生の開始

// オーディオキャプチャ
let capCfg = AoqAudioCaptureConfig()
capCfg.channel = 1; capCfg.isExternal = false
engine.startAudioCapture(capCfg)

// オーディオ再生
let playCfg = AoqAudioPlaybackConfig()
playCfg.channel = 1; playCfg.isExternal = false
engine.startAudioPlayer(playCfg)

// ビデオキャプチャ (オプション)
let vidCfg = AoqVideoCaptureConfig()
vidCfg.width = 720; vidCfg.height = 1280; vidCfg.fps = 15
engine.startVideoCapture(vidCfg)

接続認証情報の取得

ビジネス AppServer がリクエストを Model Studio にプロキシします。詳細については、「トークン認証」をご参照ください。

コーデックの設定と接続の確立

コーデックパラメータを設定してから、connect を呼び出します。

// オーディオコーデック設定
let encCfg = AoqAudioCodecConfig()
encCfg.codecType = .audioPCM; encCfg.sampleRate = 16000; encCfg.channel = 1
engine.setAudioEncoderConfig(encCfg)
engine.setAudioDecoderConfig(encCfg)

// 接続前にメディア送信を無効化し、session.updated 後に有効化する
engine.enableSendMediaStream(.audio, enable: false)

let config = AoqConnectConfig()
config.token = token
config.sid = sid
config.certFingerprint = certificate
config.relayEndpoints = relayEndpoints
config.workspaceIdHash = workspaceIdHash
config.publishTracks = [audioTrack, dataTrack]
config.subscribeTracks = [audioTrack, dataTrack]
engine.connect(config)

重要重要:AOQ SDK は、接続が確立されるとデフォルトでメディアデータを送信します。この例では、モデルへの接続時にメディア送信を無効化し、セッションの準備が整った後にのみ有効化します。

AI セッションの設定

接続が成功した後、session.update イベントを送信します。詳細については、「クライアントイベント」をご参照ください。

func onConnectionStatusChange(_ status: AoqConnectionStatus) {
    if status == .connected { sendSessionUpdate() }
}

private func sendSessionUpdate() {
    let json = """
    {
      // このイベントの ID。クライアントによって生成されます
      "event_id": "event_ToPZqeobitzUJnt3QqtWg",
      // イベントタイプ。session.update に固定されます
      "type": "session.update",
      // セッション設定
      "session": {
          // 出力モダリティ。["text"] (テキストのみ) または ["text", "audio"] (テキストとオーディオ) に設定します
          "modalities": [
              "text",
              "audio"
          ],
          // 出力オーディオの音声
          "voice": "Ethan",
          // 入力オーディオ形式。pcm のみサポートされます。入力オーディオは、16 kHz サンプルレートの PCM オーディオストリームです
          "input_audio_format": "pcm",
          // 出力オーディオ形式。pcm のみサポートされます。出力オーディオは、24 kHz サンプルレートの PCM オーディオストリームです
          "output_audio_format": "pcm",
          // モデルの目標または役割を設定するシステムメッセージ
          "instructions": "You are an AI customer service agent at a five-star hotel. Accurately and courteously answer customer questions about room types, facilities, prices, and booking policies. Always respond in a professional and helpful manner, and never provide unverified information or information beyond the scope of the hotel's services.",
          // 音声アクティビティ検出 (VAD) を有効にするには、設定オブジェクトを渡します。有効にすると、サーバーは音声の開始と終了を自動的に検出します
          // クライアント側でモデル応答をトリガーするタイミングを制御する場合は、null に設定します
          "turn_detection": {
              // VAD タイプ:server_vad または semantic_vad。qwen3.5-omni-realtime シリーズモデルには semantic_vad を推奨します
              "type": "semantic_vad",
              // VAD 検出閾値。ノイズの多い環境では増やし、静かな環境では減らします
              "threshold": 0.5,
              // 音声終了を検出するための無音期間。この期間を超えると、モデル応答がトリガーされます
              "silence_duration_ms": 800
          }
      }
    }
    """
    let msg = AoqDataMsg()
    msg.data = json.data(using: .utf8)!
    engine.send(msg)
}

session.updated 受信後のメディア送信の有効化

次の例では、モデルからの session.updated 応答を処理します。詳細については、「サーバーイベント」をご参照ください。

func onDataMsg(_ msg: AoqDataMsg) {
    guard let obj = try? JSONSerialization.jsonObject(with: msg.data) as? [String: Any],
          let type = obj["type"] as? String else { return }
    if type == "session.updated" {
        engine.enableSendMediaStream(.audio, enable: true)
        engine.enableSendMediaStream(.video, enable: true)
    }
}

重要

  1. session.updated を受信した後にのみ、メディアストリーム送信を有効化してください。そうしないと、サーバーがデータを受信する準備ができていない可能性があります。

  2. 接続設定中に追加されたオーディオトラックとビデオトラック (AOQ メディアチャネル) は、自動的にサーバーにデータを送信します。

    1. オーディオ:オーディオトラックを介して直接送信されます。input_audio_buffer.append イベントは不要です。
    2. ビデオ:フレームはビデオトラックを介して送信されます。input_image_buffer.append イベントは不要です。

切断とエンジンの破棄

engine.disconnect()
AoqClientEngine.destroy()

WebRTC 接続

WebRTC には専用の SDK はありません。Web では、ブラウザのネイティブ JavaScript API を使用して直接接続します。他のクライアントでは、オープンソースの WebRTC ライブラリ、または標準 WebRTC プロトコルをサポートするサードパーティの RTC サービスを使用して接続します。次の例では、Web 上の JavaScript を使用します。

全体的なフロー図

WebRTC flow diagram

接続の確立

# pip install aiortc aiohttp certifi
import asyncio, aiohttp, ssl, certifi
from aiortc import RTCPeerConnection, RTCConfiguration, RTCSessionDescription
from aiortc.mediastreams import AudioStreamTrack

API_KEY = "your-api-key"
MODEL = "target-model"
SIGNALING_URL = f"https://{{endpoint}}/api/v1/webrtc/realtime?model={MODEL}"

async def connect():
    pc = RTCPeerConnection(RTCConfiguration(iceServers=[]))

    # オファー SDP に m=audio が含まれるように、オーディオトラックを追加します (サーバーで必須)
    pc.addTrack(AudioStreamTrack())

    # SDP ネゴシエーションをトリガーするために DataChannel を作成します (名前はカスタマイズ可能。サーバーは「oai-events」という名前のチャネルを介してイベントをプッシュします)
    pc.createDataChannel("oai-events")

    # SDP 交換:オファーを作成してサーバーに送信します
    offer = await pc.createOffer()
    await pc.setLocalDescription(offer)

    async with aiohttp.ClientSession() as session:
        async with session.post(
            SIGNALING_URL,
            ssl=ssl.create_default_context(cafile=certifi.where()),
            data=offer.sdp.encode("utf-8"),
            headers={
                "Content-Type": "application/sdp",
                "Authorization": f"Bearer {API_KEY}",
            },
        ) as resp:
            if not resp.ok:
                raise Exception(f"SDP exchange failed: {resp.status} {await resp.text()}")
            answer_sdp = await resp.text()

    print("=== オファー SDP ===")
    print(offer.sdp)
    print("=== アンサー SDP ===")
    print(answer_sdp)

    # ICE 接続セットアップは自動的に完了します
    await pc.setRemoteDescription(RTCSessionDescription(sdp=answer_sdp, type="answer"))
    print("WebRTC 接続が確立されました")
    return pc

モデルパラメータの設定

モデルが DataChannel を介して返すメッセージをリッスンして、やり取りのシーケンスを正しく保ってください。

pc.ondatachannel = (event) => {
  const ch = event.channel;
  ch.onmessage = (e) => {
    let obj;
    try { obj = JSON.parse(e.data); }
    catch (err) {
      return;
    }
    if (obj?.type === "session.created") {
      sendUpdate(event.channel);
      // オーディオとビデオのプッシュを開始します
      audioSender?.replaceTrack(audioTrack);
      videoSender?.replaceTrack(videoTrack);
    }
  };
};

メディアデータの送受信

接続設定中に追加されたオーディオトラックとビデオトラック (RTP メディアチャネル) は、自動的にサーバーにデータを送信します。

  • オーディオ:オーディオトラック (RTP) を介して直接送信されます。input_audio_buffer.append イベントは不要です。
  • 画像:フレームはビデオトラック (RTP) を介して送信されます。input_image_buffer.append イベントはサポートされていません。

注記WebRTC は、サーバー側の VAD モード (server_vad または semantic_vad) のみをサポートします。マニュアルモードはサポートされていません。

デモのソースコード

前提条件

  • WebRTC をサポートする最新のブラウザ (Chrome、Edge、Firefox、Safari など)。
  • ブラウザにマイク権限が付与されていること。
  • ブラウザのオリジン間セキュリティポリシーにより、ブラウザから直接サーバーに接続リクエストを送信できません。ターミナルで curl コマンドを実行して接続を確立してください。

デモの実行

webrtc_demo.html という名前の HTML ファイルを作成し、次のコードをコピーしてください。

webrtc_demo.html

ブラウザでファイルを開き、次の手順に従ってください。

  1. [Start session] をクリックします。ページは自動的にオファー SDP と対応する curl コマンドを生成します。
  2. [Copy curl command] をクリックし、ターミナルでコマンドを実行します。コマンドはアンサー SDP を返します。
  3. アンサー SDP をページの [Answer SDP] テキストボックスに貼り付け、[Set Answer] をクリックして接続を確立し、音声会話を開始します。

WebSocket 接続

接続方法とフローはモデルによって異なります。詳細については、次をご参照ください。