joinRoom method
dynamic
joinRoom(
- RoomInfo roomInfo, {
- dynamic micEnabled = false,
- dynamic cameraEnabled = false,
Implementation
joinRoom(RoomInfo roomInfo,
{micEnabled = false,
cameraEnabled = false,
bool? screenShareEnabled,
bool? scrennShareEnabled}) async {
if (_currentRoomInfo != null) {
Logger.error("already in room");
return;
}
final enableScreenShare = screenShareEnabled ?? scrennShareEnabled ?? false;
final connectStopwatch = Stopwatch()..start();
Logger.info(
'[Room] joinRoom start room=${roomInfo.roomName} url=${roomInfo.url} '
'loginUID=${roomInfo.loginUID} rtcType=${roomInfo.rtcType} '
'uids=${roomInfo.uidList} mic=$micEnabled camera=$cameraEnabled '
'screen=$enableScreenShare timeout=${roomInfo.timeout}',
);
_currentRoomInfo = roomInfo;
_setConnectStatus(
roomInfo.roomName, ConnectStatus.connecting, "connecting");
room = Room(
roomOptions: RoomOptions(
// AdaptiveStream: 根据视频元素尺寸自动调整订阅质量
adaptiveStream: true,
// Dynacast: 动态暂停没有订阅者的视频层,节省带宽
dynacast: true,
// 视频捕获默认设置(发布端)- 4K 最高画质
defaultCameraCaptureOptions: const CameraCaptureOptions(
maxFrameRate: 30,
params: VideoParametersPresets.h2160_169, // 4K: 3840x2160
),
// 发布默认设置
defaultVideoPublishOptions: VideoPublishOptions(
simulcast: true, // 开启 simulcast 多层级发布
videoCodec: 'vp8', // 编码器
// 主层级的编码参数(4K 最高质量)
videoEncoding: const VideoEncoding(
maxBitrate: 8000000, // 8Mbps (4K)
maxFramerate: 30,
),
// 自定义 simulcast 层级(从低到高,网络差时自动降级)
videoSimulcastLayers: [
VideoParametersPresets.h360_169, // 640x360, 450kbps
VideoParametersPresets.h720_169, // 1280x720, 1.7Mbps
VideoParametersPresets.h1080_169, // 1920x1080, 3Mbps
],
),
),
);
listener = room!.createListener();
listener!
..on<RoomDisconnectedEvent>((event) {
Logger.info(
'[RoomEvent] disconnected room=${roomInfo.roomName} '
'reason=${event.reason} remoteParticipants=${room?.remoteParticipants.length}',
);
// disconnect
_setConnectStatus(
roomInfo.roomName, ConnectStatus.disconnected, "disconnected");
TgoRTC.instance.participantManager.getLocalParticipant()?.notifyLeave();
})
..on<RoomAttemptReconnectEvent>((event) {
Logger.info('[RoomEvent] attemptReconnect room=${roomInfo.roomName}');
// reconnect
_setConnectStatus(
roomInfo.roomName, ConnectStatus.reconnecting, "reconnecting");
})
..on<RoomConnectedEvent>((event) {
Logger.info(
'[RoomEvent] connected room=${roomInfo.roomName} '
'local=${room?.localParticipant?.identity} '
'remoteParticipants=${room?.remoteParticipants.length} '
'elapsedMs=${connectStopwatch.elapsedMilliseconds}',
);
// connected
_setConnectStatus(
roomInfo.roomName, ConnectStatus.connected, "connected");
TgoRTC.instance.participantManager
.getLocalParticipant()
?.setLocalParticipant(room!.localParticipant!);
TgoRTC.instance.participantManager.getLocalParticipant()?.notifyJoined();
for (final participant in room!.remoteParticipants.values) {
TgoRTC.instance.participantManager.setParticipantJoin(participant);
}
})
..on<RoomReconnectingEvent>((event) {
Logger.info('[RoomEvent] reconnecting room=${roomInfo.roomName}');
// reconnecting
_setConnectStatus(
roomInfo.roomName, ConnectStatus.reconnecting, "reconnecting");
})
..on<RoomReconnectedEvent>((event) {
Logger.info(
'[RoomEvent] reconnected room=${roomInfo.roomName} '
'local=${room?.localParticipant?.identity} '
'remoteParticipants=${room?.remoteParticipants.length}',
);
_setConnectStatus(
roomInfo.roomName, ConnectStatus.reconnected, "reconnected");
TgoRTC.instance.participantManager
.getLocalParticipant()
?.setLocalParticipant(room!.localParticipant!);
TgoRTC.instance.participantManager.getLocalParticipant()?.notifyJoined();
})
..on<ParticipantConnectedEvent>((event) {
Logger.info(
'[RoomEvent] participantConnected uid=${event.participant.identity} '
'sid=${event.participant.sid} '
'connectionQuality=${event.participant.connectionQuality} '
'remoteCount=${room?.remoteParticipants.length}',
);
// remote join
TgoRTC.instance.participantManager
.setParticipantJoin(event.participant);
})
..on<ParticipantDisconnectedEvent>((event) {
Logger.info(
'[RoomEvent] participantDisconnected uid=${event.participant.identity} '
'sid=${event.participant.sid} '
'remoteCount=${room?.remoteParticipants.length}',
);
// remote leave
TgoRTC.instance.participantManager
.setParticipantLeave(event.participant);
})
..on<LocalTrackPublishedEvent>((event) {
Logger.info(
'[RoomEvent] localTrackPublished kind=${event.publication.kind} '
'source=${event.publication.source} sid=${event.publication.sid} '
'track=${event.publication.track?.sid}',
);
// 调试日志:打印本地发布的视频轨道信息
final publication = event.publication;
if (publication.kind == TrackType.VIDEO) {
final track = publication.track;
if (track is LocalVideoTrack) {
final options = track.currentOptions;
final dimensions = options.params.dimensions;
Logger.info(
'[Video] Local track published: ${publication.sid}, '
'resolution: ${dimensions.width}x${dimensions.height}');
// 订阅视频统计信息事件
_subscribeToVideoStats(track);
}
}
})
..on<LocalTrackUnpublishedEvent>((event) {
Logger.info(
'[RoomEvent] localTrackUnpublished kind=${event.publication.kind} '
'source=${event.publication.source} sid=${event.publication.sid}',
);
// 本地轨道取消发布时清理
if (event.publication.kind == TrackType.VIDEO) {
_unsubscribeFromVideoStats();
}
});
Logger.info(
'[Room] connect begin room=${roomInfo.roomName} '
'url=${roomInfo.url} tokenLength=${roomInfo.token.length}',
);
try {
await room!.connect(
roomInfo.url,
roomInfo.token,
);
Logger.info(
'[Room] connect success room=${roomInfo.roomName} '
'local=${room?.localParticipant?.identity} '
'remoteParticipants=${room?.remoteParticipants.length} '
'elapsedMs=${connectStopwatch.elapsedMilliseconds}',
);
} catch (e, s) {
Logger.error(
'[Room] connect failed room=${roomInfo.roomName} '
'url=${roomInfo.url} elapsedMs=${connectStopwatch.elapsedMilliseconds} '
'errorType=${e.runtimeType} error=$e',
);
Logger.error('[Room] connect failed stack=$s');
rethrow;
} finally {
connectStopwatch.stop();
}
if (cameraEnabled) {
Logger.info('[Room] enable camera begin room=${roomInfo.roomName}');
await room!.localParticipant?.setCameraEnabled(true);
Logger.info('[Room] enable camera done room=${roomInfo.roomName}');
}
if (cameraEnabled || enableScreenShare) {
Logger.info(
'[Room] wait after video publish room=${roomInfo.roomName} '
'camera=$cameraEnabled screen=$enableScreenShare',
);
await Future.delayed(const Duration(milliseconds: 300));
}
if (micEnabled) {
Logger.info('[Room] enable microphone begin room=${roomInfo.roomName}');
await room!.localParticipant?.setMicrophoneEnabled(true);
Logger.info('[Room] enable microphone done room=${roomInfo.roomName}');
}
if (enableScreenShare) {
Logger.info('[Room] enable screen share begin room=${roomInfo.roomName}');
await Future.delayed(const Duration(milliseconds: 300));
await room!.localParticipant?.setScreenShareEnabled(true);
Logger.info('[Room] enable screen share done room=${roomInfo.roomName}');
}
// 开启定时器检查参与者超时
Logger.info(
'[Room] start timeout checker room=${roomInfo.roomName} '
'timeout=${roomInfo.timeout}',
);
_startTimeoutChecker(roomInfo.timeout);
}