Video Streaming

ConoStream SDK provides HD video streaming with adaptive bitrate, low latency, and support for beauty filters. This guide covers how to publish and display video streams.

Using ConoStreamVideoHelper

For video streaming, use the ConoStreamVideoHelper class which handles camera capture, rendering, and video track management.

public class VideoLiveActivity extends AppCompatActivity {

    private ConoStreamVideoHelper videoHelper;
    private TextureViewRenderer localVideoView;
    private TextureViewRenderer remoteVideoView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_live);

        // Find video views
        localVideoView = findViewById(R.id.local_video_view);
        remoteVideoView = findViewById(R.id.remote_video_view);

        // Get manager from Application
        ConoStreamManager manager = getConoStreamManager();

        // Initialize video helper
        videoHelper = new ConoStreamVideoHelper(manager, this);

        // Set event callback
        videoHelper.setEventCallback(new ConoStreamVideoEventCallback() {
            @Override
            public void onLocalVideoTrackPublished() {
                Log.d("Video", "Local video published");
            }

            @Override
            public void onRemoteVideoTrackSubscribed(String participantId, VideoTrack track) {
                // Display remote video
                runOnUiThread(() -> {
                    track.addRenderer(remoteVideoView);
                    remoteVideoView.setVisibility(View.VISIBLE);
                });
            }
        });
    }
}

Layout Setup

Add TextureViewRenderer views to your layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Remote video (full screen, behind) -->
    <io.conostream.webrtc.TextureViewRenderer
        android:id="@+id/remote_video_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <!-- Local video (small, corner) -->
    <io.conostream.webrtc.TextureViewRenderer
        android:id="@+id/local_video_view"
        android:layout_width="120dp"
        android:layout_height="160dp"
        android:layout_gravity="top|end"
        android:layout_margin="16dp" />

</FrameLayout>

Joining as Host (with Video)

// Join as host - will publish both camera and microphone
videoHelper.joinAsHost(
    serverUrl,
    token,
    channelName,
    localVideoView    // View to render local camera
);

Joining as Audience

// Join as audience - watch and listen only
videoHelper.joinAsAudience(serverUrl, token, channelName);

Camera Controls

Switch Camera

// Switch between front and back camera
videoHelper.switchCamera();

// Or specify camera
videoHelper.switchCamera(CameraPosition.FRONT);
videoHelper.switchCamera(CameraPosition.BACK);

Enable/Disable Camera

// Turn camera off (stop publishing video)
videoHelper.enableCamera(false);

// Turn camera back on
videoHelper.enableCamera(true);

// Check camera state
boolean isEnabled = videoHelper.isCameraEnabled();

Displaying Remote Video

When a remote participant publishes video, handle it in the callback:

videoHelper.setEventCallback(new ConoStreamVideoEventCallback() {
    @Override
    public void onRemoteVideoTrackSubscribed(String participantId, VideoTrack track) {
        runOnUiThread(() -> {
            // Attach to renderer
            track.addRenderer(remoteVideoView);
            remoteVideoView.setVisibility(View.VISIBLE);
        });
    }

    @Override
    public void onRemoteVideoTrackUnsubscribed(String participantId) {
        runOnUiThread(() -> {
            remoteVideoView.setVisibility(View.GONE);
        });
    }
});

Beauty Filters Integration

ConoStream supports custom video processors for beauty filters. Add real-time beauty effects to your video stream:

// Create beauty processor
VideoProcessor beautyProcessor = new ConoStreamBeautyProcessor(context);

// Set processor before joining
videoHelper.setVideoProcessor(beautyProcessor);

// Then join as host
videoHelper.joinAsHost(serverUrl, token, channelName, localVideoView);

See Beauty Filters for detailed beauty effects setup.

Video Quality Settings

// Configure video quality before publishing
VideoEncoderConfig config = new VideoEncoderConfig(
    1280,   // width
    720,    // height
    30,     // framerate
    2000000 // bitrate (2 Mbps)
);

videoHelper.setVideoEncoderConfig(config);

PK Battle (Split Screen)

For PK battles between two hosts:

// Layout for PK mode
LinearLayout pkLayout = findViewById(R.id.pk_layout);
TextureViewRenderer pkLeftView = findViewById(R.id.pk_left);
TextureViewRenderer pkRightView = findViewById(R.id.pk_right);

// Start PK with opponent
videoHelper.startPk(
    opponentServerUrl,
    opponentToken,
    opponentChannelName,
    pkLeftView,    // Local host video
    pkRightView    // Opponent video
);

// Stop PK
videoHelper.stopPk();

See PK Battles for detailed implementation.

Cleanup

@Override
protected void onDestroy() {
    super.onDestroy();

    if (videoHelper != null) {
        videoHelper.release();
        videoHelper = null;
    }
}
⚠️

Important: Always call release() when leaving the video room to properly clean up camera resources and stop all streams.

Best Practices

Next Steps