シグナリングの型定義

この章ではシグナリングの型について説明します。 シグナリングの仕様については シグナリング を参照ください。

型の表記は TypeScript で記述します。

基本的なデータ型

// JSON 値を表します。
// 仕様は RFC 8259 に従います。
type JSONValue =
  | null
  | boolean
  | number
  | string
  | JSONValue[]
  | { [key: string]: JSONValue | undefined };

// UnixTime
// 例: 1704067199
type UnixTime = number;

// RFC3339 UTC (マイクロ秒)
// 例: 2023-12-31T23:59:59.999999Z
type Timestamp = string;

// ストリームの種別
type Role = "sendrecv" | "sendonly" | "recvonly";

// サイマルキャストで視聴する映像の種類
type SimulcastRid = "r0" | "r1" | "r2";

// 音声の設定
type Audio =
  | boolean
  | {
      codec_type?: AudioCodecType;
      bit_rate?: number;
      opus_params?: OpusParams;
    };

type OpusParams = {
  channels?: number;
  maxplaybackrate?: number;
  minptime?: number;
  ptime?: number;
  stereo?: boolean;
  sprop_stereo?: boolean;
  useinbandfec?: boolean;
  usedtx?: boolean;
};

// 映像の設定
type Video =
  | boolean
  | {
      codec_type?: VideoCodecType;
      bit_rate?: number;
      // 利用するには sora.conf で signaling_vp9_params = true を設定する必要があります
      vp9_params?: VP9Params;
      // 利用するには sora.conf で signaling_av1_params = true を設定する必要があります
      av1_params?: AV1Params;
      // 利用するには sora.conf で signaling_h264_params = true を設定する必要があります
      h264_params?: H264Params;
      // 利用するには sora.conf で signaling_h265_params = true を設定する必要があります
      h265_params?: H265Params;
    };

type VP9Params = {
  // 0..3
  profile_id?: number;
};

type AV1Params = {
  // 0..2
  profile?: number;
};

type H264Params = {
  profile_level_id?: string;
  // sora.conf で h264_b_frame = true を設定する必要があります
  b_frame?: boolean;
};

type H265Params = {
  level_id?: number;
  // sora.conf で h265_b_frame = true を設定する必要があります
  b_frame?: boolean;
};

// 音声コーデックの種類
type AudioCodecType = "OPUS";

// 映像コーデックの種類
type VideoCodecType = "VP9" | "VP8" | "AV1" | "H264" | "H265";

// DataChannel の方向
type Direction = "sendrecv" | "sendonly" | "recvonly";

type DataChannelMessagingHeaderFieldType = "sender_connection_id";

type DataChannelMessagingHeaderField = {
  type: DataChannelMessagingHeaderFieldType;
  // * length は "type": "offer" 時の data_channels にのみ含まれる
  // * length は"type": "connect" 時には指定できない
  // * length は認証成功時の払い出し時には指定できない
  length?: number;
};

// DataChannels
type DataChannel = {
  label: string;
  direction: Direction;
  ordered?: boolean;
  max_packet_life_time?: number;
  max_retransmits?: number;
  protocol?: string;
  compress?: boolean;
  header?: DataChannelMessagingHeaderField[];
};

type ForwardingFilterRuleField = "connection_id" | "client_id" | "kind";

type ForwardingFilterRuleOperator = "is_in" | "is_not_in";

type ForwardingFilterRuleKindValue = "audio" | "video";

type ForwardingFilterRule = {
  field: ForwardingFilterRuleField;
  operator: ForwardingFilterRuleOperator;
  values: [string];
};

type ForwardingFilterAction = "block" | "allow";

type ForwardingFilter = {
  version?: string;
  metadata?: JSONValue;
  name?: string;
  priority?: number;
  action?: ForwardingFilterAction;
  rules: [[ForwardingFilterRule]];
};

type SoraClientType =
  | "Sora JavaScript SDK"
  | "Sora iOS SDK"
  | "Sora Android SDK"
  | "Sora Unity SDK"
  | "Sora C++ SDK"
  | "Sora Python SDK"
  | "Sora C SDK"
  | "OBS-Studio-WHIP"
  | "OBS-Studio-WHEP";

// SoraClient
type SoraClient = {
  environment?: string;
  raw?: string;
  type?: SoraClientType;
  version?: string;
  commit_short?: string;
  libwebrtc?: string;
};

// RTCRtpCodecParameters
// https://www.w3.org/TR/webrtc/#dom-rtcrtpcodecparameters
type SimulcastCodec = {
  // payloadType や channels は省略
  mimeType: string;
  clockRate: number;
  sdpFmtpLine?: string;
};

// RTCRtpEncodingParameters
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpencodingparameters
type SimulcastEncoding = {
  // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodingparameters-rid
  rid: SimulcastRid;
  // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-active
  active?: boolean;
  // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxframerate
  maxFramerate?: number;
  // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxbitrate
  maxBitrate?: number;
  // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-scaleresolutiondownby
  scaleResolutionDownBy?: number;
  // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodec
  codec?: SimulcastCodec;
  // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-scaleresolutiondownto
  scaleResolutionDownTo?: number;
  // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime
  adaptivePtime?: boolean;
  // https://www.w3.org/TR/webrtc-svc/#dom-rtcrtpencodingparameters-scalabilitymode
  scalabilityMode?: string;
};

シグナリング

シグナリングは「クライアントからサーバー (Sora) に送信される」メッセージと「サーバー (Sora) からクライアントに送信される」メッセージに分かれます。

クライアントからサーバーに送信されるメッセージ

  • connect

  • answer

  • candidate

  • re-answer

  • pong

    • WebSocket 経路利用時のみ

  • disconnect

  • stats

    • DataChannel 経路利用時のみ

Server からクライアントに送信されるメッセージ

  • offer

  • re-offer

  • ping

    • WebSocket 経路利用時のみ

  • push

  • notify

  • req-stats

    • DataChannel 経路利用時のみ

完全な型定義

// シグナリング
type Signaling = ClientToServer | ServerToClient;

// クライアントからサーバーに送信されるメッセージ
type ClientToServer =
  | SignalingConnectMessage
  | SignalingAnswerMessage
  | SignalingCandidateMessage
  | SignalingReAnswerToServerMessage
  | SignalingPongMessage
  | SignalingDisconnectMessage;

// サーバーからクライアントに送信されるメッセージ
type ServerToClient =
  | SignalingRedirectMessage
  | SignalingOfferMessage
  | SignalingReOfferToClientMessage
  | SignalingPingMessage
  | SignalingPushMessage
  | SignalingNotifyMessage
  | SignalingSwitchedMessage
  | SignalingCloseMessage;

// type: "connect"
type SignalingConnectMessage = {
  type: "connect";
  role: Role;
  channel_id: string;

  client_id?: string;
  bundle_id?: string;

  audio?: Audio;
  video?: Video;

  // 未指定の場合は false として扱われます
  multistream?: boolean;

  simulcast?: boolean;
  simulcast_rid?: SimulcastRid;
  // sora.conf にて simulcast_multicodec = true を有効にする必要があります
  simulcast_multicodec?: boolean;

  spotlight?: boolean;
  // 非推奨です
  // session.created の戻り値をご利用ください
  spotlight_number?: number;
  spotlight_focus_rid?: SimulcastRid | "none";
  spotlight_unfocus_rid?: SimulcastRid | "none";

  metadata?: JSONValue;
  signaling_notify_metadata?: JSONValue;

  data_channel_signaling?: boolean;
  data_channels?: DataChannel[];
  ignore_disconnect_websocket?: boolean;

  forwarding_filters?: ForwardingFilter;
  // 2025 年 12 月リリースの Sora にて廃止します
  forwarding_filter?: ForwardingFilter;

  // type: redirect で戻されて再度 type: connect で接続するときに有効にする必要があります
  redirect?: boolean;

  audio_streaming_language_code?: string;

  sdp?: string;

  sora_client?: string;
  environment?: string;
  libwebrtc?: string;
};

type Mid = {
  audio?: string;
  video?: string;
};

// type: "redirect"
type SignalingRedirectMessage = {
  type: "redirect";
  location: string;
};

// type: "offer"
type SignalingOfferMessage = {
  type: "offer";
  sdp: string;

  mid: Mid;
  version: string;

  multistream: boolean;
  simulcast: boolean;
  simulcast_multicodec: boolean;
  spotlight: boolean;

  channel_id: string;
  session_id: string;
  client_id: string;
  bundle_id: string;
  connection_id: string;

  audio: boolean;
  audio_codec_type?: AudioCodecType;
  audio_bit_rate?: number;
  video: boolean;
  video_codec_type?: VideoCodecType;
  video_bit_rate?: number;

  metadata?: JSONValue;
  config?: JSONValue;
  encodings?: SimulcastEncoding[];

  data_channels?: DataChannel[];
};

// type: "answer"
type SignalingAnswerMessage = {
  type: "answer";
  sdp: string;
};

// type: "candidate"
type SignalingCandidateMessage = {
  type: "candidate";
  candidate: string;
};

// type: "re-offer"
// サーバーからクライアントに送信される
type SignalingReOfferToClientMessage = {
  type: "re-offer";
  sdp: string;
};

// type: "re-answer"
// クライアントからサーバーに送信される
type SignalingReAnswerToServerMessage = {
  type: "re-answer";
  sdp: string;
};

// type: "close"
// サーバーからクライアントに送信されるメッセージ
// サーバー側からの切断を通知するためのメッセージ
// data_channel_signaling = true かつ ignore_disconnect_websocket = true の場合のみ
// sora.conf にて data_channel_signaling_close_message = true を有効にする必要がある
type SignalingCloseMessage = {
  type: "close";
  reason: string;
  code: number;
};

// type: "ping"
type SignalingPingMessage = {
  type: "ping";
  stats?: boolean;
};

// type: "pong"
type SignalingPongMessage = {
  type: "pong";
  stats?: RTCStatsReport[];
};

// type: "push"
type SignalingPushMessage = {
  type: "push";
  data: Record<string, unknown>;
};

// type: "notify"
type SignalingNotifyMessage =
  | SignalingNotifyConnectionCreated
  | SignalingNotifyConnectionUpdated
  | SignalingNotifyConnectionDestroyed
  | SignalingNotifySpotlightFocused
  | SignalingNotifySpotlightUnfocused
  | SignalingNotifyRecordingStarted
  | SignalingNotifyRecordingStopped
  | SignalingNotifyForwardingBlocked
  | SignalingNotifyForwardingAllowed
  | SignalingNotifyNetworkStatus
  | SignalingNotifyRtpStreamPause
  | SignalingNotifyRtpStreamResume;

// 接続中のクライアントの情報
type SignalingNotifyMetadata = {
  client_id?: string;
  bundle_id?: string;
  connection_id?: string;
  authn_metadata?: JSONValue;
  authz_metadata?: JSONValue;
  metadata?: JSONValue;
};

// "connection.created",
type SignalingNotifyConnectionCreated = {
  type: "notify";
  event_type: "connection.created";
  role: Role;
  session_id?: string;
  client_id?: string;
  bundle_id?: string;
  connection_id?: string;
  audio?: boolean;
  video?: boolean;
  authn_metadata?: JSONValue;
  authz_metadata?: JSONValue;
  metadata?: JSONValue;
  data?: SignalingNotifyMetadata[];
  minutes: number;
  channel_connections: number;
  channel_sendrecv_connections: number;
  channel_sendonly_connections: number;
  channel_recvonly_connections: number;
  turn_transport_type: "udp" | "tcp";
};

// "connection.updated"
type SignalingNotifyConnectionUpdated = {
  type: "notify";
  event_type: "connection.updated";
  role: Role;
  session_id?: string;
  client_id?: string;
  bundle_id?: string;
  connection_id?: string;
  audio?: boolean;
  video?: boolean;
  authn_metadata?: JSONValue;
  authz_metadata?: JSONValue;
  metadata?: JSONValue;
  minutes: number;
  channel_connections: number;
  channel_sendrecv_connections: number;
  channel_sendonly_connections: number;
  channel_recvonly_connections: number;
  turn_transport_type: "udp" | "tcp";
};

// "connection.destroyed"
type SignalingNotifyConnectionDestroyed = {
  type: "notify";
  event_type: "connection.destroyed";
  role: Role;
  session_id?: string;
  client_id?: string;
  bundle_id?: string;
  connection_id?: string;
  audio?: boolean;
  video?: boolean;
  minutes: number;
  authn_metadata?: JSONValue;
  authz_metadata?: JSONValue;
  metadata?: JSONValue;
  channel_connections: number;
  channel_sendrecv_connections: number;
  channel_sendonly_connections: number;
  channel_recvonly_connections: number;
  turn_transport_type: "udp" | "tcp";
};

// "spotlight.focused"
type SignalingNotifySpotlightFocused = {
  type: "notify";
  event_type: "spotlight.focused";
  client_id: string | null;
  bundle_id: string | null;
  connection_id: string;
  audio: boolean;
  video: boolean;
  fixed: boolean;
};

// "spotlight.unfocused"
type SignalingNotifySpotlightUnfocused = {
  type: "notify";
  event_type: "spotlight.unfocused";
  client_id: string | null;
  bundle_id: string | null;
  connection_id: string;
  audio: boolean;
  video: boolean;
  fixed: boolean;
};

// "recording.started"
type SignalingNotifyRecordingStarted = {
  type: "notify";
  event_type: "recording.started";
  client_id: string | null;
  bundle_id: string | null;
  connection_id: string;
};

// "recording.stopped"
type SignalingNotifyRecordingStopped = {
  type: "notify";
  event_type: "recording.stopped";
  client_id: string | null;
  bundle_id: string | null;
  connection_id: string;
};

// "forwarding.blocked"
type SignalingNotifyForwardingBlocked = {
  type: "notify";
  event_type: "forwarding.blocked";
  kind: ForwardingFilterRuleKindValue;
  destination_connection_id: string;
  source_connection_id: string;
};

// "forwarding.allowed"
type SignalingNotifyForwardingAllowed = {
  type: "notify";
  event_type: "forwarding.allowed";
  kind: ForwardingFilterRuleKindValue;
  destination_connection_id: string;
  source_connection_id: string;
};

// "network.status"
type SignalingNotifyNetworkStatus = {
  type: "notify";
  event_type: "network.status";
  unstable_level: 0 | 1 | 2 | 3;
};

// "rtp_stream.pause"
type SignalingNotifyRtpStreamPause = {
  type: "notify";
  event_type: "rtp_stream.pause";
  recv_connection_id: string;
  send_connection_id: string;
};

// "rtp_stream.pause"
type SignalingNotifyRtpStreamResume = {
  type: "notify";
  event_type: "rtp_stream.resume";
  stream_id: string;
};

// type: "disconnect"
type SignalingDisconnectMessage = {
  type: "disconnect";
  reason: string;
};

// type: "stats"
// サーバーからクライアントに送信される
type DataChannelStatsToClientMessage = {
  type: "stats";
};

// type: "stats"
// クライアントからサーバーに送信される
type DataChannelStatsToServerMessage = {
  type: "stats";
  reports: RTCStatsReport[];
};

// type: "switched"
type SignalingSwitchedMessage = {
  type: "switched";
  ignore_disconnect_websocket: boolean;
};
© Copyright 2024, Shiguredo Inc Created using Sphinx 8.1.3