How to join to a video room as subscriber #86
muhammadCodeSh
started this conversation in
General
Replies: 2 comments 1 reply
-
I also follow |
Beta Was this translation helpful? Give feedback.
0 replies
-
Can you give us feedback on this? Thanks guys! |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I tried to join a room as a subscriber but I could not.
Please send me an example code.
This is the code to join as a publisher please convert it to join as a subscriber.
`import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:janus_client/janus_client.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'dart:async';
import 'Helper.dart';
import 'conf.dart';
class TypedVideoRoomV2Unified extends StatefulWidget {
@OverRide
_VideoRoomState createState() => _VideoRoomState();
}
class _VideoRoomState extends State {
late JanusClient j;
Map<int, RemoteStream> remoteStreams = {};
late RestJanusTransport rest;
late WebSocketJanusTransport ws;
late JanusSession session;
late JanusVideoRoomPlugin plugin;
JanusVideoRoomPlugin? remoteHandle;
late int myId;
bool front = true;
int myRoom = 1234;
Map<int, dynamic> feedStreams = {};
Map<int?, dynamic> subscriptions = {};
Map<int, dynamic> feeds = {};
Map<String, int> subStreams = {};
Map<int, MediaStream?> mediaStreams = {};
@OverRide
void didChangeDependencies() async {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
initialize();
}
initialize() async {
ws = WebSocketJanusTransport(url: servermap['janus_ws']);
j = JanusClient(transport: ws, isUnifiedPlan: true, iceServers: [
RTCIceServer(
urls: "stun:stun1.l.google.com:19302", username: "", credential: "")
]);
session = await j.createSession();
plugin = await session.attach();
}
subscribeTo(List<Map<String, dynamic>> sources) async {
if (sources.length == 0) return;
var streams = (sources)
.map((e) => PublisherStream(mid: e['mid'], feed: e['feed']))
.toList();
if (remoteHandle != null) {
await remoteHandle?.subscribeToStreams(streams);
return;
}
remoteHandle = await session.attach();
print(sources);
var start = await remoteHandle?.joinSubscriber(myRoom, streams: streams);
remoteHandle?.typedMessages?.listen((event) async {
Object data = event.event.plugindata?.data;
if (data is VideoRoomAttachedEvent) {
print('Attached event');
data.streams?.forEach((element) {
if (element.mid != null && element.feedId != null) {
subStreams[element.mid!] = element.feedId!;
}
// to avoid duplicate subscriptions
if (subscriptions[element.feedId] == null)
subscriptions[element.feedId] = {};
subscriptions[element.feedId][element.mid] = true;
});
print('substreams');
print(subStreams);
}
if (event.jsep != null) {
await remoteHandle?.handleRemoteJsep(event.jsep);
await start!();
}
}, onError: (error, trace) {
if (error is JanusError) {
print(error.toMap());
}
});
remoteHandle?.remoteTrack?.listen((event) async {
String mid = event.mid!;
if (subStreams[mid] != null) {
int feedId = subStreams[mid]!;
if (!remoteStreams.containsKey(feedId)) {
RemoteStream temp = RemoteStream(feedId.toString());
await temp.init();
setState(() {
remoteStreams.putIfAbsent(feedId, () => temp);
});
}
if (event.track != null && event.flowing == true) {
remoteStreams[feedId]?.video.addTrack(event.track!);
remoteStreams[feedId]?.videoRenderer.srcObject =
remoteStreams[feedId]?.video;
if (kIsWeb) {
remoteStreams[feedId]?.videoRenderer.muted = false;
}
}
}
});
return;
}
Future joinRoom() async {
await plugin.initializeMediaDevices();
RemoteStream mystr = RemoteStream('0');
await mystr.init();
mystr.videoRenderer.srcObject = plugin.webRTCHandle!.localStream;
setState(() {
remoteStreams.putIfAbsent(0, () => mystr);
});
await plugin.joinPublisher(myRoom, displayName: "Shivansh");
plugin.typedMessages?.listen((event) async {
Object data = event.event.plugindata?.data;
if (data is VideoRoomJoinedEvent) {
(await plugin.publishMedia(bitrate: 3000000));
List<Map<String, dynamic>> publisherStreams = [];
for (Publishers publisher in data.publishers ?? []) {
for (Streams stream in publisher.streams ?? []) {
feedStreams[publisher.id!] = {
"id": publisher.id,
"display": publisher.display,
"streams": publisher.streams
};
publisherStreams.add({"feed": publisher.id, ...stream.toJson()});
if (publisher.id != null && stream.mid != null) {
subStreams[stream.mid!] = publisher.id!;
print("substreams is:");
print(subStreams);
}
}
}
subscribeTo(publisherStreams);
}
if (data is VideoRoomNewPublisherEvent) {
List<Map<String, dynamic>> publisherStreams = [];
for (Publishers publisher in data.publishers ?? []) {
feedStreams[publisher.id!] = {
"id": publisher.id,
"display": publisher.display,
"streams": publisher.streams
};
for (Streams stream in publisher.streams ?? []) {
publisherStreams.add({"feed": publisher.id, ...stream.toJson()});
if (publisher.id != null && stream.mid != null) {
subStreams[stream.mid!] = publisher.id!;
print("substreams is:");
print(subStreams);
}
}
}
print('got new publishers');
print(publisherStreams);
subscribeTo(publisherStreams);
}
if (data is VideoRoomLeavingEvent) {
print('publisher is leaving');
print(data.leaving);
unSubscribeStream(data.leaving!);
}
if (data is VideoRoomConfigured) {
print('typed event with jsep' + event.jsep.toString());
await plugin.handleRemoteJsep(event.jsep);
}
}, onError: (error, trace) {
if (error is JanusError) {
print(error.toMap());
}
});
}
Future unSubscribeStream(int id) async {
// Unsubscribe from this publisher
var feed = this.feedStreams[id];
if (feed == null) return;
this.feedStreams.remove(id);
await remoteStreams[id]?.dispose();
remoteStreams.remove(id);
MediaStream? streamRemoved = this.mediaStreams.remove(id);
streamRemoved?.getTracks().forEach((element) async {
await element.stop();
});
var unsubscribe = {
"request": "unsubscribe",
"streams": [
{feed: id}
]
};
if (remoteHandle != null)
await remoteHandle?.send(data: {"message": unsubscribe});
this.subscriptions.remove(id);
}
@OverRide
void dispose() async {
super.dispose();
await remoteHandle?.dispose();
await plugin.dispose();
session.dispose();
}
callEnd() async {
await plugin.hangup();
for (int i = 0; i < feedStreams.keys.length; i++) {
await unSubscribeStream(feedStreams.keys.elementAt(i));
}
remoteStreams.forEach((key, value) async {
value.dispose();
});
setState(() {
remoteStreams = {};
});
subStreams.clear();
subscriptions.clear();
await plugin.webRTCHandle!.localStream?.dispose();
await plugin.dispose();
await remoteHandle?.dispose();
}
@OverRide
Widget build(BuildContext context) {
print('----------------------------- ${remoteStreams.entries.length}');
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
Icons.call,
color: Colors.greenAccent,
),
onPressed: () async {
await this.joinRoom();
}),
IconButton(
icon: Icon(
Icons.call_end,
color: Colors.red,
),
onPressed: () async {
await callEnd();
}),
IconButton(
icon: Icon(
Icons.switch_camera,
color: Colors.white,
),
onPressed: () async {
setState(() {
front = !front;
});
// await plugin.switchCamera(
// deviceId: await getCameraDeviceId(front));
RemoteStream mystr = RemoteStream('0');
await mystr.init();
mystr.videoRenderer.srcObject =
plugin.webRTCHandle!.localStream;
setState(() {
remoteStreams.remove(0);
remoteStreams[0] = mystr;
});
})
],
title: const Text('janus_client'),
),
body: GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemCount:
remoteStreams.entries.map((e) => e.value).toList().length,
itemBuilder: (context, index) {
List items =
remoteStreams.entries.map((e) => e.value).toList();
RemoteStream remoteStream = items[index];
return Stack(
children: [
RTCVideoView(remoteStream.audioRenderer,
filterQuality: FilterQuality.none,
objectFit:
RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
mirror: true),
RTCVideoView(remoteStream.videoRenderer,
filterQuality: FilterQuality.none,
objectFit:
RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
mirror: true)
],
);
}));
}
}`
Beta Was this translation helpful? Give feedback.
All reactions