パブリッシャー優先 Video Codec API

パブリッシャーごとにコーデックのプリファレンスを設定し、それらのプリファレンスがネゴシエーションとどのように相互作用するかを理解し、ライブセッション中に実際に使用されているコーデックを確認するための実践的なガイド。

このトピックには以下のセクションが含まれます:

前提条件

SDKを通してPreferred Video Codec APIを使用する前に、プロジェクト設定で有効にする必要があります:

  1. に行く。 Video APIアカウント そして、プロジェクトを選択してください。
  2. プロジェクト設定で、プロジェクトレベルの優先ビデオコーデックを選択する。
  3. SDKレベルのコーデック環境設定を有効にするために必要な設定を適用します。

注: 選択したコーデックは、選択したプロジェクトにのみ影響します。サポートされているコーデックについては ビデオコーデック を案内する。

概要

Publisher Preferred Video Codec API を使用すると、各パブリッシャーが、プロジェクトレベルで Video APIアカウント.コーデックの順序付きリストを明示的に指定するか、または次のようにSDKに決定を委ねることができます。 自動モード.

重要だ: このAPIは プリファレンス制限ではない。優先コーデックが使用できない場合でも、他のコーデックをネゴシエー ションできる。優先順位は、SDPオファーに表示されるコーデックの順番に影響し、ネゴシエー ション時に優先順位が高くなる。

このAPIは、プロジェクト・レベルの設定がニーズに対して十分に具体的でない場合に使用する。よくあるシナリオは以下の通り:

  • デバイス混在のセッション。 同じセッション内で、異なるパブリッシャーが異なるコーデックの恩恵を受ける。パブリッシャーごとのプリファレンスにより、各デバイスは自分に最適なコーデックの順序を表現することができます。

  • 機能別パブリッシャー。 スクリーン共有のパブリッシャーはVP9の恩恵を受けるかもしれないが、同じセッションのカメラパブリッシャーは、より広い互換性のためにVP8を好む。

  • SDKに決めさせる。 リストをハードコードしたくない場合、自動モードはSDKに選択を委ねる。

もしあなたのアプリケーションのすべてのパブリッシャーが同じコーデックを使うべきで、プロジェクトレベルの設定がすでにその選択を反映しているなら、このAPIは必要ありません。

VP8は、すべてのエンドポイントでサポートされる実装必須のコーデックです。サポートされているコーデックはすべてフォールバックとして自動的に追加されるため、VP8をリストに明示的に含めなかったとしても、究極のフォールバックとして常に利用できます。

VP8、H.264、VP9コーデック自体の背景、コーデックカバレッジテーブル、プロジェクトレベルの優先コーデック設定については、以下を参照してください。 ビデオコーデック を案内する。

モードの選択

自動

文字列を渡す 'automatic' (Web、React Native)、またはネイティブSDKの対応するファクトリーメソッドを呼び出します。SDKはローカル環境を評価し、適切なコーデックの優先順位を決定します。

自動モードは次のような場合に使用する:

  • あなたは、独自のデバイスごとのロジックを維持することなく、SDKが異なるブラウザやデバイスに適応することを望んでいます。
  • あなたは前方互換性のあるアプローチを好みます。自動モードは、将来のSDKリリースでより洗練された選択ヒューリスティックを組み込む予定です。

注: 自動モードで使用されるヒューリスティックは、時間の経過とともに進化する。初期のリリースでは、ベースライン選択戦略が適用される。将来のSDKのバージョンでは、ハードウェアの能力、ネットワークの状態、セッションのトポロジーなどの追加的なシグナルが考慮されるかもしれません。リストをハードコードする特別な理由がない限り、自動モードを推奨されるデフォルトとして扱ってください。

マニュアル

コーデックの順序付き配列を提供する。最初の要素が最も高い優先度を持つ:

['vp9', 'vp8']          prefer VP9, fall back to VP8, then remaining codecs
['h264']                 prefer H.264; remaining codecs (VP8, VP9) are appended automatically as fallbacks
['vp8', 'h264', 'vp9']  explicit full ordering: VP8 first, then H.264, then VP9

手動モードは、特定のパブリッシャーやデバイスに最適なコーデックの順序を正確に把握している場合に使用します。この設定は、ダッシュボードで設定されたプロジェクトレベルの優先コーデックよりも優先されます。

注: あなたが指定したコーデックは優先順位を定義しますが、残りのすべてのサポートされているコーデックは、常にフォールバックとして追加されます。例えば ['vp9'] はVP9が優先されるが、VP9が利用できない場合はVP8とH.264もネゴシエーション可能であることを意味する。

デフォルト

を設定しない場合 preferredVideoCodecs を全く使用しない場合、パブリッシャーはダッシュボードで設定された プロジェクトレベルの優先コーデックを使用します。これはこのAPIが存在する前と同じ動作です。

比較

モード 使用時期 将来性?
自動 SDKに最適な順序を選択させたい SDKのアップデートによるメリット
マニュアル一覧 このパブリッシャーの正確なコーデック順をご存知ですか? いいえ、あなたがリストを管理するのです
デフォルト プロジェクトレベルの設定で十分 該当なし、プロジェクト設定を使用

一般的なシナリオで推奨されるコーデックの順序

手動モードを使用する場合、コーデックの順序は、セッションのタイプ、視聴者、ユースケースによって異なります。以下の表は、一般的なシナリオと推奨されるコーデックの順番を示しています。 preferredVideoCodecs 価値とその理由。

シナリオ 推奨オーダー なぜ
大規模セッション/ウェビナー(ルーティング) ['vp9', 'vp8'] VP9とVP8の両方が対応しています スケーラブルなビデオ、これは多数の加入者が参加するセッションには不可欠です。VP9は圧縮効率に優れており、同等の画質を得るために必要な帯域幅が少なくて済みます。VP8は、VP9スケーラブルビデオが利用できないエンドポイント向けのフォールバックとして機能します( コーデック・カバレッジ・テーブル).スケーラブル・ビデオのH.264はプラットフォームでサポートされていないため、大規模なセッションにはH.264を避け、代わりにVP8またはVP9を使用する必要があります。
小規模セッション、iOS専用デバイス ['h264', 'vp8'] iOSデバイスは、CPU負荷を軽減し、バッテリー寿命を向上させるハードウェアアクセラレーションH.264を備えています。VP8は安全なフォールバックとして残っている。
小規模なセッション、帯域幅に制約がある ['vp9', 'vp8'] VP9は、同じビットレートでVP8よりも優れた品質を実現します。VP8は、VP9をサポートしていないエンドポイント(古いバージョンのSafariなど)のためのフォールバックです。
スクリーン共有パブリッシャー ['vp9', 'vp8'] VP9はシャープエッジや静的領域の処理に優れているため、スクリーンコンテンツは非常に効率的に圧縮される。VP8はフォールバックです。
最適な圧縮率で画面共有 ['vp9'] シャープエッジやスタティックリージョンの処理に優れているVP9を推奨する。他のサポートされているコーデックは、フォールバックとして低い優先度でネゴシエートされる。
最大限の互換性(すべてのデバイスに届くこと) ['vp8'] VP8は、Linux SDK(H.264をサポートしていない)や古いSafari(VP9をサポートしていない場合がある)を含む、すべてのOpenTokエンドポイントでサポートされている唯一のコーデックです。

ヒント 上記のシナリオのいずれにも当てはまらない場合は、次のような使い方を検討してください。 自動モード を代わりに使用します。これは、SDKにローカル環境に基づいて最適な順序を選択させるもので、将来のリリースでは改良されたヒューリスティックを組み込む予定である。

コーデック・ネゴシエーションの仕組み

優先コーデックの設定 違う コーデックが使用されることを保証する。最終的なコーデックは、セッションタイプに依存するネゴシエーションプロセスによって決定される。

ルーティングセッション(メディアルーター)

においてである。 ルーティングセッション, パブリッシャーは OpenTok Media Router と通信を行います:

  1. パブリッシャは、優先順位に従ってコーデックを並べたSDPオファーを送信する (優先コーデックが最初に表示される)。
  2. メディア・ルーターはオファーを検討し、サポートするコーデックを選択する。
  3. 優先コーデックがサポートされていれば、それが使用される。そうでない場合、メディア・ルーターは次のコーデックにフォールバックする。

メディアルーターはメディア配信を処理するので、ルーティングされたセッションのすべての加入者は、パブリッシャーがネゴシエートしたのと同じコーデックでエンコードされたビデオを受信する。

中継セッション(ピアツーピア)

においてである。 中継セッションメディアルーターは存在しない。各パブリッシャーとサブスクライバーのペアは独立してネゴシエーションを行う:

  1. パブリッシャーは、優先度順にコーデックを並べたSDPオファーを送信する。
  2. 加入者は、サポートするコーデックをリストしたSDPアンサーで応答する。
  3. ペアは、両方のエンドポイントがサポートする最も優先度の高いコーデックを選択する。

つまり、同じ中継セッション内の異なる加入者ペアは、それぞれの加入者の能力に応じて、異なるコーデックを使用することになる。

何がフォールバックを引き起こすのか?

フォールバックとは、優先コーデックが使用されず、代わりに別のコーデックがパブリッシングに選択されたことを意味します。これは次のような場合に起こります:

  • 優先コーデックは、リモートエンドポイント(中継セッション)またはメディアルーター(ルーティングセッション)でサポートされていません。
  • ブラウザまたはデバイスが、優先コーデックによるエンコードをサポートしていない(例:一部のAndroidデバイスではH.264、古いバージョンのSafariではVP9)。

フォールバックが発生する可能性があるため、プリファレンスが守られたと考えるのではなく、常に使用中のコーデックをVerifyしてください。アクティブなコーデックを知っておくと便利です:

  • デバッグと品質監視 どのコーデックが使用されているかをログに記録し、Insightsによる診断や品質分析に役立てることができます。
  • 実行時に適応させる。 ネゴシエートされたコーデックの長所に基づいて、解像度やビットレートの設定を調整する(例えば、VP9はVP8よりも低いビットレートで同じ品質を実現できる)。
  • セッションの一貫性を確保する。 セッション内のすべてのパブリッシャーが期待されるコーデックを使用していることを確認する。特に、メディアルーターがパブリッシャーごとに単一のコーデックをすべてのサブスクライバーに配布するルーティングセッションの場合。

参照 使用コーデックのベリファイ をご覧ください。

プラットフォーム別の環境設定

ウェブSDK


export type VideoCodec = 'vp8' | 'vp9' | 'h264';
export type PreferredVideoCodecs = 'automatic' | [VideoCodec, ...VideoCodec[]];

// Automatic mode
const publisher = OT.initPublisher('publisherContainer', {
  preferredVideoCodecs: 'automatic'
});

// Manual mode
const publisher = OT.initPublisher('publisherContainer', {
  preferredVideoCodecs: ['vp9', 'vp8']
});

// Default (uses project-level preferred codec)
const publisher = OT.initPublisher('publisherContainer', {});

空の配列や無効なコーデック文字列を渡すと、パブリッシャーは OT_INVALID_PARAMETER エラー。

iOS SDK


// Automatic mode
OTVideoCodecPreference *pref = [OTVideoCodecPreference automatic];
OTPublisherKitSettings *settings = [[OTPublisherKitSettings alloc] init];
settings.videoCodecPreference = pref;
OTPublisherKit *publisher = [[OTPublisherKit alloc] initWithDelegate:self
                                                            settings:settings];

// Manual mode
OTVideoCodecPreference *pref = [OTVideoCodecPreference manualWithCodecs:@[
    @(OTVideoCodecTypeVP9),
    @(OTVideoCodecTypeH264),
    @(OTVideoCodecTypeVP8)
]];
OTPublisherKitSettings *settings = [[OTPublisherKitSettings alloc] init];
settings.videoCodecPreference = pref;

アンドロイドSDK


// Automatic mode
PublisherKit.PreferredVideoCodecs preferredVideoCodecs =
    PublisherKit.PreferredVideoCodecs.automatic();

Publisher publisher = new Publisher.Builder(context)
    .preferredVideoCodecs(preferredVideoCodecs)
    .build();

// Manual mode
PublisherKit.PreferredVideoCodecs preferredVideoCodecs =
    PublisherKit.PreferredVideoCodecs.manual(
        new ArrayList<PublisherKit.PreferredVideoCodecs.Codec>(
            List.of(PublisherKit.PreferredVideoCodecs.Codec.VP9,
                    PublisherKit.PreferredVideoCodecs.Codec.H264)));

Publisher publisher = new Publisher.Builder(context)
    .preferredVideoCodecs(preferredVideoCodecs)
    .build();

を渡す。 null または空のリストを manual() スロー IllegalArgumentException.

Windows SDK


// Automatic mode
builder.PreferredVideoCodecs = PreferredVideoCodecs.Automatic();

// Manual mode
builder.PreferredVideoCodecs = new PreferredVideoCodecs(
    new List<PreferredVideoCodecs.Codec> {
        PreferredVideoCodecs.Codec.VP9,
        PreferredVideoCodecs.Codec.H264,
        PreferredVideoCodecs.Codec.VP8
    });

// Default (uses project-level setting)
builder.PreferredVideoCodecs = null;

空のリストを渡すと ArgumentException.

Linux SDK


// Automatic mode
otc_publisher_settings* settings = otc_publisher_settings_new();
otc_publisher_settings_set_preferred_video_codecs_automatic(settings);

otc_publisher_callbacks callbacks = {0};
struct otc_publisher* publisher =
    otc_publisher_new_with_settings(&callbacks, settings);
otc_publisher_settings_delete(settings);

// Manual mode
otc_publisher_settings* settings = otc_publisher_settings_new();

otc_video_codec_type codecs[] = {
    OTC_VIDEO_CODEC_VP9,
    OTC_VIDEO_CODEC_H264,
    OTC_VIDEO_CODEC_VP8
};

otc_publisher_settings_set_preferred_video_codecs(
    settings, codecs, sizeof(codecs) / sizeof(codecs[0]));

otc_publisher_callbacks callbacks = {0};
struct otc_publisher* publisher =
    otc_publisher_new_with_settings(&callbacks, settings);
otc_publisher_settings_delete(settings);

リアクト・ネイティブSDK


// Automatic mode
<OTPublisher properties={{ preferredVideoCodecs: 'automatic' }} />

// Manual mode
<OTPublisher properties={{ preferredVideoCodecs: ['vp9', 'vp8'] }} />

使用コーデックのベリファイ

パブリッシャーがストリーミングを開始した後、SDKの統計APIを使って、実際にどのコーデックがネゴシエートされたかを確認してください。プリファレンスが守られたと思わないでください。

公開前に対応コーデックを確認する

プリファレンスを設定する前に、クライアントがサポートしているコーデックを積極的にチェックすることができます。

ウェブSDK:


const supportedCodecs = await OT.getSupportedCodecs();
console.log('Encoders:', supportedCodecs.videoEncoders);
console.log('Decoders:', supportedCodecs.videoDecoders);

Android SDK:


MediaUtils.SupportedCodecs supported =
    MediaUtils.SupportedCodecs.getSupportedCodecs(context);
Log.d("Codecs", "Encoders: " + supported.videoEncoders);
Log.d("Codecs", "Decoders: " + supported.videoDecoders);

Linux SDK:


otc_media_utils_codecs* supported_codecs = NULL;
otc_status status = otc_media_utils_get_supported_codecs(&supported_codecs);
if (status == OTC_SUCCESS) {
  for (size_t i = 0; i < supported_codecs->number_encoder_video_codecs; i++) {
    printf("Encoder: %d\n", supported_codecs->encoder_video_codecs[i]);
  }
  for (size_t i = 0; i < supported_codecs->number_decoder_video_codecs; i++) {
    printf("Decoder: %d\n", supported_codecs->decoder_video_codecs[i]);
  }
  otc_media_utils_codecs_delete(supported_codecs);
}

SDK統計からアクティブなコーデックを読み取る

注: SDK統計からアクティブなコーデックを読み取るには、Web SDK 2.33以降が必要です。このバージョンでは、Statsオブジェクトでコーデック情報を公開するClient Observability APIが導入されました。

ウェブSDK

出版社


setInterval(() => {
  publisher.getStats((error, statsArray) => {
    if (error) return;
    statsArray.forEach(({ stats }) => {
      if (stats.video && stats.video.layers) {
        stats.video.layers.forEach((layer) => {
          console.log('Publisher video codec:', layer.codec);
        });
      }
    });
  });
}, 5000);

加入者


setInterval(() => {
  subscriber.getStats((error, stats) => {
    if (error) return;
    if (stats.video) {
      console.log('Subscriber video codec:', stats.video.codec);
    }
  });
}, 5000);

より低レベルのWebRTC情報については getRtcStatsReport():


publisher.getRtcStatsReport()
  .then(statsArray => {
    // Each entry contains a standard RTCStatsReport.
    // Look for type "codec" entries with mimeType.
    statsArray.forEach(console.log);
  });

アンドロイドSDK


publisher.setNetworkStatsListener(new PublisherKit.NetworkStatsListener() {
    @Override
    public void onVideoStats(PublisherKit publisher,
                             PublisherKit.PublisherVideoStats[] statsArray) {
        if (statsArray != null && statsArray.length > 0) {
            for (PublisherKit.VideoLayerStats layer : statsArray[0].videoLayers) {
                Log.d("Codec", "Publisher codec: " + layer.codec);
            }
        }
    }
});

iOS SDK


- (void)publisher:(OTPublisherKit *)publisher
videoNetworkStatsUpdated:(NSArray<OTPublisherKitVideoNetworkStats *> *)statsArray {
    OTPublisherKitVideoNetworkStats *stats = statsArray.firstObject;
    for (OTPublisherKitVideoLayerStats *layer in stats.videoLayers) {
        NSLog(@"Publisher codec: %@", layer.codec ?: @"unknown");
    }
}

リアクト・ネイティブSDK


// Publisher
OTPublisher.getRtcStatsReport();

// Subscriber
OTSubscriber.getRtcStatsReport(streamId);

インサイトとビデオ・インスペクターの使用

ビデオ・インスペクタ・ツールでは、コーデック、解像度、フレームレートが品質メトリッ ク・モジュールに表示されます。プロットされた線上の任意のポイントにマウスオーバーすると、その時点で使用されているコーデックが表示されます。

でコーデック別にストリーム統計をフィルタリングすることもできます。 インサイト GraphQLクエリ:


{
  project(projectId: YOUR_PROJECT_ID) {
    sessionData {
      sessions(start: START_TIME, end: END_TIME) {
        resources {
          streamStatsCollection(filters: { videoCodec: VP9 }) {
            resources {
              createdAt
              videoBitrateKbps
            }
          }
        }
      }
    }
  }
}

ベストプラクティス

  1. セッションのタイプを考える。 ルーティングされたセッションでは、すべての加入者は1つのパブリッシャー につき1つのコーデックを共有する。リレイセッションでは、各ペアは独立にネゴシエートするので、同じパブリッシャー が異なるサブスクライバーに異なるコーデックを使うことができる。

  2. 出版社ごとの設定とプロジェクトレベルの設定を合わせる。 プロジェクトレベルの優先コーデックは、独自の優先順位を設定しないパブリッシャーにも適用されます。サプライズを避けるために、両方のレベルが一貫していることを確認してください。

  3. クライアントのコーデックサポートを確認する。 手動でプリファレンスを設定する前に OT.getSupportedCodecs() (ウェブ)または MediaUtils.SupportedCodecs (Android)を使って、好みのコーデックがローカルで利用可能であることを確認する。

  4. 自動モードから始める。 特定のコーデック要件がない限り、自動モードを使用し、SDKに選択させてください。将来のSDKリリースでは、自動選択のヒューリスティックが改良され、あなたのアプリケーションはコードを変更することなく恩恵を受けるでしょう。

  5. ネゴシエートされたコーデックを検証する。 用途 getStats() または getRtcStatsReport() をクリックして、パブリッシング開始後にコーデックを確認してください。

  6. 対象デバイスを横断してテストする。 コーデックのサポートは、ブラウザやプラットフォームによって異なります。詳しくは コーデック・カバレッジ・テーブル をご覧ください。ユーザーが実際に使用するデバイスで、環境設定をテストしてください。