パブリッシャー優先 Video Codec API
パブリッシャーごとにコーデックのプリファレンスを設定し、それらのプリファレンスがネゴシエーションとどのように相互作用するかを理解し、ライブセッション中に実際に使用されているコーデックを確認するための実践的なガイド。
このトピックには以下のセクションが含まれます:
前提条件
SDKを通してPreferred Video Codec APIを使用する前に、プロジェクト設定で有効にする必要があります:
- に行く。 Video APIアカウント そして、プロジェクトを選択してください。
- プロジェクト設定で、プロジェクトレベルの優先ビデオコーデックを選択する。
- 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 と通信を行います:
- パブリッシャは、優先順位に従ってコーデックを並べたSDPオファーを送信する (優先コーデックが最初に表示される)。
- メディア・ルーターはオファーを検討し、サポートするコーデックを選択する。
- 優先コーデックがサポートされていれば、それが使用される。そうでない場合、メディア・ルーターは次のコーデックにフォールバックする。
メディアルーターはメディア配信を処理するので、ルーティングされたセッションのすべての加入者は、パブリッシャーがネゴシエートしたのと同じコーデックでエンコードされたビデオを受信する。
中継セッション(ピアツーピア)
においてである。 中継セッションメディアルーターは存在しない。各パブリッシャーとサブスクライバーのペアは独立してネゴシエーションを行う:
- パブリッシャーは、優先度順にコーデックを並べたSDPオファーを送信する。
- 加入者は、サポートするコーデックをリストしたSDPアンサーで応答する。
- ペアは、両方のエンドポイントがサポートする最も優先度の高いコーデックを選択する。
つまり、同じ中継セッション内の異なる加入者ペアは、それぞれの加入者の能力に応じて、異なるコーデックを使用することになる。
何がフォールバックを引き起こすのか?
フォールバックとは、優先コーデックが使用されず、代わりに別のコーデックがパブリッシングに選択されたことを意味します。これは次のような場合に起こります:
- 優先コーデックは、リモートエンドポイント(中継セッション)またはメディアルーター(ルーティングセッション)でサポートされていません。
- ブラウザまたはデバイスが、優先コーデックによるエンコードをサポートしていない(例:一部の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つのコーデックを共有する。リレイセッションでは、各ペアは独立にネゴシエートするので、同じパブリッシャー が異なるサブスクライバーに異なるコーデックを使うことができる。
-
出版社ごとの設定とプロジェクトレベルの設定を合わせる。 プロジェクトレベルの優先コーデックは、独自の優先順位を設定しないパブリッシャーにも適用されます。サプライズを避けるために、両方のレベルが一貫していることを確認してください。
-
クライアントのコーデックサポートを確認する。 手動でプリファレンスを設定する前に
OT.getSupportedCodecs()(ウェブ)またはMediaUtils.SupportedCodecs(Android)を使って、好みのコーデックがローカルで利用可能であることを確認する。 -
自動モードから始める。 特定のコーデック要件がない限り、自動モードを使用し、SDKに選択させてください。将来のSDKリリースでは、自動選択のヒューリスティックが改良され、あなたのアプリケーションはコードを変更することなく恩恵を受けるでしょう。
-
ネゴシエートされたコーデックを検証する。 用途
getStats()またはgetRtcStatsReport()をクリックして、パブリッシング開始後にコーデックを確認してください。 -
対象デバイスを横断してテストする。 コーデックのサポートは、ブラウザやプラットフォームによって異なります。詳しくは コーデック・カバレッジ・テーブル をご覧ください。ユーザーが実際に使用するデバイスで、環境設定をテストしてください。