ApsaraVideo Liveは、Web上での共同ストリーミングをサポートしています。 視聴者は、ウェブページ上でストリーマと対話するための共同ストリーマになることができ、追加のアプリケーションをインストールする必要がなくなります。 このトピックでは、web上でコストリーミングを実装する方法と、関連するサンプルコードについて説明します。
コストリーミングの実装方法の概要
Push SDKは、ApsaraVideo Real-time Communication (ARTC) に基づくコストリーミングを実装しています。 これにより、ユーザーはより多くの人を超低遅延で引き付けるインタラクティブなストリーミングを開始できます。
共同ストリーミングの前: ストリーマーはARTCベースの共同ストリーミングの取り込みURLを使用してストリームを取り込み、ビューアはCDNからストリームをプルします。
コストリーミング中: 視聴者はコストリーマになります。 コストリーマは、ARTCベースのコストリーミング用の取り込みURLを使用してストリームを取り込み、ARTCベースのコストリーミング用のストリーミングURLを使用して、ストリーマのストリームを超低レイテンシでプルする。 ストリーマは、ARTCベースのコストリーミング用のストリーミングURLを使用して、コストリーマのストリームを超低レイテンシでプルします。
コストリーミング後: コストリーマは普通の視聴者になります。 視聴者によるARTCベースのストリーム取り込みおよびストリームプルは停止される。 視聴者はCDNからストリームを再度取得します。
使用上の注意
コストリーミングモードでは、ストリーマーとコストリーマーはAlivcLivePlayerオブジェクトのみを使用して、お互いのストリームを再生できます。 AlivcLivePlayerオブジェクトは、URLが
artc://live.aliyun.com/play/
で始まるストリームのみをサポートします。次のセクションでは、web上で共同ストリーミング機能を使用する方法について説明します。 Web用コストリーミングSDKを統合する方法の詳細については、「Web用コストリーミングSDKの統合」をご参照ください。
重要2024年3月15日に、共同ストリーミングSDK for Webのアップグレードが開始されました。これにより、SDKは新しいバージョンのGoogleChromeと互換性があります。 古いSDKを使用しているユーザーは、可用性の問題を回避するために、できるだけ早くSDKをアップグレードする必要があります。 SDKの最新バージョンを統合する方法の詳細については、「共同ストリーミングSDK For Webの統合」をご参照ください。
ステップ1: コストリーミング機能を有効にする
コストリーミング機能を使用するには、コストリーミングアプリケーションを作成し、ビューアのストリーミングドメインを構成する必要があります。 詳細については、「共同ストリーミングの開始」をご参照ください。
ステップ2: コストリーミング用の取り込みURLとストリーミングURLの生成
ストリーマーと共同ストリーマーの取り込みURLとストリーミングURL、および視聴者のCDNストリーミングURLは、ApsaraVideo Liveコンソールを使用して生成するか、連結ルールを使用して作成できます。
方法1: コンソールを使用してURLを生成する
ApsaraVideo LiveコンソールのURLジェネレーターを使用して、ストリーマーと共同ストリーマーの取り込みURLとストリーミングURL、および視聴者のCDNストリーミングURLを生成できます。 詳細については、「共同ストリーミングURLジェネレーター」をご参照ください。
方法2: URLを作成する
コンソールを使用して生成されるストリーマと共同ストリーマの取り込みURLとストリーミングURLのトークンは一時的なもので、通常はテストに使用されます。 ビジネス目的で使用される取り込みURLとストリーミングURLが必要な場合は、セキュリティ上の理由から連結ルールを使用してURLを構築します。 連結ルールを使用して構築するURLのトークンは、SHA-256暗号化アルゴリズムを使用して、SdkAppID、AppKey、ルームID、UserID、およびタイムスタンプに基づいて計算されます。 これらのトークンは、より高いセキュリティを提供します。 詳細については、「コストリーミングシナリオでのストリーマとコストリーマの取り込みとストリーミングURL」および「視聴者のCDNストリーミングURL」をご参照ください。
ステップ3: ストリーム取り込みに関連するオブジェクトを作成する
このステップは、ストリーマ側とコーストリーマ側の両方で必要です。
AlivcLivePusherオブジェクトの作成
ストリーム取り込みインスタンスとしてAlivcLivePusherオブジェクトを作成し、関連するコールバックを設定します。
const pusher = new window.AlivcLivePush.AlivcLivePusher();
await pusher.init({
resolution: window.AlivcLivePush.AlivcResolutionEnum.RESOLUTION_540P,
fps: window.AlivcLivePush.AlivcFpsEnum.FPS_30,
// audioOnly: true, Only for scenarios in which audio-only streams are ingested.
});
pusher.info.on('pushstatistics', _stat => {
// TODO... Process stream ingest statistics data.
// console.log(_stat);
});
pusher.error.on('system', error => {
console.log(error);
});
pusher.network.on('connectionlost', () => {
console.log('connectionlost');
});
共同ストリーミングモードでストリームの取り込みを開始する
共同ストリーミングの取り込みURLを使用してストリームを取り込みます。
await pusher.startPreview(videoElement);
await pusher.startPush("artc://live.aliyun.com/push/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX"); // The ingest URL of the streamer or co-streamer.
startPreviewとstartPushはどちらも非同期メソッドです。 呼び出しの順序を確保するには、awaitキーワードまたはPromiseオブジェクトを使用する必要があります。
AndroidまたはiOSのネイティブクライアントとwebの間でコストリーミングを実装する場合は、ネイティブクライアントでHTML5互換モードを有効にする必要があります。 それ以外の場合、web上のユーザーは、ネイティブクライアントのユーザーから送信された黒い画面が表示されます。 HTML5互換モードを有効にするには、NativeクライアントでAlivcLivePushConfig#setH5CompatibleModeを呼び出します。 詳細については、「ネイティブSDKのAPIリファレンス」をご参照ください。
ステップ4: CDN再生用のAliPlayerオブジェクトの作成
このステップは、視聴者側で必要とされます。
CDN再生にAliPlayerオブジェクトを使用するには、まず視聴者のCDNストリーミングURLを取得します。 詳細については、「手順2: コストリーミング用の取り込みURLとストリーミングURLの生成」を参照してください。
リアルタイムメッセージングプロトコル (RTMP) 形式のストリーミングURLではなく、HTTP-FLV形式のストリーミングURLを使用することをお勧めします。 ApsaraVideo Liveコンソールを使用してURLを生成すると、RTMPおよびHTTP-FLV形式のURLが生成されます。 RTMPフォーマットのURLとHTTP-FLVフォーマットのURLは、同じデータコンテンツを含むが、異なるプロトコルを使用します。 HTTPは、インターネットを介して情報を送信するための主要なプロトコルです。 Alibaba Cloud CDN、インターネットサービスプロバイダー (ISP) 、仲介デバイス間の接続など、HTTPプロトコルを介した接続は高度に最適化されています。 HTTPプロトコルのデフォルトポートは80で、HTTPSプロトコルのデフォルトポートは443です。 ほとんどの場合、ポートはホワイトリストに追加され、無効にすることはできません。 RTMPは古いプロトコルであり、デフォルトポートとして1935を使用します。 ポート1935は、ファイアウォールによって無効にすることができます。 これにより、エラーが発生する可能性があります。 RTMPと比較して、HTTP-FLVはより安定しており、より良いパフォーマンスを提供します。 例えば、HTTP-FLV上のビデオ再生は、RTMPよりも低いスタッターレート及び低いレイテンシを有します。
const player = new window.Aliplayer(
{
id: videoId, // video element ID
source: url, // The streaming URL, which can be a third-party streaming URL or a streaming URL from ApsaraVideo Live.
isLive: true, // Specify whether the content that you want to play is a live stream.
},
function (player: any) {
console.log('The player is created.', player);
}
);
ステップ5: 共同ストリーミングを開始する
ストリーマーAはARTCに基づいてストリームを取り込みます
Streamer AはAlivcLivePusherオブジェクトを使用してストリームの取り込みを開始します。 サンプルコード:
await pusher.startPreview(videoElement); // You can use methods of the Document interface (such as getElementById) to obtain the videoElement object.
await pusher.startPush("artc://live.aliyun.com/push/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX"); // The ingest URL of the streamer or co-streamer.
視聴者はCDNストリーミングURLを使用してStreamer aのストリームを再生します
すべてのビューアは、AliPlayerオブジェクトを使用してStreamer Aのストリームを再生します。サンプルコード:
const player = new window.Aliplayer(
{
id: videoId, // video element ID
source: 'rtmp://test.alivecdn.com/live/streamId?auth_key=XXX', // The streaming URL, which can be a third-party streaming URL or a streaming URL from ApsaraVideo Live.
isLive: true, // Specify whether the content that you want to play is a live stream.
},
function (player: any) {
console.log('The player is created.', player);
}
);
ビューアDが共同ストリーミングを開始
ビューアDはAlivcLivePusherオブジェクトを作成し、コストリーミング用の取り込みURLを使用してストリームを取り込みます。 この場合、ビューアDはコストリーマになる。 サンプルコード:
const pusher = new window.AlivcLivePush.AlivcLivePusher(); pusher.init({ resolution: window.AlivcLivePush.AlivcResolutionEnum.RESOLUTION_540P, fps: window.AlivcLivePush.AlivcFpsEnum.FPS_30, // audioOnly: true, Only for scenarios in which audio-only streams are ingested. }); pusher.info.on('pushstatistics', _stat => { // TODO... Process stream ingest statistics data. // console.log(_stat); }); pusher.error.on('system', error => { console.log(error); }); pusher.network.on('connectionlost', () => { console.log('connectionlost'); }); await pusher.startPreview(videoElement); // You can use methods of the Document interface (such as getElementById) to obtain the videoElement object. await pusher.startPush("artc://live.aliyun.com/push/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX"); // The ingest URL of the streamer or co-streamer.
ストリーマAは、コストリーマDのコストリーミングのためのストリーミングURLを取得し、コストリーマDのストリームをリアルタイムでプルするためのAlivcLivePlayerオブジェクトを作成する。 サンプルコード:
const player = new window.AlivcLivePush.AlivcLivePlayer(); // Specify the streaming URL of Co-streamer D, which starts with artc://. const playInfo = await player.startPlay("artc://live.aliyun.com/play/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX", videoElement); playInfo.on('userleft', () => { // Handle the event that is triggered when Co-streamer D leaves the room. }); playInfo.on('canplay', () => { // Handle the event that is triggered when the video is available for playback. }
同時に、Co-streamer Dは、Streamer Aのコストリーミング用のストリーミングURLを取得し、AlivcLivePlayerオブジェクトを作成して、Streamer Aのストリームをリアルタイムでプルします。 サンプルコード:
const player = new window.AlivcLivePush.AlivcLivePlayer(); // Specify the streaming URL of Streamer A, which starts with artc://. const playInfo = await player.startPlay("artc://live.aliyun.com/play/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX", videoElement); playInfo.on('userleft', () => { // Handle the event that is triggered when Streamer A leaves the room. }); playInfo.on('canplay', () => { // Handle the event that is triggered when the video is available for playback. }
ストリーマAは、コストリーミングが成功した後に混合ストリームを更新します
ビューアBおよびビューアC (コストリーマではない) がコストリーマDのストリームを確実に見ることができるようにするために、ストリーマAはストリームミキシング動作を実行しなければならない。 このようにして、ストリーマAおよびコストリーマDのストリームは、視聴者が再生のためにCDNから引き出すことができる単一のストリームに混合することができます。
具体的には、ストリーマAは、setLiveMixTranscodingConfigメソッドを呼び出して、混合ストリームのトランスコーディングタスクを開始し、混合するストリームを指定します。 混合ストリームの解像度やフレームレートなどのパラメータは、AlivcLivePushConfigでAlivcLivePusherオブジェクトを作成するときにStreamer Aが設定したものです。 たとえば、AlivcLivePusherオブジェクトを作成するときにStreamer AがAlivcLivePushConfigで解像度を720pに設定した場合、混合ストリームの解像度は720pになります。
const resolution = pusher.getResolution();
const width = window.AlivcLivePush.AlivcResolution.GetResolutionWidth(resolution);
const height = window.AlivcLivePush.AlivcResolution.GetResolutionHeight(resolution);
const mixStreams = [];
const transcodingConfig = new window.AlivcLivePush.AlivcLiveTranscodingConfig();
const anchorMixStream = new window.AlivcLivePush.AlivcLiveMixStream(
userA, // Specify the user ID of Streamer A.
0,
0,
width,
height,
1
);
// Add the stream of Streamer A for mixing.
mixStreams.push(anchorMixStream);
const audienceMixStream = new window.AlivcLivePush.AlivcLiveMixStream(
userD, // Specify the user ID of Co-streamer D.
100,
200,
200,
300,
2
);
// Add the stream of Co-streamer D for mixing.
mixStreams.push(audienceMixStream);
transcodingConfig.mixStreams = mixStreams;
await pusher.setLiveMixTranscodingConfig(transcodingConfig);
視聴者は、ストリーマAとコストリーマDの混合ストリームを視聴できます。
共同ストリーマーDが共同ストリーミングを終了
コストリーミングを停止するには、co-streamer DがAlivcLivePusherでストリーム取り込みを停止するメソッドを呼び出してから、AlivcLivePusherを破棄する必要があります。 サンプルコード:
await pusher.destroy(); pusher = null;
同時に、Co-streamer DはAlivcLivePlayerで再生を停止するために使用されるメソッドを呼び出し、AlivcLivePlayerを破棄する必要があります。 サンプルコード:
await player.destroy(); player = null;
コストリーマDは通常のビューアになり、CDNからストリームをプルできます。 詳細については、「手順4: CDN再生用のAliPlayerオブジェクトの作成」をご参照ください。
Streamer Aは、AlivcLivePlayerで再生を停止するメソッドを呼び出してから、AlivcLivePlayerを破棄する必要があります。 サンプルコード:
await player.destroy(); player = null;
同時に、Streamer AはsetLiveMixTranscodingConfigメソッドを呼び出し、空の値を渡す必要があります。 このようにして、流れの混合は停止される。 視聴者がストリーマAのストリームのみを視聴したい場合は常に、ストリーマAは上記の操作を実行してストリームミキシングを停止できることに注意してください。
警告ストリーマがまだ室内にあるが、ストリームミキシングを必要としない場合は、ストリームミキシングが停止していることを確認してください。 ストリームミキシングが停止されていない場合、実行を継続するストリームミキシングモジュールには不要な料金が発生します。
pusher.setLiveMixTranscodingConfig();