Skip to main content
Version: 0.1.x

Picture-in-Picture Mode - React Native

Picture-in-picture (PiP) is a commonly used feature in video conferencing software, enabling users to simultaneously engage in a video conference and perform other tasks on their device. With PiP, you can keep the video conference window open, resize it to a smaller size, and continue working on other tasks while still seeing and hearing the other participants in the conference. This feature proves beneficial when you need to take notes, send an email, or look up information during the conference.

This guide explains the steps to implement the Picture-in-Picture feature using VideoSDK.

info
  • Picture-in-Picture (PiP) functionality is not supported after screen sharing
  • PiP is available exclusively on Android devices.

Step 1: Install Package

To begin with, you need to install a third party package react-native-pip-android to achieve PiP mode in android.

npm install react-native-pip-android

Step 2: Setup

Include the following attribute in /android/app/src/main/AndroidManifest.xml file.

  <activity
...
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...

Step 3: Import Activity in MainActivity.java file

...
import com.reactnativepipandroid.PipAndroidModule;

public class MainActivity extends ReactActivity {

...

@Override
public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode) {
PipAndroidModule.pipModeChanged(isInPictureInPictureMode);
}

Step 4: Setup PiP for Rendering participant media

To set up Picture-in-Picture (PiP) mode for rendering participant media, you can utilize the usePipModeListener hook to control the rendering. The example below demonstrate s how to render a participant list.

import PipHandler, { usePipModeListener } from "react-native-pip-android";

function ParticipantView({ participantId, inPipMode }) {
const { webcamStream, webcamOn } = useParticipant(participantId);

return webcamOn && webcamStream ? (
<RTCView
streamURL={new MediaStream([webcamStream.track]).toURL()}
objectFit={"cover"}
style={{
height: inPipMode ? 75 : 300,
marginVertical: 8,
marginHorizontal: 8,
}}
/>
) : null;
}

function ControlsContainer() {
return null;
}

function MeetingView() {
// Get `participants` from useMeeting Hook
const { participants } = useMeeting({});

const inPipMode = usePipModeListener();

// Use this boolean to show / hide ui when pip mode changes
if (inPipMode) {
// Render the participant in PiP Box

return [...participants.keys()].map((participantId, index) => (
<ParticipantView
key={index}
participantId={participantId}
inPipMode={true}
/>
));
}

return (
<View style={{ flex: 1 }}>
{[...participants.keys()].map((participantId, index) => (
<ParticipantView key={index} participantId={participantId} />
))}
<ControlsContainer />
</View>
);
}

Step 5: Enter in PiP mode

To enter Picture-in-Picture (PiP) mode, use the enterPipMode method of PipHandler. Provide the PiP box's height and width as parameters to this method.

function ControlsContainer() {
const { join, leave } = useMeeting();
return (
<View
style={{
padding: 24,
flexDirection: "row",
justifyContent: "space-evenly",
}}
>
<Button
onPress={() => {
join();
}}
buttonText={"Join"}
backgroundColor={"#1178F8"}
/>
<Button
onPress={() => {
leave();
}}
buttonText={"Leave"}
backgroundColor={"#FF0000"}
/>
<Button
onPress={() => {
PipHandler.enterPipMode(300, 500);
}}
buttonText={"PiP"}
backgroundColor={"blue"}
/>
</View>
);
}

Output


Got a Question? Ask us on discord