HoloLens 2中FaceTracker类调用ProcessNextFrameAsync报错求助
排查HoloLens 2 FaceTracker ProcessNextFrameAsync抛出COM异常的思路
我在HoloLens 2开发中也碰到过类似的0x80004005 COM异常,结合你提供的代码和测试信息,核心问题大概率出在VideoFrame的获取方式和MediaCapture的初始化细节上,咱们一步步拆解:
1. 最关键的问题:你传入的是空白VideoFrame,而非实际捕获的帧
你的代码里直接新建了一个空的VideoFrame传给ProcessNextFrameAsync,但FaceTracker需要的是MediaCapture实时捕获到的有效视频帧,空帧会触发底层COM组件报错。正确的做法是通过MediaCapture.GetPreviewFrameAsync()获取实际预览帧:
private async void ProcessCurrentVideoFrameAsync(ThreadPoolTimer timer) { const BitmapPixelFormat InputPixelFormat = BitmapPixelFormat.Nv12; try { // 获取实际的预览帧,而非新建空帧 using (VideoFrame videoFrame = await mediaCapture.GetPreviewFrameAsync( new VideoFrame(InputPixelFormat, (int)videoProperties.Width, (int)videoProperties.Height))) { IList<DetectedFace> detectedFaces = await faceTracker.ProcessNextFrameAsync(videoFrame); // 处理检测结果逻辑 } } catch (Exception e) { System.Diagnostics.Debug.WriteLine($"Failed with Exception: {e.ToString()}"); return; } }
这里用using语句自动释放VideoFrame资源,避免内存泄漏问题。
2. 解决"No capture devices are available."的权限与初始化问题
虽然你在Unity中配置了权限,但HoloLens 2的相机权限还有几个细节要确认:
- 检查打包后的
Package.appxmanifest文件,确保已添加webcam功能声明(Unity自动打包时偶尔会丢失该声明,需要手动补全)。 - 在代码中主动请求相机权限,不要仅依赖Unity的设置:
建议在private async Task RequestPermissions() { var webcamAccessStatus = await MediaCapture.RequestAccessAsync(MediaCaptureVideoDeviceAccessKind.VideoPreview); if (webcamAccessStatus != MediaCaptureAccessStatus.Allowed) { Debug.LogError("Webcam access denied!"); return; } }Start()方法中优先调用这个权限请求方法,再初始化MediaCapture。 - 初始化MediaCapture时明确指定配置,绑定你找到的Color相机:
var settings = new MediaCaptureInitializationSettings { SourceGroup = sourceGroup, StreamingCaptureMode = StreamingCaptureMode.Video, PhotoCaptureSource = PhotoCaptureSource.VideoPreview }; await mediaCapture.InitializeAsync(settings);
3. 确保FaceTracker与MediaCapture的格式、尺寸完全匹配
- 确认FaceTracker支持Nv12格式(HoloLens 2的FaceTracker确实支持,但要保证VideoFrame的尺寸和MediaCapture实际预览尺寸一致)。你可以在MediaCapture初始化后打印实际预览属性,验证是否和预期一致:
如果实际尺寸和你创建VideoFrame时用的参数不一致,会触发格式不兼容的异常。var actualProps = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties; Debug.Log($"Actual preview size: {actualProps.Width}x{actualProps.Height}, format: {actualProps.Subtype}");
4. 线程上下文问题:ThreadPoolTimer回调的异步处理
ThreadPoolTimer的回调在后台线程执行,而MediaCapture和FaceTracker的部分操作可能需要在UI线程(Dispatcher线程)中运行。你可以尝试把帧处理逻辑调度到UI线程:
private void ProcessCurrentVideoFrameAsync(ThreadPoolTimer timer) { CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { // 这里放入帧获取和人脸检测的逻辑 }); }
结合你的更新:验证MediaCapture帧的有效性
你提到FaceDetector处理本地图片正常,可以先测试用MediaCapture捕获帧后再用FaceDetector处理,确认MediaCapture是否能获取有效帧:
private async Task TestMediaCaptureFrame() { using (VideoFrame frame = await mediaCapture.GetPreviewFrameAsync(new VideoFrame(BitmapPixelFormat.Bgra8, 1920, 1080))) { var faceDetector = await FaceDetector.CreateAsync(); var result = await faceDetector.DetectAsync(frame.SoftwareBitmap); Debug.Log($"Detected {result.Count} faces from MediaCapture frame"); } }
如果这个测试报错,说明MediaCapture的初始化或权限确实有问题;如果正常,那问题就聚焦在FaceTracker的调用细节(比如格式匹配、线程兼容)上。
内容的提问来源于stack exchange,提问作者user13248502
相关产品推荐
相关产品推荐

