Skip to main content
Version: 5.x.x

Manage Audio and Video Devices - Flutter

This feature allows hosts to switch their microphone, speaker, or camera devices during a live stream. Hosts (in SEND_AND_RECV mode) can change the microphone and camera they broadcast with, ensuring they maintain control over their audio and video quality, while audience members (in RECV_ONLY mode) continue to receive the broadcast. Audience members can still switch the speaker they listen on.

Changing Audio Input Device​

During the livestream at any point a host wishes to switch his/her input audio device, it can be done using the below mentioned methods.

important

On Android and iOS, the microphone and the speaker share a single audio route. Changing the microphone with changeMic() also changes where you hear audio, and setAudioDevice() changes both too.

getMics()​

  • The getMics() method of the VideoSDK class lists the audio devices you can switch to, as a list of MicrophoneDeviceInfo objects. Each one is an audio route.

  • The MicrophoneDeviceInfo object will contain the deviceId and label for the device.

  • On Android, the devices are SPEAKER_PHONE, EARPIECE, WIRED_HEADSET and BLUETOOTH, as each one is connected. On iOS, the list starts with Speaker, which is not a microphone, followed by the microphones you can use, such as iPhone Microphone, Headphones for a wired headset, or the name of a Bluetooth headset.

changeMic()​

  • After selecting the desired device, you can switch the audio input by passing its deviceId to changeMic(deviceId:).

  • Calling changeMic() without a device switches to the next microphone.

  • A muted microphone stays muted. If the microphone is on, it is turned off and on again on the new device, so you get Events.streamDisabled and then Events.streamEnabled for your audio stream.

  • You can call changeMic() with a device before you join. The room uses that device when you join.

  • changeMic() returns a Future that throws a VideoSDKError if the switch fails, for example 3059 when the device is not available. The same error also reaches your Events.error handler.

Example​

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class LiveStreamScreen extends StatefulWidget {
const LiveStreamScreen({Key? key}) : super(key: key);

@override
_LiveStreamScreenState createState() => _LiveStreamScreenState();
}

class _LiveStreamScreenState extends State<LiveStreamScreen> {
late Room _room;
List<MicrophoneDeviceInfo> mics = [];

@override
void initState() {
super.initState();
fetchMics();
}

void fetchMics() async {
List<MicrophoneDeviceInfo>? audioDevices = await VideoSDK.getMics();
setState(() {
// On iOS, "Speaker" is not a microphone.
mics = (audioDevices ?? [])
.where((device) => device.label != 'Speaker')
.toList();
});
}

Future<void> changeMic(MicrophoneDeviceInfo device) async {
try {
await _room.changeMic(deviceId: device.deviceId);
} on VideoSDKError catch (error) {
print("changeMic failed: ${error.code} ${error.name}");
}
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
child: Text("Change Input Device"),
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("Select Audio Device"),
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SingleChildScrollView(
reverse: true,
child: mics.isNotEmpty
? Column(
children: mics
.map(
(device) => ElevatedButton(
child: Text(device.label),
onPressed: () async {
Navigator.pop(context);
await changeMic(device);
},
),
)
.toList(),
)
: const Text("No Microphone Devices found."),
)
],
),
),
);
}),
]);
}
}

Changing Audio Output Device​

During the livestream at any point a host wishes to switch his/her output audio like from headphones to speaker, it can be done using the below mentioned methods.

important

On Android and iOS, the microphone and the speaker share a single audio route, so setAudioDevice() changes both. To choose the microphone, see Changing Audio Input Device.

getMics()​

  • The getMics() method will help you to list down all the audio devices you can switch to, which will return a list of MicrophoneDeviceInfo objects. Each one is an audio route.

  • The MicrophoneDeviceInfo object will contain the deviceId and label for the device.

setAudioDevice()​

  • After selecting the desired device, you can switch the audio output by passing the corresponding MicrophoneDeviceInfo object as a parameter to the setAudioDevice() method.

  • The microphone stays muted or unmuted as it was.

  • setAudioDevice() returns a Future that throws a VideoSDKError if the switch fails.

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class LiveStreamScreen extends StatefulWidget {
const LiveStreamScreen({Key? key}) : super(key: key);

@override
_LiveStreamScreenState createState() => _LiveStreamScreenState();
}

class _LiveStreamScreenState extends State<LiveStreamScreen> {
late Room _room;
List<MicrophoneDeviceInfo> speakers = [];

@override
void initState() {
super.initState();
fetchSpeakers();
}

void fetchSpeakers() async {
List<MicrophoneDeviceInfo>? audioDevices = await VideoSDK.getMics();
setState(() => speakers = audioDevices ?? []);
}

Future<void> setAudioDevice(MicrophoneDeviceInfo device) async {
try {
await _room.setAudioDevice(device);
} on VideoSDKError catch (error) {
print("setAudioDevice failed: ${error.code} ${error.name}");
}
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
child: const Text("Change Audio Device"),
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("Select Audio Device"),
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SingleChildScrollView(
reverse: true,
child: speakers.isNotEmpty
? Column(
children: speakers
.map(
(device) => ElevatedButton(
child: Text(device.label),
onPressed: () async {
Navigator.pop(context);
await setAudioDevice(device);
},
),
)
.toList(),
)
: const Text("No Speaker Devices found."),
)
],
),
),
);
}),
]);
}
}

Changing Camera Input Device​

During the livestream at any point a host wishes to switch his/her input video device, it can be done using the below mentioned methods.

getCameras()​

  • This method of the VideoSDK class will give you the list of all the available cameras which can be shown in a list.

  • This method will return a list of CameraDeviceInfo which will contain the deviceId, label and kind of the camera input devices.

changeCam()​

  • After selecting the desired device, you can switch the camera input by passing its deviceId to changeCam(deviceId:).

  • Call changeCam() without a device to switch to the next camera, for example from the front camera to the back camera.

  • changeCam() returns a Future that throws a VideoSDKError if the switch fails, for example 3051 when the camera is not available. The same error also reaches your Events.error handler.

Future<void> switchToNextCamera() async {
try {
// No device: switch to the next camera
await _room.changeCam();
} on VideoSDKError catch (error) {
print("changeCam failed: ${error.code} ${error.name}");
}
}

Example​

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class LiveStreamScreen extends StatefulWidget {
const LiveStreamScreen({Key? key}) : super(key: key);

@override
_LiveStreamScreenState createState() => _LiveStreamScreenState();
}

class _LiveStreamScreenState extends State<LiveStreamScreen> {
late Room _room;
List<CameraDeviceInfo>? cameras = [];

@override
void initState() {
super.initState();
fetchCameras();
}

void fetchCameras() async {
cameras = await VideoSDK.getCameras();
setState(() {});
}

Future<void> changeCam(CameraDeviceInfo device) async {
try {
await _room.changeCam(deviceId: device.deviceId);
} on VideoSDKError catch (error) {
print("changeCam failed: ${error.code} ${error.name}");
}
}

@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
child: const Text("Change Camera"),
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("Select Camera Device"),
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SingleChildScrollView(
reverse: true,
child: cameras != null && cameras!.isNotEmpty
? Column(
children: cameras!.map(
(device) => ElevatedButton(
child: Text(device.label),
onPressed: () async {
Navigator.pop(context);
await changeCam(device);
},
),
).toList(),
)
: const Text("No Camera Devices found."),
),
],
),
),
);
},
),
],
);
}
}

API Reference​

The API references for all the methods and events utilised in this guide are provided below.

Got a Question? Ask us on discord