← Cloudflare Realtime / realtime / realtimekit / core
Удалённые участники
Это руководство объясняет, как получать данные участников, отображать видео, обрабатывать события и управлять разрешениями участников во встречах RealtimeKit.
Объект участника содержит всю информацию, относящуюся к конкретному участнику, включая сведения о сетке, медиапотоках каждого участника, имени и переменных состояния. Он доступен через meeting.participants.
Свойства
Свойства метаданных
id-participantIdучастника (также известного какpeerId)userId-userIdучастникаname- Имя участникаpicture- Изображение участника (если есть)customParticipantId- Произвольный ID, который можно задать для идентификации участникаisPinned- Устанавливается вtrueесли участник закреплёнpresetName- Имя пресета, связанного с участником
Свойства метаданных
id- Идентификатор, уникальный для сессии, создаваемый при присоединении участника к сессии встречи (также известный какpeerId)userId- Постоянный идентификатор участника, создаваемый при добавлении участника во встречуname- Отображаемое имя участникаpicture- Строка URL с изображением профиля участника (если есть)customParticipantId- Пользовательский идентификатор, который заказчик может задать при добавлении участника во встречуisHost- Логическое значение, указывающее, есть ли у этого участника права организатораisPinned- Закреплён ли этот участник в данный момент во встречеpresetName- Имя пресета, применённого к этому участнику при добавлении во встречуstageStatus- Указывает текущий статус участника на сцене (применимо только для встреч с включенной сценой)
Свойства метаданных
id- Идентификатор, уникальный для сессии, создаваемый при присоединении участника к сессии встречи (также известный какpeerId)userId- Постоянный идентификатор участника, создаваемый при добавлении участника во встречуname- Отображаемое имя участникаpicture- Строка URL с изображением профиля участника (если есть)customParticipantId- Пользовательский идентификатор, который заказчик может задать при добавлении участника во встречуisHost- Логическое значение, указывающее, есть ли у этого участника права организатораisPinned- Закреплён ли этот участник в данный момент во встречеpresetName- Имя пресета, применённого к этому участнику при добавлении во встречуstageStatus- Указывает текущий статус участника на сцене (применимо только для встреч с включенной сценой)
Свойства медиа
videoEnabled- Устанавливается вtrueесли у участника включена камераaudioEnabled- Устанавливается вtrueесли у участника включён микрофонscreenShareEnabled- Устанавливается вtrueесли участник демонстрирует экранvideoTrack- Видеодорожка участникаaudioTrack- Аудиодорожка участникаscreenShareTracks- Видео и аудиодорожки демонстрации экрана участника
Свойства медиа
videoEnabled- Включена ли в данный момент камера участникаaudioEnabled- Включён ли в данный момент микрофон участникаscreenshareEnabled- Демонстрирует ли участник в данный момент экран
Доступ к свойствам участника
// Number of participants joined in the meeting
console.log(meeting.participants.count);
// Number of pages available in paginated mode
console.log(meeting.participants.pageCount);
// Maximum number of participants in active state
console.log(meeting.participants.maxActiveParticipantsCount);
// ParticipantId of the last participant who spoke
console.log(meeting.participants.lastActiveSpeaker);Используйте useRealtimeKitSelector хук для доступа к свойствам:
// Number of participants joined in the meeting
const participantCount = useRealtimeKitSelector((m) => m.participants.count);
// Number of pages available in paginated mode
const pageCount = useRealtimeKitSelector((m) => m.participants.pageCount);
// Maximum number of participants in active state
const maxActiveCount = useRealtimeKitSelector(
(m) => m.participants.maxActiveParticipantsCount,
);
// ParticipantId of the last participant who spoke
const lastActiveSpeaker = useRealtimeKitSelector(
(m) => m.participants.lastActiveSpeaker,
);// Number of participants joined in the meeting
val participantCount = meeting.participants.joined.size
// Access pagination properties
val maxNumberOnScreen = meeting.participants.maxNumberOnScreen
val currentPageNumber = meeting.participants.currentPageNumber
val pageCount = meeting.participants.pageCount
val canGoNextPage = meeting.participants.canGoNextPage
val canGoPreviousPage = meeting.participants.canGoPreviousPage// Number of participants joined in the meeting
let participantCount = meeting.participants.joined.count
// Access pagination properties
let maxNumberOnScreen = meeting.participants.maxNumberOnScreen
let currentPageNumber = meeting.participants.currentPageNumber
let pageCount = meeting.participants.pageCount
let canGoNextPage = meeting.participants.canGoNextPage
let canGoPreviousPage = meeting.participants.canGoPreviousPageИспользуйте useRealtimeKitSelector хук для доступа к свойствам:
// Number of participants joined in the meeting
const participantCount = useRealtimeKitSelector((m) => m.participants.count);
// Number of pages available in paginated mode
const pageCount = useRealtimeKitSelector((m) => m.participants.pageCount);
// Maximum number of participants in active state
const maxActiveCount = useRealtimeKitSelector(
(m) => m.participants.maxActiveParticipantsCount,
);
// ParticipantId of the last participant who spoke
const lastActiveSpeaker = useRealtimeKitSelector(
(m) => m.participants.lastActiveSpeaker,
);Доступ к объекту участника
Участника можно получить из карты участников.
const participant = meeting.participants.joined.get(participantId);
// Access participant properties
console.log(participant.name);
console.log(participant.videoEnabled);
console.log(participant.audioEnabled);// Get a specific participant
const participant = useRealtimeKitSelector((m) =>
m.participants.joined.get(participantId),
);
// Access participant properties
const participantName = participant?.name;
const isVideoEnabled = participant?.videoEnabled;
const isAudioEnabled = participant?.audioEnabled;// Find a participant by peer ID
val participant = meeting.participants.joined.firstOrNull { it.id == participantId }
// Access participant properties
participant?.let {
println("Participant: ${it.name}")
println("Video: ${it.videoEnabled}")
println("Audio: ${it.audioEnabled}")
}// Find a participant by peer ID
if let participant = meeting.participants.joined.first(where: { $0.id == participantId }) {
// Access participant properties
print("Participant: \(participant.name)")
print("Video: \(participant.videoEnabled)")
print("Audio: \(participant.audioEnabled)")
}// Get a specific participant
const participant = useRealtimeKitSelector((m) =>
m.participants.joined.get(participantId),
);
// Access participant properties
const participantName = participant?.name;
const isVideoEnabled = participant?.videoEnabled;
const isAudioEnabled = participant?.audioEnabled;Карты участников
Все участники хранятся в meeting.participants. Они не включают локального пользователя.
meeting.participants объект содержит следующие карты:
joined- Все участники, находящиеся во встрече в данный момент (кроме локального пользователя)waitlisted- Все участники, ожидающие присоединения к встречеactive- Все участники, на медиаданные которых оформлена подписка (участники, которые должны отображаться на экране)pinned- Все закрепленные участники встречи
Если вы создаёте сетку видео и аудио, используйте active map. Чтобы отобразить список всех участников, используйте joined map.
Каждый участник в этих map имеет тип RTKParticipant.
Все участники хранятся в meeting.participants. Они не включают локального пользователя.
meeting.participants объект содержит следующие списки:
joined- Все участники, находящиеся во встрече в данный момент (кроме локального пользователя)waitlisted- Все участники, ожидающие присоединения к встречеactive- Все участники, на медиаданные которых оформлена подписка (участники, которые должны отображаться на экране)pinned- Все закрепленные участники встречиscreenShares- Все участники, демонстрирующие экран
Если вы создаёте сетку видео и аудио, используйте active список. Чтобы отобразить список всех участников, используйте joined список.
// Get all joined participants
const joinedParticipants = meeting.participants.joined;
// Get active participants (those on screen)
const activeParticipants = meeting.participants.active;
// Get pinned participants
const pinnedParticipants = meeting.participants.pinned;
// Get waitlisted participants
const waitlistedParticipants = meeting.participants.waitlisted;Используйте useRealtimeKitSelector хук для доступа к картам участников:
import { useRealtimeKitSelector } from "@cloudflare/realtimekit-react";
// Get all joined participants
const joinedParticipants = useRealtimeKitSelector((m) => m.participants.joined);
// Get active participants (those on screen)
const activeParticipants = useRealtimeKitSelector((m) => m.participants.active);
// Get pinned participants
const pinnedParticipants = useRealtimeKitSelector((m) => m.participants.pinned);
// Get waitlisted participants
const waitlistedParticipants = useRealtimeKitSelector(
(m) => m.participants.waitlisted,
);// Get all joined participants
val joinedParticipants: List<RtkRemoteParticipant> = meeting.participants.joined
// Get active participants (those on screen)
val activeParticipants: List<RtkRemoteParticipant> = meeting.participants.active
// Get pinned participants
val pinnedParticipants: List<RtkRemoteParticipant> = meeting.participants.pinned
// Get waitlisted participants
val waitlistedParticipants: List<RtkRemoteParticipant> = meeting.participants.waitlisted
// Get screen sharing participants
val screenShareParticipants: List<RtkRemoteParticipant> = meeting.participants.screenShares// Get all joined participants
let joinedParticipants: [RtkRemoteParticipant] = meeting.participants.joined
// Get active participants (those on screen)
let activeParticipants: [RtkRemoteParticipant] = meeting.participants.active
// Get pinned participants
let pinnedParticipants: [RtkRemoteParticipant] = meeting.participants.pinned
// Get waitlisted participants
let waitlistedParticipants: [RtkRemoteParticipant] = meeting.participants.waitlisted
// Get screen sharing participants
let screenShareParticipants: [RtkRemoteParticipant] = meeting.participants.screenSharesИспользуйте useRealtimeKitSelector хук для доступа к картам участников:
import { useRealtimeKitSelector } from "@cloudflare/realtimekit-react-native";
// Get all joined participants
const joinedParticipants = useRealtimeKitSelector((m) => m.participants.joined);
// Get active participants (those on screen)
const activeParticipants = useRealtimeKitSelector((m) => m.participants.active);
// Get pinned participants
const pinnedParticipants = useRealtimeKitSelector((m) => m.participants.pinned);
// Get waitlisted participants
const waitlistedParticipants = useRealtimeKitSelector(
(m) => m.participants.waitlisted,
);Режимы отображения
Режим отображения показывает, размещаются ли участники в ACTIVE_GRID режим или PAGINATED режим.
ACTIVE_GRIDрежим - Участники автоматически заменяются вmeeting.participants.activeв зависимости от того, кто говорит или у кого включено видеоPAGINATEDрежим - Участники вmeeting.participants.activeфиксированы. ИспользуйтеsetPage()чтобы изменить активных участников
Настроить режим отображения
// Set the view mode to paginated
await meeting.participants.setViewMode("PAGINATED");
// Set the view mode to active grid
await meeting.participants.setViewMode("ACTIVE_GRID");Используйте useRealtimeKitClient хук для доступа к объекту встречи:
import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
// Set the view mode to paginated
await meeting.participants.setViewMode("PAGINATED");
// Set the view mode to active grid
await meeting.participants.setViewMode("ACTIVE_GRID");По умолчанию Android SDK использует активный режим сетки на странице 0. При переключении на следующую страницу он автоматически переходит в постраничный режим.
По умолчанию iOS SDK использует активный режим сетки на странице 0. При переключении на следующую страницу он автоматически переходит в постраничный режим.
// Set the view mode to paginated
await meeting.participants.setViewMode("PAGINATED");
// Set the view mode to active grid
await meeting.participants.setViewMode("ACTIVE_GRID");Задать страницу в постраничном режиме
// Switch to second page
await meeting.participants.setPage(2);import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
// Switch to second page
await meeting.participants.setPage(2);// Switch to first page
meeting.participants.setPage(1)// Switch to first page
meeting.participants.setPage(1)// Switch to second page
await meeting.participants.setPage(2);Режим наблюдения
const viewMode = meeting.participants.viewMode;
const currentPage = meeting.participants.currentPage;const viewMode = useRealtimeKitSelector((m) => m.participants.viewMode);
const currentPage = useRealtimeKitSelector((m) => m.participants.currentPage);Режим наблюдения недоступен на этой платформе.
const viewMode = useRealtimeKitSelector((m) => m.participants.viewMode);
const currentPage = useRealtimeKitSelector((m) => m.participants.currentPage);Элементы управления организатора
Объект участника предоставляет организатору несколько элементов управления. Их можно выбрать при создании пресет.
Управление медиа
При наличии нужных разрешений организатор может отключать медиа удаленных участников.
const participant = meeting.participants.joined.get(participantId);
// Disable a participant's video stream
participant.disableVideo();
// Disable a participant's audio stream
participant.disableAudio();
// Kick a participant from the meeting
participant.kick();import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
const participant = meeting.participants.joined.get(participantId);
// Disable a participant's video stream
participant.disableVideo();
// Disable a participant's audio stream
participant.disableAudio();
// Kick a participant from the meeting
participant.kick();val participant = meeting.participants.joined.firstOrNull { it.id == participantId }
participant?.let { pcpt ->
// Disable a participant's video stream
val videoError = pcpt.disableVideo()
// Disable a participant's audio stream
val audioError = pcpt.disableAudio()
// Kick a participant from the meeting
val kickError = pcpt.kick()
}if let participant = meeting.participants.joined.first(where: { $0.id == participantId }) {
// Disable a participant's video stream
let videoError: HostError? = participant.disableVideo()
// Disable a participant's audio stream
let audioError: HostError? = participant.disableAudio()
// Kick a participant from the meeting
let kickError: HostError? = participant.kick()
}const participant = meeting.participants.joined.get(participantId);
// Disable a participant's video stream
participant.disableVideo();
// Disable a participant's audio stream
participant.disableAudio();
// Kick a participant from the meeting
participant.kick();Элементы управления залом ожидания
Зал ожидания позволяет организатору контролировать, какие пользователи и когда могут присоединиться к вашей встрече. Он может принять или отклонить запрос.
Этот процесс также можно автоматизировать, чтобы пользователи присоединялись к встрече автоматически, когда к ней присоединяется организатор, с помощью пресеты.
Принятие запроса на вход в зал ожидания
await meeting.participants.acceptWaitingRoomRequest(participantId);import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
await meeting.participants.acceptWaitingRoomRequest(participantId);meeting.participants.acceptWaitingRoomRequest(participantId)meeting.participants.acceptWaitingRoomRequest(id: participantId)await meeting.participants.acceptWaitingRoomRequest(participantId);Отклоните запрос из зала ожидания
await meeting.participants.rejectWaitingRoomRequest(participantId);import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
await meeting.participants.rejectWaitingRoomRequest(participantId);meeting.participants.rejectWaitingRoomRequest(participantId)meeting.participants.rejectWaitingRoomRequest(participantId)await meeting.participants.rejectWaitingRoomRequest(participantId);Закрепление участников
Организатор может закреплять или откреплять участников в сетке.
const participant = meeting.participants.joined.get(participantId);
// Pin a participant
await participant.pin();
// Unpin a participant
await participant.unpin();import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
const participant = meeting.participants.joined.get(participantId);
// Pin a participant
await participant.pin();
// Unpin a participant
await participant.unpin();val participant = meeting.participants.joined.firstOrNull { it.id == participantId }
participant?.let { pcpt ->
// Pin a participant
val pinError = pcpt.pin()
// Unpin a participant
val unpinError = pcpt.unpin()
}if let participant = meeting.participants.joined.first(where: { $0.id == participantId }) {
// Pin a participant
let pinError: HostError? = participant.pin()
// Unpin a participant
let unpinError: HostError? = participant.unpin()
}const participant = meeting.participants.joined.get(participantId);
// Pin a participant
await participant.pin();
// Unpin a participant
await participant.unpin();Обновление разрешений участника
Организатор может изменять разрешения участника. Разрешения участника определяются его пресетом.
Обновление разрешений участника недоступно на этой платформе.
Сначала найдите участника или участников, которых нужно обновить.
const participantIds = meeting.participants.joined
.toArray()
.filter((e) => e.name.startsWith("John"))
.map((p) => p.id);Используйте updatePermissions метод, чтобы изменить разрешения участника.
// Allow file upload permissions in public chat
const newPermissions = {
chat: {
public: {
files: true,
},
},
};
meeting.participants.updatePermissions(participantIds, newPermissions);Можно изменить следующие разрешения:
interface UpdatedPermissions {
polls?: {
canCreate?: boolean;
canVote?: boolean;
};
plugins?: {
canClose?: boolean;
canStart?: boolean;
};
chat?: {
public?: {
canSend?: boolean;
text?: boolean;
files?: boolean;
};
private?: {
canSend?: boolean;
text?: boolean;
files?: boolean;
};
};
}Отображение видео участников
Чтобы воспроизвести видеодорожку участника на <video> (элемент):
<video class="participant-video" id="participant-video"></video>// Get the video element
const videoElement = document.getElementById("participant-video");
// Get the participant
const participant = meeting.participants.joined.get(participantId);
// Register the video element
participant.registerVideoElement(videoElement);Для локального предпросмотра пользователя (видео не отправляется другим пользователям):
meeting.self.registerVideoElement(videoElement, true);Очистите ресурсы, когда видеоэлемент больше не нужен:
participant.deregisterVideoElement(videoElement);Чтобы воспроизвести видеодорожку участника на <video> (элемент):
import { useRealtimeKitClient } from "@cloudflare/realtimekit-react";
const [meeting] = useRealtimeKitClient();
// Get the video element
const videoElement = document.getElementById("participant-video");
// Get the participant
const participant = meeting.participants.joined.get(participantId);
// Register the video element
participant.registerVideoElement(videoElement);
// Clean up when the video element is no longer needed
participant.deregisterVideoElement(videoElement);Для локального предпросмотра пользователя (видео не отправляется другим пользователям):
meeting.self.registerVideoElement(videoElement, true);Вызовите participant.getVideoView() который возвращает View который отрисовывает видеопоток участника:
// Get video view of a given participant
val videoView = participant.getVideoView()
// Get screen share video view
val screenShareView = participant.getScreenShareVideoView()Вызовите participant.getVideoView() который возвращает UIView который отрисовывает видеопоток участника:
// Get video view of a given participant
let videoView = participant.getVideoView()
// Get screen share video view
let screenShareView = participant.getScreenShareVideoView()Используйте useRealtimeKitSelector чтобы получить видеодорожку и отрисовать её с помощью RTCView:
import { useRealtimeKitSelector } from "@cloudflare/realtimekit-react-native";
import { MediaStream, RTCView } from "@cloudflare/react-native-webrtc";
function VideoView() {
const { videoTrack } = useRealtimeKitSelector((m) =>
m.participants.active.toArray(),
)[0];
const stream = new MediaStream(undefined);
stream.addTrack(videoTrack);
return (
<RTCView
objectFit="cover"
style={{ flex: 1 }}
streamURL={stream.toURL()}
mirror={true}
zOrder={1}
/>
);
}