ショートビデオ SDK は、バックグラウンドミュージック、速度変更、顔ステッカーなどのさまざまなエフェクトを使用した基本的な録画を可能にします。
サポートされているエディション
エディション | サポート |
professional edition | はい |
standard edition | はい |
basic edition | はい |
関連クラス
クラス | 説明 |
録画用のコアインターフェイスです。録画の開始、プレビューの設定、エフェクトの適用、コールバックの設定などの主要な機能が含まれています。 | |
録画インスタンスを作成するためのファクトリークラスです。 | |
動画の解像度、エンコーダータイプ、キャプチャフレームレートなどの録画パラメーターを設定するためのクラスです。 | |
完了、進捗、エラーなどの録画イベントのコールバックを提供するインターフェイスです。 | |
プレビュー解像度の選択、フレームデータのキャプチャ、カメラ起動の失敗など、カメラデータキャプチャのコールバックを提供するインターフェイスです。 | |
PCM フォーマットのオーディオデータのコールバックを提供するインターフェイスです。 | |
ビデオクリップを管理するためのインターフェイスです。クリップの削除や録画時間の設定に使用します。 |
ワークフロー
動画の録画には、カメラとマイクの権限が必要です。
段階 | 手順 | 説明 | サンプルコード |
基本 | 1 | 録画インターフェイスの作成と破棄、および録画パラメーターの設定。 | |
2 | コールバックの設定。 | ||
3 | プレビューの開始と停止。 | ||
4 | ビデオクリップの録画開始、キャンセル、停止。 | ||
5 | 録画の停止と出力の生成。 | ||
高度な機能 | 6 | 任意で、カメラタイプやフラッシュモードなどのカメラ制御、最大・最小録画時間やクリップ削除などのクリップ管理設定を構成します。 | |
7 | 任意で、レタッチ、フィルター、バックグラウンドミュージックなどのエフェクトを適用します。 | ||
8 | 写真撮影や顔認識などの追加機能を有効にします。 |
初期化とパラメーター設定
レコーダーを初期化し、AliyunIRecorder インターフェイスを使用して録画インスタンスを作成し、録画パラメーターを設定します。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
初期化
// 録画インターフェイスを作成します。
AliyunIRecorder recorder = AliyunRecorderCreator.getRecorderInstance(context);// context パラメーターは現在のページコンテキストです。
// 録画インターフェイスを破棄します。
// アプリの終了前など、インターフェイスが不要になったときにこのメソッドを呼び出します。レコーダーの使用中には呼び出さないでください。
recorder.destroy();録画パラメーターの設定
// 録画された動画の品質を設定します。
recorder.setVideoQuality(quality);
// 録画された動画のビットレートを設定します。
recorder.setVideoBitrate(int bitrate);// 単位:Kbps
// 録画された動画の出力パラメーターを設定します。
recorder.setMediaInfo(mediaInfo);// パラメーターの詳細については、MediaInfo API リファレンスをご参照ください。
// 録画された動画の出力パスを設定します。
recorder.setOutputPath(string path);
// 録画された動画の GOP (Group of Pictures) サイズを設定します。
recorder.setGop(int gop);// 単位:フレームコールバックの設定
コールバックを設定することで、オーディオとビデオの処理の進捗とステータスに関する最新情報をタイムリーに受け取ることができます。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
// 録画コールバックを設定します。
recorder.setRecordCallBack(RecordCallback callBack);
// ビデオフレームキャプチャのコールバックを設定します。
recorder.setOnFrameCallback(OnFrameCallBack callback);
// オーディオデータキャプチャのコールバックを設定します。
recorder.setOnAudioCallback(OnAudioCallBack callback);プレビューの有効化
プレビューを有効にするには、SurfaceView コンテナを設定する必要があります。ご利用の Activity または Fragment の onResume() メソッドで startPreview を呼び出し、onPause() で stopPreview を呼び出します。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
// プレビュービューを設定します。
recorder.setDisplayView(SurfaceView displayView);
// プレビューを開始します。
recorder.startPreview();
// プレビューを停止します。
// ご利用の Activity または Fragment の onPause() メソッドで stopPreview を呼び出します。
recorder.stopPreview();録画の開始
録画中に、複数回の停止、キャンセル、再開が可能です。録画を停止するとビデオクリップが生成され、キャンセルすると現在のビデオクリップは破棄されます。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
録画の開始
// 録画を開始します。
recorder.startRecording();ビデオクリップの録画
// 録画を開始します。
recorder.startRecording();
// 録画を停止してビデオクリップを生成します。
recorder.stopRecording();
recorder.startRecording();
// 録画をキャンセルします。現在のビデオクリップは保存されません。
recorder.cancelRecording();
// 次のビデオクリップの録画を続行します。
recorder.startRecording();
recorder.stopRecording();録画の停止
録画を停止する際に、録画したクリップを 1 つの動画にマージするか、クリップの構成情報のみを生成するかを選択できます。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
// 録画を停止し、ビデオクリップを 1 つの動画にマージします。
recorder.finishRecording();
// 録画を停止し、クリップの構成情報を生成します (マージは行いません)。
recorder.finishRecordingForEdit();録画の制御と管理
カメラタイプやフラッシュモードなどのカメラ制御、最大・最小録画時間やクリップ削除などのクリップ管理設定を構成します。この手順は任意です。
使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
録画カメラの制御
// カメラの数を取得します。
AliyunIRrecorder.getCameraCount();
// カメラタイプを設定します。
AliyunIRecorder.setCamera(cameraType);
// 録画をミュートします。
AliyunIRecorder.setMute(boolean isMute);
// センサーの回転角度を設定します。
// 重要:API リファレンスをよくお読みください。
AliyunIRecorder.setRotation(int rotation);
// 録画の回転角度を設定します。
// 重要:API リファレンスをよくお読みください。
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();エフェクトの設定
レタッチ、フィルター、バックグラウンドミュージックなどのエフェクトを適用します。この手順は任意です。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
フィルター
カスタムフィルターを使用できます。作成方法については、「フィルターとトランジション」をご参照ください。
// フィルターを適用します。
AliyunIRecorder.applyFilter(EffectFilter effectFilter);// フィルターを削除するには、path パラメーターを 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 と統合する必要があります。
Alibaba Cloud Queen SDK の統合方法については、「Alibaba Cloud Queen SDK」をご参照ください。エフェクトの設定方法を示すサンプルコードについては、「使用例」をご参照ください。
FaceUnity の購入、統合、使用方法については、「FaceUnity」をご参照ください。
サードパーティ製レタッチ SDK が機能するには、カメラテクスチャ ID とカメラの生フレームデータの 2 種類のデータが必要です。以下のコードは、このデータを取得する方法を示しています。
カメラテクスチャ 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() { // SDK バージョン 3.7.8 より前では、カスタムレンダリング (サードパーティレンダリング) の GL リソースを破棄するために GLSurfaceView.queueEvent を使用できます。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() { } });
その他の機能
動画録画中に写真撮影と顔認識を有効にできます。 使用されるパラメーターの詳細については、「関連クラス」セクションの API リファレンスをご参照ください。
写真撮影
エフェクト付きで写真を撮影するか、システムカメラを使用してエフェクトなしで写真を撮影できます。写真データは 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);
// 顔検出の回転角度を設定します。
// 重要:API リファレンスをよくお読みください。
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, "Stop recording", 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, "Start recording", 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@RecordActivity, "Photo saved to album", 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>