概要
ARTC SDK は、ビジネス要件に応じて動画キャプチャデバイスを柔軟に管理できるカスタム動画キャプチャ機能を提供します。
デフォルトでは、SDK 内蔵のキャプチャ機能をご利用いただくことを推奨します。ただし、動画品質、デバイス互換性、またはキャプチャワークフローに関する特定の要件を満たさない場合、カスタム動画キャプチャにより、より高い拡張性とカスタマイズ性を実現できます。
サンプルコード
Android 向けカスタム動画キャプチャ: Android/ARTCExample/AdvancedUsage/src/main/java/com/aliyun/artc/api/advancedusage/CustomVideoCaptureAndRender/CustomVideoCaptureActivity.java。
iOS 向けカスタム動画キャプチャ: iOS/ARTCExample/AdvancedUsage/CustomVideoCapture/CustomVideoCaptureVC.swift。
前提条件
開始する前に、以下の要件を満たしていることを確認してください。
Alibaba Cloud アカウント (root ユーザー) を保有し、ARTC アプリケーションを作成済みで、AppID および AppKey を取得済みであること。手順については、「アプリケーションの作成」をご参照ください。認証情報は、ApsaraVideo Live コンソールでご確認いただけます。
ARTC SDK をプロジェクトに統合済みであり、基本的な音声・動画通話機能を実装済みであること。詳細については、「ARTC SDK の統合」および「音声・動画通話の実装」をご参照ください。
実装手順
1. 内蔵キャプチャの無効化
enableLocalVideo メソッドを呼び出して、SDK 内蔵の動画キャプチャを無効化します。
Android
/* 内蔵キャプチャを無効化します。 */
mAliRtcEngine.enableLocalVideo(false);
/* 内蔵キャプチャを有効化します(デフォルトで有効)。 */
mAliRtcEngine.enableLocalVideo(true);iOS
/* 内蔵キャプチャを無効化します。 */
[_engine enableLocalVideo:NO];
/* 内蔵キャプチャを有効化します(デフォルトで有効)。 */
[_engine enableLocalVideo:YES];Mac
/* 内蔵キャプチャを無効化します。 */
[self.engine enableLocalVideo:NO];
/* 内蔵キャプチャを有効化します(デフォルトで有効)。 */
[self.engine enableLocalVideo:YES];Windows
/* 内蔵キャプチャを無効化します。 */
mAliRtcEngine->EnableLocalVideo(false);
/* 内蔵キャプチャを有効化します(デフォルトで有効)。 */
mAliRtcEngine->EnableLocalVideo(true);2. 外部動画ソースの設定
setExternalVideoSource を呼び出して外部動画ソースを設定します。主なパラメーターは以下のとおりです。
enable:外部動画ソースを有効にするかどうかを指定します。
useTexture:テクスチャ入力を使用するかどうかを指定します。
streamType:SDK が置き換えるストリームの種類(例:カメラストリーム、画面共有ストリーム)を指定します。
renderMode:外部動画ソースの縦横比と配信プロファイルの縦横比が一致しない場合に使用されるレンダリングモード。SDK はこのモードに従って動画をスケーリングします。
Android
YUV 入力
/* YUV 入力 */
/* 外部キャプチャを有効化します(本例ではカメラストリームを使用)。sourceType および renderMode は必要に応じて調整可能です。 */
mAliRtcEngine.setExternalVideoSource(true,false, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );
/* 外部キャプチャを無効化します(本例ではカメラストリームを使用)。sourceType は必要に応じて調整可能です。 */
mAliRtcEngine.setExternalVideoSource(false,false, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );テクスチャ入力
/* テクスチャ入力 */
/* 外部キャプチャを有効化します(本例ではカメラストリームを使用)。sourceType および renderMode は必要に応じて調整可能です。 */
mAliRtcEngine.setExternalVideoSource(true,true, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );
/* 外部キャプチャを無効化します(本例ではカメラストリームを使用)。sourceType は必要に応じて調整可能です。 */
mAliRtcEngine.setExternalVideoSource(false,true, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );iOS
/* 外部キャプチャを有効化します(本例ではカメラストリームを使用)。sourceType および renderMode は必要に応じて調整可能です。 */
[_engine setExternalVideoSource:YES sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto];
/* 外部キャプチャを無効化します(本例ではカメラストリームを使用)。sourceType は必要に応じて調整可能です。 */
[_engine setExternalVideoSource:NO sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto]; Mac
/* 外部キャプチャを有効化します(本例ではカメラストリームを使用)。sourceType および renderMode は必要に応じて調整可能です。 */
[self.engine setExternalVideoSource:YES sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto];
/* 外部キャプチャを無効化します(本例ではカメラストリームを使用)。sourceType は必要に応じて調整可能です。 */
[self.engine setExternalVideoSource:NO sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto];Windows
/* テクスチャ入力 */
/* 外部キャプチャを有効化します(本例ではカメラストリームを使用)。sourceType および renderMode は必要に応じて調整可能です。 */
mAliRtcEngine->SetExternalVideoSource(true,true, AliEngineVideoTrackCamera,AliEngineRenderModeAuto );
/* 外部キャプチャを無効化します(本例ではカメラストリームを使用)。sourceType は必要に応じて調整可能です。 */
mAliRtcEngine->SetExternalVideoSource(false,true, AliEngineVideoTrackCamera,AliEngineRenderModeAuto );3. 動画フレームの SDK へのプッシュ
動画フレームをキャプチャした後、pushExternalVideoFrame メソッドを使用して ARTC SDK へ送信します。
Android
YUV 入力の例:
/* 本例では YUV (I420) フォーマットを使用します。 */
int width = 720;
int height = 1280;
AliRtcEngine.AliRtcVideoFormat videoformat = AliRtcEngine.AliRtcVideoFormat.AliRtcVideoFormatI420;
int[] lineSize = {width, width / 2, width / 2, 0};
int frameLength = width * height * 3 / 2;
byte[] buffer = new byte[frameLength];
/* SDK へ渡すデータオブジェクトを構築します。 */
AliRtcEngine.AliRtcRawDataFrame rawDataFrame
= new AliRtcEngine.AliRtcRawDataFrame(buffer,
videoformat,
width,
height,
lineSize,
0,
buffer.length);
/* API を呼び出してデータオブジェクトをプッシュします。 */
int ret = mAliRtcEngine.pushExternalVideoFrame(rawDataFrame, AliRtcVideoTrackCamera);
if (ret != 0) {
/* エラーを処理します。 */
}テクスチャ入力の例:
/* 本例ではテクスチャフォーマットを使用します。 */
/* OpenGL 環境を作成します。 */
private static EglBase14 createEglBase14(EGLContext shareEglContext) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
EglBase14.Context eglBase14Context = shareEglContext == null ? null : new EglBase14.Context(shareEglContext);
EglBase14 eglBase14 = new EglBase14(eglBase14Context, EglBase.CONFIG_PIXEL_BUFFER);
try {
eglBase14.createDummyPbufferSurface();
eglBase14.makeCurrent();
} catch (RuntimeException e) {
Log.e(TAG, "CreateEGLBase14Context, failed, " + e.getMessage());
}
return eglBase14;
}
return null;
}
/* 入力データ用のコンテキストを構築します。 */
float[] transformMatrix = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
int frameWidth = 720; /* 画像の幅。 */
int frameHeight = 1280; /* 画像の高さ。 */
int textureID = xxx; /* ご利用のテクスチャ ID。 */
AliRtcEngine.AliRtcRawDataFrame aliRawDataFrame
= new AliRtcEngine.AliRtcRawDataFrame(textureID,
AliRtcVideoFormatTexture2D,
frameWidth,
frameHeight,
transformMatrix,
0,
0,
frameWidth,
frameHeight,
mEglBase14.getEglContext());
/* API を呼び出してデータオブジェクトをプッシュします。 */
int ret = mAliRtcEngine.pushExternalVideoFrame(aliRawDataFrame, AliRtcVideoTrackCamera);
if (ret != 0) {
/* エラーを処理します。 */
}iOS
/* データ形式に応じて以下のパラメーターを指定します(本例では I420 フォーマットを使用)。 */
AliRtcVideoDataSample *dataSample = [[AliRtcVideoDataSample alloc] init];
dataSample.dataPtr = (long)yuv_read_data;
dataSample.format = AliRtcVideoFormat_I420;
dataSample.type = AliRtcBufferType_Raw_Data;
dataSample.width = width;
dataSample.height = height;
dataSample.strideY = width;
dataSample.strideU = width/2;
dataSample.strideV = width/2;
dataSample.dataLength = dataSample.strideY * dataSample.height * 3/2;
/* API を呼び出してデータオブジェクトをプッシュします。 */
int ret = [self.engine pushExternalVideoFrame:dataSample sourceType:AliRtcVideosourceCameraType];
if (ret != 0) {
/* エラーを処理します。 */
}Mac
/* データ形式に応じて以下のパラメーターを指定します(本例では I420 フォーマットを使用)。 */
AliRtcVideoDataSample *dataSample = [[AliRtcVideoDataSample alloc] init];
dataSample.dataPtr = (long)yuv_read_data;
dataSample.format = AliRtcVideoFormat_I420;
dataSample.type = AliRtcBufferType_Raw_Data;
dataSample.width = width;
dataSample.height = height;
dataSample.strideY = width;
dataSample.strideU = width/2;
dataSample.strideV = width/2;
dataSample.dataLength = dataSample.strideY * dataSample.height * 3/2;
/* API を呼び出してデータオブジェクトをプッシュします。 */
int ret = [self.engine pushExternalVideoFrame:dataSample sourceType:AliRtcVideosourceCameraType];
if (ret != 0) {
/* エラーを処理します。 */
if ( ret == AliRtcErrAudioBufferFull ) {
// バッファーが満杯です。20 ms 待って再試行します。
[NSThread sleepForTimeInterval:0.02] ;
continue ;
}
break ;
}Windows
AliEngineVideoRawData sample;
sample.dataPtr = (unsigned char*)cache_buf;
sample.format = AliEngineVideoFormatI420;
sample.width = mIYuvWidth;
sample.height = mIYuvHeight;
sample.strideY = mIYuvWidth;
sample.strideU = mIYuvWidth / 2;
sample.strideV = mIYuvWidth / 2;
sample.dataLength = frame_length;
sample.rotation = 0;
/* API を呼び出してデータオブジェクトをプッシュします。 */
int ret = mAliRtcEngine->PushExternalVideoFrame(sample, AliEngineVideoTrackScreen);
if ( ret != 0 ) {
if ( ret == AliEngineErrorAudioBufferFull ) {
Sleep(20);
continue;
}else {
// エラーを処理します。
break ;
}
} else {
}