Video
This section describes how to render video.
Render the video view
The Video SDK for Flutter uses two different widgets to render video.
- For Android it uses
AndroidView. - For iOS it uses
UiKitView.
Define a View class to render the video view for both of these platforms:
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return AndroidView(
viewType: 'the name of view type',
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
case TargetPlatform.iOS:
return UiKitView(
viewType: 'the name of view type',
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
default:
throw UnsupportedError("Unsupported platform");
}
Separate full screen and horizontal scrolling list views
To separate the full screen view and horizontal scrolling list view, define another class, VideoView, to render the View based on whether it is full screen or not:
class VideoView extends HookWidget {
final ZoomVideoSdkUser? user;
final bool sharing;
final bool preview;
final bool focused;
final bool hasMultiCamera;
final String multiCameraIndex;
final String? videoAspect;
final bool fullScreen;
const VideoView({
super.key,
required this.user,
required this.sharing,
required this.preview,
required this.focused,
required this.hasMultiCamera,
required this.multiCameraIndex,
this.videoAspect,
required this.fullScreen,
});
}
In the example app file, lib/call-screen.dart, the function returns VideoView in two separate code blocks:
- one for full screen visualization and
- the other for a horizontally scrolling list of remote users in a video session at the bottom of the screen.
Full screen visualization
The full screen visualization, upon initialization with video enabled, renders what others participating in a video session see:
fullScreenView = AnimatedOpacity(
opacity: opacityLevel,
duration: const Duration(seconds: 3),
child: VideoView(
user: fullScreenUser.value,
hasMultiCamera: false,
sharing: sharingUser.value == null
? false
: (sharingUser.value?.userId == fullScreenUser.value?.userId),
preview: false,
focused: false,
multiCameraIndex: "0",
videoAspect: VideoAspect.Original,
fullScreen: true,
),
);
Creation parameters passed to View
This function passes the following parameters to View:
user: AZoomVideoSdkUsertype instantiated via an event listener for Video SDK session when a user creates, joins, or leaves a session.sharing: A Boolean set totrueif the current full screen user is currently the user who is sharing a screen with others.preview: A Boolean set totrueif the video view is for preview.hasMultiCamera: A Boolean set totrueif the user's device has more than one camera.multiCameraIndex: The index of camera view that theViewshould render.videoAspect: The aspect ratio.fullScreen: A Boolean value that tells theViewcomponent to render itself full screen or horizontalListView.
Horizontally scrolling list
At the bottom of the call-screen, users can see a horizontally scrolling list of other users in the call. Use VideoView in the horizontal ListView that renders this as well:
Container(
height: 110,
margin: const EdgeInsets.only(left: 20, right: 20),
alignment: Alignment.center,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: users.value.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () async {
onSelectedUser(users.value[index]);
},
child: Center(
child: VideoView(
user: users.value[index],
hasMultiCamera: false,
sharing: sharingUser.value == null
? false
: sharingUser.value?.userId == users.value[index].userId,
preview: false,
focused: false,
multiCameraIndex: "0",
videoAspect: VideoAspect.Original,
fullScreen: false,
),
),
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
),
);
The horizontally scrolling ListView at the bottom of the screen renders mini video screens for all users in a session. Tapping a remote user's screen sets that user to the full screen user.
Use virtual background
Use ZoomVideoSdkVirtualBackgroundHelper to enable virtual backgrounds. First determine whether the device supports it using isSupportVirtualBackground. If the device supports it, use the helper functions to add, get, set, and remove virtual backgrounds.
To add virtual backgrounds:
- Use
addVirtualBackgroundItemto add a virtual background item. - Use
getVirtualBackgroundItemListto get a list of available virtual background items. - Choose a virtual background item from the list and use
setVirtualBackgroundItemto set the virtual background.
Use removeVirtualBackgroundItem to remove the virtual background or set the virtual background to None. Use getSelectedVirtualBackgroundItem to get the current selected background.
// Check if virtual background is supported
@override
Future<bool> isSupportVirtualBackground() async {
return await methodChannel
.invokeMethod<bool>('isSupportVirtualBackground')
.then<bool>((bool? value) => value ?? false);
}
// Add virtual background item
@override
Future<ZoomVideoSdkVirtualBackgroundItem?> addVirtualBackgroundItem(String filePath) async {
var params = <String, dynamic>{};
params.putIfAbsent("filePath", () => filePath);
var itemString = await methodChannel
.invokeMethod<String>('addVirtualBackgroundItem', params)
.then<String>((String? value) => value ?? "");
Map<String, dynamic> itemMap = jsonDecode(itemString!);
var vbItem =
ZoomVideoSdkVirtualBackgroundItem.fromJson(itemMap);
return vbItem;
}
// Remove virtual background item
@override
Future<String> removeVirtualBackgroundItem(String imageName) async {
var params = <String, dynamic>{};
params.putIfAbsent("imageName", () => imageName);
return await methodChannel
.invokeMethod<String>('removeVirtualBackgroundItem', params)
.then<String>((String? value) => value ?? "");
}
// Get virtual background item list
@override
Future<List<ZoomVideoSdkVirtualBackgroundItem>> getVirtualBackgroundItemList() async {
var itemListString = await methodChannel
.invokeMethod<String?>('getVirtualBackgroundItemList')
.then<String?>((String? value) => value);
var itemListJson = jsonDecode(itemListString!) as List;
List<ZoomVideoSdkVirtualBackgroundItem> itemList = itemListJson
.map((languageJson) =>
ZoomVideoSdkVirtualBackgroundItem.fromJson(languageJson))
.toList();
return itemList;
}
// Set virtual background item
@override
Future<String> setVirtualBackgroundItem(String imageName) async {
var params = <String, dynamic>{};
params.putIfAbsent("imageName", () => imageName);
return await methodChannel
.invokeMethod<String>('setVirtualBackgroundItem', params)
.then<String>((String? value) => value ?? "");
}
// Get selected virtual background
@override
Future<ZoomVideoSdkVirtualBackgroundItem> getSelectedVirtualBackgroundItem() async {
}