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
- Request
CAMERAandRECORD_AUDIOpermissions before joining as host - Initialize video views before calling
joinAsHost() - Handle lifecycle properly - release resources in
onDestroy() - Use
runOnUiThread()when updating UI from callbacks - For beauty filters, set the processor before joining the room