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

Flutter WebRTC关闭视频通话后摄像头仍后台运行问题求助

解决flutter_webrtc关闭视频通话后摄像头持续运行的问题

核心修复步骤

  • 完善资源释放逻辑
    确保CallVideoEntity的dispose方法中,先显式停止所有媒体轨道,再释放流、PeerConnection和渲染器——这是WebRTC释放摄像头的关键:

    class CallVideoEntity {
      RTCPeerConnection? _peerConnection;
      MediaStream? _localStream;
      RTCVideoRenderer? _localRenderer;
    
      Future<void> dispose() async {
        // 停止并释放本地流的所有轨道
        if (_localStream != null) {
          await Future.wait(
            _localStream!.getTracks().map((track) => track.stop())
          );
          await _localStream!.dispose();
          _localStream = null;
        }
        // 关闭PeerConnection
        if (_peerConnection != null) {
          await _peerConnection!.close();
          _peerConnection = null;
        }
        // 释放视频渲染器
        if (_localRenderer != null) {
          await _localRenderer!.dispose();
          _localRenderer = null;
        }
      }
    }
    

    很多时候只释放流而不停止轨道,会导致摄像头被持续占用。

  • 调整资源清理的时机
    将CallVideoEntity.dispose()的调用从VideoCallPage的deactivate移到dispose生命周期中——dispose是页面销毁的最后回调,能确保资源在页面彻底销毁时被清理:

    class VideoCallPage extends StatefulWidget {
      @override
      _VideoCallPageState createState() => _VideoCallPageState();
    }
    
    class _VideoCallPageState extends State<VideoCallPage> {
      CallVideoEntity? _callEntity;
    
      @override
      void dispose() {
        // 页面销毁时必执行资源清理
        _callEntity?.dispose();
        super.dispose();
      }
    }
    

    deactivate仅在页面失去焦点时触发,无法保证页面被销毁时一定执行。

  • 排查全局引用问题
    确认CallVideoEntity没有被全局单例或其他组件持有引用,否则即使页面销毁,实例依然存活,摄像头资源无法释放。确保每个通话页面持有独立的实例,且页面销毁时实例被彻底回收。

验证修复效果

修复后关闭通话页面,检查日志是否不再出现I/org.webrtc.Logging(18069): CameraStatistics: Camera fps: 30.,若日志消失则说明摄像头已成功释放。

内容的提问来源于stack exchange,提问作者ABDULKARIM ALBAIK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 15:34:52