Agora IO调用.close()后摄像头灯未关闭问题求助(Next.js医疗应用)
解决Agora IO视频通话后摄像头灯未关闭的问题
核心问题分析
调用close()后摄像头灯仍保持亮起,本质是轨道实例的引用未被彻底清理,尤其是在Next.js/React的组件生命周期中,若轨道对象被留存于状态或未妥善销毁,会导致浏览器无法释放硬件资源,即便user-unpublished事件触发,硬件占用仍未解除。
正确的资源释放流程
无论通过哪种方式创建轨道,都需要严格遵循以下步骤:
- 若轨道已发布到频道,必须先调用
unpublish()取消发布,再执行close() - 调用
close()后,立即清空所有对该轨道实例的引用 - 在组件卸载(如通话结束、页面切换)时,强制触发资源清理逻辑
Next.js组件完整示例代码
以下是基于agora-rtc-react的落地实现,确保摄像头资源被彻底释放:
'use client'; import { useEffect, useRef, useState } from 'react'; import { createMicrophoneAndCameraTracks, useClient } from 'agora-rtc-react'; export default function MedicalVideoCall() { const client = useClient(); const [inCall, setInCall] = useState(false); // 用useRef存储轨道实例,避免状态更新引发的实例残留 const trackRef = useRef({ audio: null, video: null }); // 启动通话逻辑 const startCall = async () => { try { const [audioTrack, videoTrack] = await createMicrophoneAndCameraTracks(); trackRef.current = { audio: audioTrack, video: videoTrack }; // 发布轨道至频道 await client.publish([audioTrack, videoTrack]); setInCall(true); } catch (err) { console.error('通话启动失败:', err); } }; // 结束通话并清理资源 const endCall = async () => { const { audio, video } = trackRef.current; try { // 先取消发布轨道 if (audio) await client.unpublish(audio); if (video) await client.unpublish(video); // 关闭轨道并清空引用 if (audio) { await audio.close(); trackRef.current.audio = null; } if (video) { await video.close(); trackRef.current.video = null; } setInCall(false); } catch (err) { console.error('通话结束失败:', err); } }; // 组件卸载时强制清理资源 useEffect(() => { return () => { if (inCall) endCall(); }; }, [inCall]); return ( <div className="call-container"> <button onClick={inCall ? endCall : startCall}> {inCall ? '结束通话' : '发起视频会诊'} </button> {/* 渲染本地视频流 */} {inCall && trackRef.current.video && ( <video autoPlay playsInline ref={(el) => el && trackRef.current.video.play(el)} className="local-video" /> )} </div> ); }
额外注意事项
- 不要用
useState存储轨道实例:状态更新会触发组件重渲染,极易导致旧轨道实例未被清理,引发资源泄漏 - 针对原生
agora-rtc-sdk-ng调用,流程完全一致:先执行client.unpublish(track),再调用track.close(),最后清空引用 - 可通过
navigator.mediaDevices.enumerateDevices()在关闭后检查设备状态,确认资源是否释放
内容的提问来源于stack exchange,提问作者Lenin Boccardo
相关产品推荐
相关产品推荐

