import io.livekit.android.room.track.LocalVideoTrackOptions
import org.webrtc.VideoFrame
import org.webrtc.VideoProcessor
import org.webrtc.VideoSink
class FacebetterVideoProcessor(
private val appContext: android.content.Context,
) : VideoProcessor {
private var sink: VideoSink? = null
private var beautyEngine: BeautyEffectEngine? = null
override fun setSink(videoSink: VideoSink?) {
sink = videoSink
}
override fun onCapturerStarted(success: Boolean) {}
override fun onCapturerStopped() {
beautyEngine?.release()
beautyEngine = null
}
override fun onFrameCaptured(frame: VideoFrame) {
val buffer = frame.buffer
if (buffer !is VideoFrame.TextureBuffer ||
buffer.type != VideoFrame.TextureBuffer.Type.RGB
) {
sink?.onFrame(frame)
return
}
ensureEngine() // LiveKit / WebRTC current EGL context
val outId = processTexture(
beautyEngine,
buffer.textureId,
buffer.width,
buffer.height,
)
// Build a new TextureBuffer / VideoFrame from outId, then:
// sink?.onFrame(processedFrame)
// processedFrame.release()
//
// TextureBuffer construction needs WebRTC Handler / YuvConverter, etc. —
// follow LiveKit Android SDK and WebRTC samples for the wrap.
sink?.onFrame(frame)
}
}
// Attach the processor when creating the track (API per your livekit-android version)
val videoTrack = room.localParticipant.createVideoTrack(
options = LocalVideoTrackOptions(),
videoProcessor = FacebetterVideoProcessor(context),
)
videoTrack.startCapture()
room.localParticipant.publishVideoTrack(videoTrack)