You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中使用Vonage Opentok实现订阅者关摄像头时显示占位图

解决Flutter中Vonage Opentok订阅者关闭摄像头时显示占位图的问题

核心原因

Opentok的SubscriberWidget在订阅者关闭摄像头后,视频渲染层不会自动消失,只是无画面输出(呈现黑屏),直接给组件设置背景会被上层的视频渲染层遮挡,所以看不到占位图。需要通过监听视频状态,动态控制组件显示逻辑。

具体实现方案

1. 监听订阅者的视频状态

通过Subscriber对象的onVideoDisabled和onVideoEnabled事件,或者实时判断subscriber.stream?.hasVideo的值,来感知视频流的开启/关闭状态。

2. 动态切换显示内容

可以用两种方式实现:

  • 条件渲染:视频可用时显示SubscriberWidget,不可用时显示占位图容器
  • Stack叠加:将占位图放在底层,视频组件放在上层,通过透明度控制显示,避免组件切换时的闪烁

代码示例

方式一:条件渲染

bool _hasVideo = true;

@override
void initState() {
  super.initState();
  // 监听摄像头关闭事件
  subscriber.onVideoDisabled = () {
    setState(() {
      _hasVideo = false;
    });
  };
  // 监听摄像头开启事件
  subscriber.onVideoEnabled = () {
    setState(() {
      _hasVideo = true;
    });
  };
}

@override
Widget build(BuildContext context) {
  return _hasVideo
      ? SubscriberWidget(
          subscriber: subscriber,
          onSubscribe: (subscriber) {},
          onUnsubscribe: (subscriber) {},
        )
      : Container(
          decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage('assets/camera_off_placeholder.png'), // 替换为你的占位图路径
              fit: BoxFit.cover,
            ),
          ),
          child: Center(
            child: Text('对方已关闭摄像头', style: TextStyle(color: Colors.white, fontSize: 16)),
          ),
        );
}

方式二:Stack叠加(无切换闪烁)

bool _hasVideo = true;

@override
void initState() {
  super.initState();
  subscriber.onVideoDisabled = () => setState(() => _hasVideo = false);
  subscriber.onVideoEnabled = () => setState(() => _hasVideo = true);
}

@override
Widget build(BuildContext context) {
  return Stack(
    fit: StackFit.expand,
    children: [
      // 底层占位图
      Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage('assets/camera_off_placeholder.png'),
            fit: BoxFit.cover,
          ),
        ),
      ),
      // 上层视频组件,视频不可用时设为透明
      Opacity(
        opacity: _hasVideo ? 1.0 : 0.0,
        child: SubscriberWidget(
          subscriber: subscriber,
          onSubscribe: (subscriber) {},
          onUnsubscribe: (subscriber) {},
        ),
      ),
      // 可选:视频关闭时显示提示文字
      if (!_hasVideo)
        Center(
          child: Text('对方已关闭摄像头', style: TextStyle(color: Colors.white, fontSize: 16)),
        ),
    ],
  );
}

注意事项

  • 确保subscriber对象已正确初始化并加入会话
  • 占位图路径需要在pubspec.yaml的assets节点中正确配置
  • 如果使用subscriber.stream?.hasVideo做初始判断,建议在会话连接成功后再获取状态,避免初始值错误

内容的提问来源于stack exchange,提问作者Hafiz Hamza Jamil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 07:27:02