Skip to content

インストールとテスト

本ドキュメントでは、Volcano Engineの音声サービスを統合し、基本的なテストを完了する方法を説明します。Volcano Engineは複数プラットフォーム向けのSDKを提供しており、本ガイドではWeb SDK(@volcengine/rtc)を例に統合手順を解説します。

前提条件

統合を開始する前に、必要なVolcano Engineサービスが有効化され、認証情報が設定されていることを確認してください。詳細な手順はクイックスタート – Volcano Engine認証情報を参照してください。

必要な認証情報:

認証情報用途
AppId / AppKeyRTCルーム接続およびトークン生成
AccessKeyId / SecretKeyOpenAPIリクエスト署名
ASR AppId音声認識サービス
TTS AppId / TTS Token / TTS ResourceId音声合成サービス

認証プロキシサービス

クライアントはRTCルームに参加するためにトークンが必要であり、そのトークンはAppKeyを用いて生成されます。音声セッションの開始にはStartVoiceChat APIの呼び出しが必要で、こちらはAccessKeyで署名しなければなりません。これらの認証情報はクライアントに公開してはならないため、認証プロキシサービスを用意します。

プロキシサービスの役割:

  • AppKeyを用いたRTCトークンの生成
  • AccessKeyを用いたVolcano Engine OpenAPIの呼び出し
  • クライアントへのTokenおよびルーム情報の返却

RTCトークンの生成

TokenはHMAC-SHA256アルゴリズムを用いてAppKeyから生成されます。

言語参照実装
Node.js / Buntoken.ts
typescript
import { AccessToken, Privileges } from './rtctoken'

const token = new AccessToken(appId, appKey, roomId, userId)
token.addPrivilege(Privileges.PrivPublishStream, expireTime)
const tokenString = token.serialize()  // クライアントへ返却

Volcano Engine OpenAPIの呼び出し

StartVoiceChatStopVoiceChatなどのAPIは、AccessKeyIdSecretKeyを用いたV4署名が必要です。公式OpenAPI SDKには署名用のSignerクラスが提供されています。

bash
# Node.js / Bun
npm install @volcengine/openapi

# Python
pip install volcengine-python-sdk

# Go
go get github.com/volcengine/volc-sdk-golang
typescript
// Node.js例
import { Signer } from '@volcengine/openapi'

const body = { AppId: appId, RoomId: roomId, /* ... */ }

// リクエストデータの構築
const openApiRequestData = {
  region: 'cn-north-1',
  method: 'POST',
  params: {
    Action: 'StartVoiceChat',
    Version: '2024-12-01',
  },
  headers: {
    Host: 'rtc.volcengineapi.com',
    'Content-Type': 'application/json',
  },
  body,
}

// Signerを作成し認証ヘッダーを追加
const signer = new Signer(openApiRequestData, 'rtc')
signer.addAuthorization({
  accessKeyId: process.env.ACCESS_KEY_ID,
  secretKey: process.env.SECRET_KEY,
})

// リクエスト送信(ヘッダーに署名が含まれる)
const response = await fetch(
  'https://rtc.volcengineapi.com?Action=StartVoiceChat&Version=2024-12-01',
  {
    method: 'POST',
    headers: openApiRequestData.headers,
    body: JSON.stringify(body),
  }
)

署名ルールの詳細はVolcano Engine V4署名アルゴリズムを参照してください。

API設計例

プロキシサービスはクライアント用に以下のAPIを公開します。

typescript
// シーン設定取得 – Tokenとルーム情報を返す
GET /api/scenes
Response: {
  scenes: [{
    id: string,
    rtcConfig: { appId: string, roomId: string, userId: string, token: string }
  }]
}

// 音声セッション開始
POST /api/voice/start
Request:  { sceneId: string }
Response: { success: boolean }

// 音声セッション停止
POST /api/voice/stop
Request:  { sceneId: string }
Response: { success: boolean }

サーバー側実装のポイント:

  • シーン設定:サーバーは初期化時に各シーンごとにroomId(UUID)とuserIdを生成し、AppKeyで対応するRTCトークン(有効期限24時間)を生成します。クライアントは/api/scenes経由でこれらの情報を取得し、RTCルームに参加します。
  • トークン利用:クライアントはRTC SDKのjoinRoomメソッドにトークンを渡して認証します。
  • 音声セッションの開始/停止:サーバーはsceneIdでシーン設定を検索し、roomIdなどのパラメータを取得後、Volcano Engine OpenAPIのStartVoiceChatStopVoiceChatを呼び出します。

Web統合

Volcano EngineはWeb統合用に@volcengine/rtc SDKを提供しています。クライアントとサーバー間のやり取りの流れは以下の通りです。

通話フロー

SDKのインストール

bash
npm install @volcengine/rtc

AIノイズリダクションには@volcengine/rtc/extension-ainr拡張機能が含まれています。

基本的な統合フロー

1. シーン設定の取得

RTC SDKを使用する前に、サーバーAPIを呼び出してシーン設定(Tokenやルーム情報)を取得します。

typescript
// サーバーAPIを呼び出してシーン設定を取得
const response = await fetch('/api/scenes')
const { scenes } = await response.json()

// 対象シーンを選択
const scene = scenes.find(s => s.id === 'your-scene-id') || scenes[0]
const { appId, roomId, token, userId } = scene.rtcConfig

2. RTCエンジンの作成

typescript
import VERTC, { RoomProfileType, MediaType } from '@volcengine/rtc'

// サーバーから取得したappIdを使ってエンジンを作成
const engine = VERTC.createEngine(appId)

3. イベントリスナーの登録

typescript
// エラーを監視
engine.on(VERTC.events.onError, (event) => {
  console.error('RTCエラー:', event.errorCode)
})

// リモートユーザーのストリーム公開を監視(AI音声応答)
engine.on(VERTC.events.onUserPublishStream, async (event) => {
  const { userId, mediaType } = event
  // リモートの音声ストリームをサブスクライブ
  await engine.subscribeStream(userId, mediaType)
})

// バイナリメッセージ(字幕、ステータスなど)を受信
engine.on(VERTC.events.onRoomBinaryMessageReceived, (event) => {
  const { message } = event
  // messageはTLV形式のArrayBuffer
  // ASR結果、TTSテキスト、エージェントステータスなどを含む
})

4. ルームに参加

typescript
// ステップ1で取得したtoken、roomId、userIdを使ってルームに参加
await engine.joinRoom(
  token,
  roomId,
  {
    userId: userId,
    extraInfo: JSON.stringify({
      call_scene: 'RTC-AIGC',
      user_name: userId,
    }),
  },
  {
    isAutoPublish: false,
    isAutoSubscribeAudio: false,
    roomProfileType: RoomProfileType.chat,
  }
)

5. マイクを開始し音声をパブリッシュ

typescript
// マイクキャプチャを開始
await engine.startAudioCapture()

// 音声ストリームをルームにパブリッシュ
await engine.publishStream(MediaType.AUDIO)

6. 音声セッションの開始

音声ストリームをパブリッシュした後、サーバーAPIを呼び出してAI音声セッションを開始します。

typescript
// 音声セッション開始
await fetch('/api/voice/start', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sceneId: scene.id }),
})

ここで音声対話が開始されます。ユーザーの発話はASRで認識され、LLMで処理され、TTSで再生されます。

7. ルームから退出

typescript
// パブリッシュ停止
await engine.unpublishStream(MediaType.AUDIO)

// キャプチャ停止
await engine.stopAudioCapture()

// ルーム退出
await engine.leaveRoom()

// エンジン破棄
VERTC.destroyEngine(engine)

// サーバーAPIを呼び出して音声セッション停止
await fetch('/api/voice/stop', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sceneId: scene.id }),
})

AIノイズリダクション(任意)

Volcano Engine RTC SDKには環境ノイズを効果的に除去するAIノイズリダクション拡張が含まれています。

typescript
import RTCAIAnsExtension, { AnsMode } from '@volcengine/rtc/extension-ainr'

// 拡張機能を作成して登録
const aiAnsExtension = new RTCAIAnsExtension()
engine.registerExtension(aiAnsExtension)

// サポート確認
const supported = await aiAnsExtension.isSupported()
if (supported) {
  // ノイズリダクションモード設定:LOW / MEDIUM / HIGH
  await aiAnsExtension.setAnsMode(AnsMode.MEDIUM)
  // ノイズリダクション有効化
  aiAnsExtension.enable()
}

リモート音声ストリームの受信

リモートストリームをサブスクライブした後、MediaStreamを取得して再生できます。

typescript
import { StreamIndex } from '@volcengine/rtc'

// リモートユーザーの音声トラックを取得
const audioTrack = engine.getRemoteStreamTrack(userId, StreamIndex.STREAM_INDEX_MAIN, 'audio')

// MediaStreamを作成し再生
const stream = new MediaStream()
if (audioTrack) {
  stream.addTrack(audioTrack)
}

// audio要素にバインドして再生
const audioElement = document.querySelector('audio')
audioElement.srcObject = stream

他プラットフォーム向けSDK

Volcano Engine RTC SDKはソフトウェアアプリケーションとハードウェアデバイスの両方をサポートしています。

ソフトウェアアプリケーション

参照:リアルタイム会話型AI統合(ソフトウェアアプリケーション)

プラットフォームSDKドキュメント
Web@volcengine/rtcWeb SDKドキュメント
iOSVolcEngineRTCiOS SDKドキュメント
AndroidVolcEngineRTCAndroid SDKドキュメント
WindowsVolcEngineRTCWindows SDKドキュメント
macOSVolcEngineRTCmacOS SDKドキュメント
LinuxVolcEngineRTCLinux SDKドキュメント
Fluttervolc_engine_rtcFlutter SDKドキュメント
Electron@volcengine/rtcElectron SDKドキュメント

ハードウェアデバイス

参照:リアルタイム会話型AI統合(組み込みハードウェア)

Embedded Linux、RTOS、Androidなどのハードウェアプラットフォームに対応しています。ハードウェアSDKはVolcano Engineの技術サポートに問い合わせて入手してください。

テストと検証

RTC接続の確認

ルーム参加成功後、以下のイベントで確認できます。

typescript
engine.on(VERTC.events.onUserJoined, (event) => {
  console.log('ユーザーが参加しました:', event.userInfo.userId)
})

音声認識の確認

マイクに向かって話し、onRoomBinaryMessageReceivedでバイナリメッセージを受信します。メッセージはTLVエンコードされており、以下を含みます。

  • 字幕メッセージ:ASR結果およびLLM応答テキスト
  • ステータスメッセージ:エージェント状態(リスニング/思考中/発話中)
  • 関数呼び出し:ツール呼び出しリクエスト

音声合成の確認

AI応答はリモート音声ストリームで再生されます。以下を確認してください。

  1. onUserPublishStreamが処理されている
  2. subscribeStreamが呼ばれている
  3. 音声トラックが<audio>要素にバインドされている

よくある問題

接続と認証

問題考えられる原因対処方法
無効なトークン(token_errorトークンの有効期限切れまたはパラメータ不一致トークン生成時のUserIdとRoomIdが参加時と一致しているか確認、またはトークンを再生成
ルームに参加できないネットワーク障害またはAppId誤りネットワーク接続を確認し、AppIdを正しく設定しているか確認
Invalid 'Authorization' headerAK/SK設定誤りサーバーのAccessKeyIdとSecretKeyを検証
クロスサービス呼び出し失敗クロスサービス認可未設定RTCコンソールでクロスサービス認可を完了させる

エージェント起動

問題考えられる原因対処方法
StartVoiceChat失敗署名エラーまたはパラメータ不足API署名と必須パラメータを検証
The task has been startedエラー固定のRoomId/UserIdで繰り返し呼び出し先にStopVoiceChatを呼び出し、その後StartVoiceChatを再度呼び出す
「AI準備中」で停止権限不足/パラメータエラー/残高不足1) コンソールの権限確認 2) パラメータの型・大文字小文字確認 3) サービス有効化と残高確認
デジタルアバターが準備中のまま同時接続数制限または設定エラーアバターのAppId/Tokenを検証し、同時接続数制限を超えていないか確認

デバイスとメディア

問題考えられる原因対処方法
マイク/カメラが起動しないセキュアでないコンテキストページがlocalhostまたはhttpsでアクセスされているか確認
デバイス権限拒否ブラウザの許可がないWebデバイス権限トラブルシューティングを参照
ASR結果がないマイク許可なしまたはASR未有効ブラウザのマイク許可を確認し、ASRサービスが有効か確認
TTS音声が出ないリモート音声をサブスクライブしていないリモート音声ストリームに対してsubscribeStreamを呼んでいるか確認

モデル設定

問題対処方法
サードパーティモデルやCoze Botを使用LLMConfigでモデルパラメータを設定し、ModeCustomLLMにしてコールバックURLを指定
会話で応答がないLLM設定を検証し、CustomLLMコールバックサービスが稼働しているか確認

関連リソース