Description
There is no deterministic way to set the local video mute state from Dart, and the only setter that maps to the native setMute(bool) is both deprecated and inverted.
HMSSDK.switchVideo({bool isOn}) passes its isOn value straight through to the native HMSLocalVideoTrack.setMute(...) without negation, on both platforms. So isOn: true mutes the camera (turns it OFF) β the opposite of
what the parameter name implies.
Dart β lib/src/hmssdk.dart:
@Deprecated('Use [toggleCameraMuteState]')
Future<HMSException?> switchVideo({bool isOn = false}) async {
bool result = await PlatformService.invokeMethod(
PlatformMethod.switchVideo, arguments: {'is_on': isOn});
...
}
iOS β ios/Classes/Actions/HMSVideoAction.swift:
guard let shouldMute = arguments["is_on"] as? Bool, // value of is_on
let peer = hmsSDK?.localPeer,
let video = peer.videoTrack as? HMSLocalVideoTrack else { ... }
video.setMute(shouldMute) // is_on -> setMute(), no negation
Android β android/.../methods/HMSVideoAction.kt:
val argsIsOn = call.argument<Boolean>("is_on")
val videoTrack = peer?.videoTrack
videoTrack.setMute(argsIsOn ?: false) // same: is_on -> setMute()
Resulting behaviour:
| Call |
Native effect |
Camera |
switchVideo(isOn: true) |
setMute(true) |
OFF |
switchVideo(isOn: false) |
setMute(false) |
ON |
Why toggleCameraMuteState() is not a sufficient replacement: it is a blind toggle (setMute(!isMute())). When the underlying mute state is changing on its own β e.g. the burst of trackMuted/trackUnMuted updates emitted
during the previewβjoin handoff, or when another AVCaptureSession acquires/releases the camera β a single toggle races those changes and lands on a non-deterministic final state. Only an absolute setMute(bool) can converge the
camera to a known state.
Request: expose a deterministic, non-deprecated local-video mute setter, e.g. Future<HMSException?> setLocalVideoMute(bool mute) (or HMSLocalVideoTrack.setMute(bool)). The native setMute(bool) already exists; it's simply
not reachable from Dart except through the broken/deprecated switchVideo. Either fix switchVideo's inversion and un-deprecate it, or add a clearly-named replacement.
100ms Flutter Version
1.11.1
Steps to reproduce
- Build and join a room:
HMSSDK()..build(), addUpdateListener, join(config).
- After
onJoin, call hmsSDK.switchVideo(isOn: true), intending β per the parameter name β to turn the local camera ON.
- Observe
onTrackUpdate for the local video track and/or the HMSVideoView.
Expected results
switchVideo(isOn: true) turns the local camera ON (unmuted), as the isOn parameter name implies.
More generally: a non-deprecated, deterministic API to set the local video mute state to an absolute value, so the camera can be forced to a known state regardless of in-flight mute events.
Code example, screenshot, or link to a repository
Code sample
// After onJoin has fired:
await hmsSDK.switchVideo(isOn: true);
// Parameter name implies "camera ON".
// Actual: onTrackUpdate reports trackMuted / isMute == true β camera OFF.
await hmsSDK.switchVideo(isOn: false);
// Parameter name implies "camera OFF".
// Actual: isMute == false β camera ON.
// Root cause, verifiable in the SDK's own source:
// Dart switchVideo({bool isOn}) -> invokeMethod(switchVideo, {'is_on': isOn})
// iOS HMSVideoAction.switchVideo: video.setMute(arguments["is_on"])
// Kotlin HMSVideoAction.switchVideo: videoTrack.setMute(argsIsOn ?: false)
// 'is_on' is forwarded directly to setMute() with no negation on either platform.
Logs
Logs
// App-level logs after calling switchVideo(isOn: true) post-join
// (our wrapper logs the intent; the SDK then reports the inverted result):
setLocalVideoEnabled(enabled=true) joined=true // we want camera ON
trackUpdate=HMSTrackUpdate.trackMuted, kind=video, isMute=true // SDK muted it (OFF)
Flutter Doctor output
Doctor output
[β] Flutter (Channel stable, 3.41.8, on macOS 26.2 25C56 darwin-arm64, locale fr-FR)
β’ Flutter version 3.41.8 on channel stable
β’ Framework revision 02085feb3f, 2026-04-24
β’ Engine revision 59aa584fdf
β’ Dart version 3.11.5
[β] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
[β] Xcode - develop for iOS and macOS (Xcode 26.1, Build 17B55)
β’ CocoaPods version 1.16.2
[β] Connected device (2 available)
β’ iPhone (mobile) β’ ios β’ iOS 26.5 23F77
β’ macOS (desktop) β’ darwin-arm64 β’ macOS 26.2
[β] Network resources
Description
There is no deterministic way to set the local video mute state from Dart, and the only setter that maps to the native
setMute(bool)is both deprecated and inverted.HMSSDK.switchVideo({bool isOn})passes itsisOnvalue straight through to the nativeHMSLocalVideoTrack.setMute(...)without negation, on both platforms. SoisOn: truemutes the camera (turns it OFF) β the opposite ofwhat the parameter name implies.
Dart β
lib/src/hmssdk.dart:iOS β
ios/Classes/Actions/HMSVideoAction.swift:Android β
android/.../methods/HMSVideoAction.kt:Resulting behaviour:
switchVideo(isOn: true)setMute(true)switchVideo(isOn: false)setMute(false)Why
toggleCameraMuteState()is not a sufficient replacement: it is a blind toggle (setMute(!isMute())). When the underlying mute state is changing on its own β e.g. the burst oftrackMuted/trackUnMutedupdates emittedduring the previewβjoin handoff, or when another
AVCaptureSessionacquires/releases the camera β a single toggle races those changes and lands on a non-deterministic final state. Only an absolutesetMute(bool)can converge thecamera to a known state.
Request: expose a deterministic, non-deprecated local-video mute setter, e.g.
Future<HMSException?> setLocalVideoMute(bool mute)(orHMSLocalVideoTrack.setMute(bool)). The nativesetMute(bool)already exists; it's simplynot reachable from Dart except through the broken/deprecated
switchVideo. Either fixswitchVideo's inversion and un-deprecate it, or add a clearly-named replacement.100ms Flutter Version
1.11.1
Steps to reproduce
HMSSDK()..build(),addUpdateListener,join(config).onJoin, callhmsSDK.switchVideo(isOn: true), intending β per the parameter name β to turn the local camera ON.onTrackUpdatefor the local video track and/or theHMSVideoView.Expected results
switchVideo(isOn: true)turns the local camera ON (unmuted), as theisOnparameter name implies.More generally: a non-deprecated, deterministic API to set the local video mute state to an absolute value, so the camera can be forced to a known state regardless of in-flight mute events.
Code example, screenshot, or link to a repository
Code sample
Logs
Logs
Flutter Doctor output
Doctor output