ショートビデオ SDK は、基本録画機能を提供し、ショートビデオに背景音楽、速度ランプ、フェイス ステッカーなどの録画効果を適用できます。
対応エディション
エディション | 対応 |
Professional | はい |
Standard | はい |
Basic | はい |
関連クラス
クラス | 説明 |
録画、プレビュー設定、エフェクト設定、コールバック設定など、録画機能を定義するコア クラスです。 | |
録画インスタンスの作成に使用されるファクトリ クラスです。 | |
ビデオの幅と高さ、エンコーダー タイプ、フレーム レートなど、録画パラメーターを定義するクラスです。 | |
録画完了コールバック、録画進捗コールバック、録画エラー コールバックなど、録画コールバックを定義するクラスです。 | |
選択されたプレビュー解像度のコールバック、カメラでキャプチャされたフレーム データのコールバック、カメラの有効化に失敗した場合に発生するエラーのコールバックなど、データ キャプチャのコールバックを定義するクラスです。 | |
PCM 形式のオーディオ データのコールバックを定義するクラスです。 | |
ビデオクリップを管理するクラスです。たとえば、ビデオクリップの削除や録画時間の構成を行います。 |
録画の構成
ビデオを録画するには、カメラとマイクの権限が必要です。
構成 | 手順 | 説明 | サンプル コード |
基本構成 | 1 | 録画インスタンスの作成と破棄、および録画パラメーターの構成を行います。 | |
2 | コールバックを構成します。 | ||
3 | プレビューを開始および停止します。 | ||
4 | ビデオクリップの録画を開始、キャンセル、および停止します。 | ||
5 | 録画を停止し、構成情報を生成します。 | ||
高度な構成 | 6 | カメラ コントロールとビデオクリップ管理のパラメーターを構成します。カメラ コントロールのパラメーターには、カメラ タイプとフラッシュ モードが含まれます。ビデオクリップ管理のパラメーターには、最大または最小録画時間、ビデオクリップの削除方法、ビデオクリップ数のクエリ方法が含まれます。ビジネス要件に基づいてこれらのパラメーターを構成します。 | |
7 | ビジネス要件に基づいて、レタッチ、フィルター、背景音楽などの録画効果を構成します。 | ||
8 | 写真撮影または顔認識を構成します。 |
AliyunIRecorder クラスを初期化し、パラメーターを構成する
AliyunIRecorder クラスを初期化し、録画インスタンスを作成し、録画パラメーターを構成します。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
クラスの初期化
// 録画インスタンスを作成します。
AliyunIRecorder recorder = AliyunRecorderCreator.getRecorderInstance(context);// context パラメーターは、現在の画面のコンテキストを示します。
// 録画インスタンスを破棄します。
// SDK を使用する必要がなくなった場合、またはプログラムを終了する前に、録画インスタンスを破棄します。使用中に録画インスタンスを破棄しないでください。
recorder.destroy();録画パラメーターの構成
// 録画ビデオの品質を指定します。
recorder.setVideoQuality(quality);
// 録画ビデオのビットレートを指定します。
recorder.setVideoBitrate(int bitrate);// 単位: Kbit/s。
// 録画ビデオの出力パラメーターを構成します。
recorder.setMediaInfo(mediaInfo);// パラメーターの詳細については、SDK リファレンスの MediaInfo を参照してください。
// 録画ビデオの出力パスを指定します。
recorder.setOutputPath(string path);
// 録画ビデオの出力グループ オブ ピクチャ (GOP) を指定します。
recorder.setGop(int gop);// 単位: フレーム。コールバックを構成する
コールバックを構成して、オーディオとビデオの処理の進捗状況とステータスをタイムリーに取得できます。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
// 録画コールバックを構成します。
recorder.setRecordCallBack(RecordCallback callBack);
// ビデオ フレーム コレクションのコールバックを構成します。
recorder.setOnFrameCallback(OnFrameCallBack callback);
// オーディオ コレクション コールバックを構成します。
recorder.setOnAudioCallback(OnAudioCallBack callback);プレビューを有効にする
プレビュー中は、SurfaceView を構成する必要があります。同時に、Activity/Fragment の onResume() で startPreview を実行し、onPause() で stopPreview を実行します。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
// プレビュー ビューを構成します。
recorder.setDisplayView(SurfaceView displayView);
// プレビューを開始します。
recorder.startPreview();
// プレビューを停止します。
// Activity/Fragment の onPause() で stopPreview を実行します。
recorder.stopPreview();録画を開始する
録画プロセスでは、必要な完全なビデオが得られるまで、ビデオの停止、キャンセル、または再録画が必要になる場合があります。録画を停止すると、ビデオクリップが生成されます。ただし、録画をキャンセルすると、現在のビデオクリップは保持されません。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
録画の開始
// 録画を開始します。
recorder.startRecording();ビデオクリップの録画
// 録画を開始します。
recorder.startRecording();
// 録画を停止します。ビデオクリップが生成されます。
recorder.stopRecording();
recorder.startRecording();
// 録画をキャンセルします。現在のビデオクリップは保存されません。
recorder.cancelRecording();
// 次のビデオクリップの録画を続行します。
recorder.startRecording();
recorder.stopRecording();録画を停止する
録画を停止すると、録画されたビデオクリップが 1 つのビデオにマージされるか、録画されたビデオクリップに関する構成情報が生成されます。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
// 録画を停止し、録画されたビデオクリップを 1 つのビデオにマージします。
recorder.finishRecording();
// 録画を停止し、ビデオクリップをマージせずに、録画されたビデオクリップに関する構成情報を生成します。
recorder.finishRecordingForEdit();カメラ設定を構成し、ビデオクリップを管理する
カメラ コントロールとビデオクリップ管理のパラメーターを構成します。カメラ コントロールのパラメーターには、カメラ タイプとフラッシュ モードが含まれます。ビデオクリップ管理のパラメーターには、最大または最小録画時間、ビデオクリップの削除方法、ビデオクリップ数のクエリ方法が含まれます。ビジネス要件に基づいてこれらのパラメーターを構成します。
コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
カメラ設定の構成
// カメラの数を取得します。
AliyunIRrecorder.getCameraCount();
// カメラ タイプを指定します。
AliyunIRecorder.setCamera(cameraType);
// 録画中に音声をミュートするかどうかを指定します。
AliyunIRecorder.setMute(boolean isMute);
// センサーの角度を指定します。
// この設定は非常に重要です。SDK リファレンスをお読みになることをお勧めします。
AliyunIRecorder.setRotation(int rotation);
// ビデオを録画する角度を指定します。
// この設定は非常に重要です。SDK リファレンスをお読みになることをお勧めします。
AliyunIRecorder.setRecordRotation(int rotation);
// プレビュー中のカメラ パラメーター (フラッシュ モード、フォーカス モード、ズーム係数、露出レベルなど) を構成します。以下のメソッドを使用して、プレビュー パラメーターを個別に構成することもできます。
AliyunIRecorder.setCameraParam(CameraParam cameraParam);
// フロント カメラとリア カメラを切り替えます。
AliyunIRecorder.switchCamera();
// フラッシュ モードを指定します。
AliyunIRecorder.setLight(flashType);
// ズーム係数を指定します。
AliyunIRecorder.setZoom(float rate);
// 露出レベルを指定します。
AliyunIRecorder.setExposureCompensationRatio(float value);
// フォーカス モードを指定します。
AliyunIRecorder.setFocusMode(int mode);
// 手動フォーカスを構成します。
AliyunIRecorder.setFocus(float xRatio, float yRatio);ビデオクリップの管理
// クリップ マネージャーを取得します。
AliyunIClipManager manager = AliyunIRecorder.getClipManager();
// 最大録画時間を指定します。これは、単一のビデオクリップではなく、すべてのビデオクリップの最大時間です。
manager.setMaxDuration(int maxDurationMs);
// 最小録画時間を指定します。これは、単一のビデオクリップではなく、すべてのビデオクリップの最小時間です。
manager.setMinDuration(int minDurationMs);
// 最後のビデオクリップを削除します。
manager.deletePart();
// 指定されたビデオクリップを削除します。
manager.deletePart(int index);
// すべてのビデオクリップを削除します。
manager.deleteAllPart();
// ビデオクリップの合計時間を取得します。
manager.getDuration();
// ビデオクリップの総数を取得します。
manager.getPartCount();
// ビデオクリップのパスを取得します。
manager.getVideoPathList();効果を構成する
ビジネス要件に基づいて、レタッチ、フィルター、背景音楽などの録画効果を構成します。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
フィルター
カスタム フィルターを作成できます。詳細については、「フィルターとトランジション」をご参照ください。
// フィルターを適用します。
AliyunIRecorder.applyFilter(EffectFilter effectFilter);// パスが null に設定されている場合、フィルターは削除されます。
// フィルターを削除します。
AliyunIRecorder.applyFilter(new EffectFilter(null));アニメーション フィルター
// アニメーション フィルターを適用します。
AliyunIRecorder.applyAnimationFilter(EffectFilter effectFilter);
// アニメーション フィルターを削除します。
AliyunIRecorder.removeAnimationFilter(EffectFilter effctFilter);背景音楽
// 背景音楽を構成します。
AliyunIRecorder.setMusic(String path,long startTime,long duration);
// 背景音楽を削除します。
AliyunIRecorder.setMusic(null, 0, 0);速度ランプ
// 録画の速度ランプを構成します。
AliyunIRecorder.setRate(float rate);静的ステッカーと静的ウォーターマーク
// 静的ウォーターマークまたは静的ステッカーを追加します。
AliyunIRecorder.addImage(EffectImage effctImage);
// 静的ウォーターマークまたは静的ステッカーを削除します。
AliyunIRecorder.removeImage(EffectImage effctImage);
// 静的ウォーターマークまたは静的ステッカーの位置を更新します。
AliyunIRecorder.setEffectView(float xRatio,float yRatio,float widthRatio,float heightRatio,EffectBase effectBase);アニメーション ステッカー
カスタム アニメーション ステッカーを作成できます。詳細については、「アニメーション」をご参照ください。
// アニメーション ステッカーを追加します。
AliyunIRecorder.addPaster(EffectPaster effectPaster,float sx,float sy,float sw,float sh,float rotation,boolean flip);
// アニメーション ステッカーを削除します。
AliyunIRecorder.removePaster(EffectPaster effectPaster);
// アニメーション ステッカーの位置を更新します。
AliyunIRecorder.setEffectView(float xRatio,float yRatio,float widthRatio,float heightRatio,EffectBase effectBase);高度なレタッチ
ビデオ録画モジュールは、基本的な組み込みレタッチ機能を提供するだけでなく、Alibaba Cloud Queen SDK や FaceUnity などのレタッチ SDK の使用もサポートしています。組み込みのレタッチ機能を使用して、レタッチ レベルのみを構成できます。レタッチ SDK は、顔のレタッチ、顔の整形、メイク、フィルター、ステッカーなど、豊富なレタッチ効果を提供します。
組み込みレタッチ
// レタッチを有効または無効にします。 AliyunIRecorder.setBeautyStatus(boolean on); // レタッチ レベルを構成します。 AliyunIRecorder.setBeautyLevel(int level);レタッチ SDK
ショートビデオ SDK でレタッチ SDK が提供する効果を使用するには、まずレタッチ SDK の権限を取得し、レタッチ SDK をショートビデオ SDK に統合する必要があります。
レタッチ SDK でレタッチ効果を実装するには、カメラ テクスチャ ID とカメラ生フレーム データが必要です。次のコードは、カメラ テクスチャ ID とカメラ生フレーム データを取得する方法の例を示しています。
カメラ テクスチャ ID の取得
AliyunIRecorder.setOnTextureIdCallback(new OnTextureIdCallBack() { @Override public int onTextureIdBack(int textureId, int textureWidth, int textureHeight, float[] matrix) { if (mBeautyInterface != null) { return mBeautyInterface.onTextureIdBack(textureId, textureWidth, textureHeight, matrix, mControlView.getCameraType().getType()); } return textureId; } @Override public int onScaledIdBack(int scaledId, int textureWidth, int textureHeight, float[] matrix) { return scaledId; } @Override public void onTextureDestroyed() { // V3.7.8 より前のバージョンのショートビデオ SDK の場合、GLSurfaceView の GLSurfaceView.queueEvent を使用して、サードパーティのカスタム レンダリング用の gl リソースを破棄できます。ショートビデオ SDK V3.7.8 以降では、このコールバックで gl リソースを破棄することをお勧めします。 if (mBeautyInterface != null) { mBeautyInterface.release(); mBeautyInterface = null; } } });カメラ生フレーム データの取得
AliyunIRecorder.setOnFrameCallback(new OnFrameCallBack() { @Override public void onFrameBack(byte[] bytes, int width, int height, Camera.CameraInfo info) { // コールバック生データのデータ型は NV21 です。取得した生データは FaceUnity によって使用されます。 if (mBeautyInterface != null) { mBeautyInterface.onFrameBack(bytes, width, height, info); } } @Override public Camera.Size onChoosePreviewSize(List<Camera.Size> supportedPreviewSizes, Camera.Size preferredPreviewSizeForVideo) { return null; } @Override public void openFailed() { } });
その他の機能を構成する
ビデオ録画中は、写真撮影と顔認識がサポートされています。コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
写真撮影
エフェクトを有効にした状態、またはデフォルトのカメラ設定を使用して写真を撮ることができます。デフォルトのカメラ設定では、エフェクトはサポートされていません。写真が撮影されると、RecordCallback.onPictureBack(Bitmap) または RecordCallback.onPictureDataBack(byte[]) を使用してデータが返されます。
// エフェクトを有効にした状態で写真を撮ります。
AliyunIRecorder.takePhoto(boolean needBitmap);
// デフォルトのカメラ設定を使用して写真を撮ります。デフォルトのカメラ設定では、エフェクトはサポートされていません。
AliyunIRecorder.takePicture(boolean needBitmap);
// 写真のサイズを指定します。このメソッドは、デフォルトのカメラ設定を使用して写真を撮る場合にのみサポートされています。
AliyunIRecorder.setPictureSize(Camera.Size size);顔認識
顔認識を使用するには、アプリケーションの組み込み顔認識モデルにアクセスする必要があります。参考までに、顔認識モデル デモ をダウンロードできます。
// 顔認識を有効にするかどうかを指定します。
AliyunIRecorder.needFaceTrackInternal(boolean need);
// 顔認識モデル ファイルのパスを指定します。
AliyunIRecorder.setFaceTrackInternalModelPath(String path);
// 顔認識を実行する角度を指定します。
// この設定は非常に重要です。SDK リファレンスをお読みになることをお勧めします。
AliyunIRecorder.setFaceDetectRotation(int rotation);
// 認識できる顔の数を指定します。
// 同時に認識できる顔の最大数を指定します。最大値: 3。
AliyunIRecorder.setFaceTrackInternalMaxFaceCount(int maxFaceCount);
// アニメーション フェイス ステッカーを追加します。
AliyunIRecorder.addPaster(EffectPaster effectPaster);基本録画のサンプル コード
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.aliyun.svideosdk.common.struct.recorder.MediaInfo;
import com.aliyun.svideosdk.recorder.AliyunIRecorder;
import com.aliyun.svideosdk.recorder.RecordCallback;
import com.aliyun.svideosdk.recorder.impl.AliyunRecorderCreator;
import com.svideo.guide.R;
import java.io.FileOutputStream;
/**
* ビデオ録画のサンプル コード
*/
class RecordActivity : AppCompatActivity() {
enum class RecordStatus {
Idle,
Recording
}
private lateinit var mAliyunRecord : AliyunIRecorder
private lateinit var mCameraViiew : SurfaceView
private lateinit var mRecordBtn : ImageView
private var mRecordStatus = RecordStatus.Idle
companion object {
const val TAG = "RecordActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_record)
mCameraViiew = findViewById(R.id.cameraPreviewView)
mRecordBtn = findViewById(R.id.btnRecordControl)
// 録画を開始します。
mRecordBtn.setOnClickListener {
if(mRecordStatus == RecordStatus.Recording) {
mAliyunRecord.stopRecording()
Toast.makeText(this@RecordActivity, "録画停止", Toast.LENGTH_SHORT).show()
updateRecordStatus(RecordStatus.Idle)
} else {
mAliyunRecord.takePhoto(true)
}
}
mRecordBtn.setOnLongClickListener {
if(mRecordStatus == RecordStatus.Idle) {
val curTime = System.currentTimeMillis()
mAliyunRecord.setOutputPath("/storage/emulated/0/DCIM/Camera/svideo_record_video_$curTime.mp4")
mAliyunRecord.startRecording()
Toast.makeText(this@RecordActivity, "録画開始", Toast.LENGTH_SHORT).show()
updateRecordStatus(RecordStatus.Recording)
}
true
}
mAliyunRecord = AliyunRecorderCreator.getRecorderInstance(this)
val mediaInfo = MediaInfo()
mediaInfo.fps = 30
mediaInfo.crf = 6
mediaInfo.videoWidth = 720
mediaInfo.videoHeight = 1080
mAliyunRecord.setMediaInfo(mediaInfo)
mAliyunRecord.setDisplayView(mCameraViiew)
mAliyunRecord.setRecordCallBack(object : RecordCallback {
override fun onComplete(validClip: Boolean, clipDuration: Long) {
Log.i(TAG, "onComplete")
}
override fun onFinish(outputPath: String?) {
Log.i(TAG, "onFinish path : $outputPath")
}
override fun onProgress(duration: Long) {
}
override fun onMaxDuration() {
Log.i(TAG, "onMaxDuration")
}
override fun onError(errorCode: Int) {
Log.i(TAG, "onError : $errorCode")
}
override fun onInitReady() {
Log.i(TAG, "onInitReady")
}
override fun onDrawReady() {
Log.i(TAG, "onDrawReady")
}
override fun onPictureBack(bitmap: Bitmap?) {
Log.i(TAG, "onPictureBack")
val curTime = System.currentTimeMillis()
val outputFile = "/storage/emulated/0/DCIM/Camera/svideo_record_photo_$curTime.png"
val outputStream = FileOutputStream(outputFile)
bitmap?.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
outputStream.flush()
outputStream.close()
runOnUiThread {
Toast.makeText(this@MixRecordActivity, "写真はアルバムに保存されました", Toast.LENGTH_SHORT).show()
}
}
override fun onPictureDataBack(p0: ByteArray?) {
Log.i(TAG, "onPictureDataBack")
}
})
}
private fun updateRecordStatus(recordStatus: RecordStatus)
{
mRecordStatus = recordStatus
when(recordStatus) {
RecordStatus.Idle -> {
mRecordBtn.setImageResource(R.mipmap.alivc_svideo_bg_record_start)
}
RecordStatus.Recording -> {
mRecordBtn.setImageResource(R.mipmap.alivc_svideo_bg_record_storp)
}
}
}
override fun onResume() {
super.onResume()
mAliyunRecord.startPreview()
}
override fun onPause() {
super.onPause()
mAliyunRecord.stopPreview()
}
override fun onDestroy() {
super.onDestroy()
mAliyunRecord.destroy()
}
}XML での構成例
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<SurfaceView
android:id="@+id/cameraPreviewView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</SurfaceView>
<ImageView
android:id="@+id/btnRecordControl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="50dp"
android:src="@mipmap/alivc_svideo_bg_record_storp"
android:visibility="visible">
</ImageView>
</androidx.constraintlayout.widget.ConstraintLayout>