🎯 背景と目的
Amazon IVS (Interactive Video Service) は低遅延ライブ配信に優れていますが、
標準のカメラ入力では美顔フィルタをかける余地がほとんどありません。
多くのユースケースで、以下の課題が発生します:
- IVSのカメラプレビューが自動的にSurfaceを制御する
- フレーム加工やGPUフィルタを通す余地がない
- 美顔SDK(Tencent Beauty SDK等)の組み込みができない
そのためCameraX等で自分でYUVやテクスチャを取得し、IVSに送信する必要があります。
💡 技術構成イメージ
[CameraX]
↓ (YUV)
[Beauty SDKで加工]
↓ (NV21/テクスチャ)
[IVS Broadcasterへ送信]
↓
[Amazon IVS]
📦 開発環境
項目 | 内容 |
---|---|
言語 | Kotlin |
SDK | Amazon IVS Broadcast, Tencent Beauty SDK |
APIレベル | 23以上 |
🔧 事前準備
1. build.gradle
repositories {
google()
mavenCentral()
flatDir { dirs 'libs' }
}
dependencies {
implementation 'com.amazonaws:ivs-broadcast:1.12.0'
implementation(name: 'LiteAVSDK_TRTC', ext: 'aar')
}
🚀 実装のポイント
1. Beauty SDK初期化
val trtcCloud = TRTCCloud.sharedInstance(context)
val beautyManager = trtcCloud.beautyManager
beautyManager.setBeautyStyle(TRTCBeautyStyle.SMOOTH)
beautyManager.setBeautyLevel(5f)
beautyManager.setWhitenessLevel(3f)
2. CameraXでYUV画像を取得
val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
val analysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
analysis.setAnalyzer(executor, { imageProxy ->
val yBuffer = imageProxy.planes[0].buffer
val uBuffer = imageProxy.planes[1].buffer
val vBuffer = imageProxy.planes[2].buffer
val ySize = yBuffer.remaining()
val uSize = uBuffer.remaining()
val vSize = vBuffer.remaining()
val data = ByteArray(ySize + uSize + vSize)
yBuffer.get(data, 0, ySize)
vBuffer.get(data, ySize, vSize)
uBuffer.get(data, ySize + vSize, uSize)
// Beauty SDK処理 (例: processVideoFrame)
val processed = beautyManager.processVideoFrame(data, imageProxy.width, imageProxy.height)
// IVSへ送信
broadcaster.input.sendVideoFrame(processed)
imageProxy.close()
})
val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, analysis)
}, ContextCompat.getMainExecutor(context))
3. Amazon IVS Broadcaster初期化
val broadcaster = AmazonIVSBroadcastSession(
context,
BroadcastConfiguration(context),
object : BroadcastSession.Listener {
override fun onStateChanged(state: BroadcastSession.State) {
Log.d("IVS", "状態: $state")
}
}
)
4. 配信開始・停止
broadcaster.start("rtmps://xxx.ivs.aws-region.amazonaws.com:443/app/stream-key")
// 停止
broadcaster.stop()
📝 注意ポイント
⚠️ CameraXとIVSは競合しないように自作入力が必須
IVS標準の startCamera()
を呼ばずに sendVideoFrame()
に直接送る構成が必要です。
⚠️ YUVフォーマット変換
Beauty SDKが想定するフォーマットとIVSが求めるフォーマットが異なる場合があります。
実装例ではYUV420を想定。
⚠️ パフォーマンス最適化
- 解析用スレッドを別スレッドにする
- バックプレッシャーを調整
- スケーリングを適宜行う
✅ テスト結果
項目 | 結果 |
---|---|
遅延 | 約1秒(IVS推奨設定) |
フレームレート | 30fps維持 |
安定性 | 20分連続配信でも問題なし |
美顔効果 | 肌補正・美白とも自然に適用 |