nimeet Docs
中文

Screen Sharing

Capture methods, sourceId selection, permissions and common issues per platform.

Version v1.1.0 · Updated 2026-10-26 · revision 1

Screen sharing uses a different mechanism on every platform: browsers go through getDisplayMedia (the user picks a source), desktop apps enumerate sources and pin an id, and mobile platforms go through system screen mirroring or recording extensions. This page gives the exact entry-point method names per platform, and covers permissions and common pitfalls.

Prerequisites

  • The SDK for your platform is integrated and token authentication is working.
  • Browser: the page runs in a secure context (HTTPS or localhost) and the user gesture starts sharing.
  • Desktop: screen-recording permission is granted; mobile: the system screen-mirroring/recording extension is available.

Entry points per platform (method names from the public interface definition)

PlatformCapture entry pointStopSource selection
WebAgoraRTC.createScreenVideoTrack(config, withAudio)track.close()Browser picker; in Electron pin the source with electronScreenSourceId
ElectronAgoraRTC.createScreenVideoTrack({ electronScreenSourceId }, 'disable')track.close()Enumerate with window.nimeetDesktop.getSources()
AndroidstartScreenCapture(ScreenCaptureParameters)stopScreenCapture()MediaProjection consent
iOSstartScreenCapture:stopScreenCaptureReplayKit Broadcast Upload Extension
macOSstartScreenCaptureByDisplayId:regionRect:captureParams: / startScreenCaptureByWindowId:...stopScreenCapturegetScreenCaptureSourcesWithThumbSize:iconSize:includeScreen:
Windows (C++)startScreenCaptureByWindowId / startScreenCaptureByScreenRect / startScreenCaptureByDisplayIdstopScreenCapturegetScreenCaptureSources
FlutterstartScreenCapture(...)stopScreenCapture()getScreenCaptureSources()
React NativestartScreenCapture(...)stopScreenCapture()Native platform capabilities
UnityStartScreenCaptureByDisplayId / StartScreenCaptureByWindowIdStopScreenCaptureGetScreenCaptureSources
Unreal (C++)startScreenCaptureByDisplayId / startScreenCaptureByWindowIdstopScreenCapturegetScreenCaptureSources
Unreal (Blueprint)StartScreenCaptureByDisplayId / StartScreenCaptureByWindowIdStopScreenCaptureGetScreenCaptureSources
C#StartScreenCaptureByWindowId / StartScreenCaptureByScreenRectStopScreenCaptureGetScreenCaptureSources
HarmonyOSstartScreenCapture(parameters)stopScreenCapture()System screen-recording permission
Cocos Creator——No public interface definition (see the Cocos page)

Full signatures (including parameter types) live in the API reference for each platform; do not write them from memory.

Web: the three snippets you need most

javascript
import AgoraRTC from '@nimeet/rtc-web';

const client = AgoraRTC.createClient({ mode: 'rtc' });

// 1) Share video only
const screenVideoTrack = await AgoraRTC.createScreenVideoTrack({ encoderConfig: '1080p_1' }, 'disable');
await client.publish(screenVideoTrack);

// 2) Share video and system audio together (Chrome/Edge support this; Safari does not support system audio)
const [videoTrack, audioTrack] = await AgoraRTC.createScreenVideoTrack({ encoderConfig: '1080p_1' }, 'enable');
await client.publish([videoTrack, audioTrack]);

// 3) When the user clicks "Stop sharing" (in the browser toolbar)
screenVideoTrack.on('track-ended', () => {
  client.unpublish(screenVideoTrack);
  screenVideoTrack.close();
});

Always handle track-ended: when the user stops sharing from the browser's native toolbar the track ends by itself, and without a handler you end up "still publishing a dead track".

Electron: pinning the source (the key difference from the browser)

javascript
const sources = await window.nimeetDesktop.getSources({ types: ['screen', 'window'] });
const primary = sources.find((source) => source.isScreen);
const track = await AgoraRTC.createScreenVideoTrack({ electronScreenSourceId: primary.id }, 'disable');
await client.publish(track);

Once electronScreenSourceId is pinned, switching the foreground window does not change what is being shared — this is the behaviour you need for "share a specific PPT window".

Mobile: a different permission model

  • Android: requires the MediaProjection consent dialog plus a foreground service (from Android 14 onwards the FOREGROUND_SERVICE_MEDIA_PROJECTION type is also required). Without a foreground service, moving to the background gets the capture reclaimed immediately.
  • iOS: direct screen recording is not possible; a Broadcast Upload Extension must capture the sample buffers, and the app and the extension share state through an App Group. The user starts and stops the broadcast from Control Center.
  • HarmonyOS: uses the system screen-recording permission, which must be declared in module.json5 and requested at runtime.

Choosing encoder parameters

ScenarioRecommendation
Documentation and code demos1080p / 15fps / prefer sharpness (degradationPreference: 'maintain-resolution')
Video playback demos1080p / 30fps / raise the bitrate ceiling
Poor networks720p / 15fps / prefer frame rate
Low-bandwidth mobile clientsSubscribe to the low stream only for screen sharing (see Stream control and fallback)

Common issues

SymptomCauseHandling
The shared content is blackThe user picked a protected window (DRM or a private page)Switch to the whole screen or to a visible window
The macOS source list is emptyThe "Screen Recording" permission was not grantedGrant it in System Settings and restart the app
The other side sees a mirrored or upside-down imageThe screen track is handled as a camera trackCheck whether the render layer distinguishes by sourceType
Sharing system audio failsSafari/Firefox do not support itShare video only and route audio through the microphone
Frame rate collapses while sharingResolution too high plus a poor networkLower encoderConfig or enable the low stream
Still sending after sharing has stoppedtrack-ended was not handled / unpublish was not calledSee snippet 3 above

Next steps

Generated by the documentation build pipeline · 2026-10-31 01:24:02 UTC · Documentation center v1.1.0.

Content follows the public API definitions.

ni-meet is a self-hosted RTC PaaS with a LiveKit-based media plane (Apache-2.0) and an Agora-compatible API.