Google MLKit姿态检测未触发onSuccessListener/onFailureListener问题
排查MLKit姿态检测Listener未触发的问题
我正在使用MediaMetadataRetriever和MLKit对本地视频文件做姿态检测,已经通过ImageView验证提取的Bitmap是正确的,但
poseDetector.process()的OnSuccessListener和OnFailureListener都没有执行,看不到对应的日志输出。相关代码如下:
public ArrayList<ArrayList<Float>> extractPoses() throws FileNotFoundException { Log.e("DATA SOURCE: ", videoUri.getPath()); URIPathHelper uph = new URIPathHelper(); String videoInputPath = uph.getPath(applicationContext, videoUri).toString(); File vidInputFile = new File(videoInputPath); File inputFile = new File(vidInputFile.getAbsolutePath()); if (!inputFile.canRead()) { throw new FileNotFoundException("Unable to read " + inputFile); } mdr.setDataSource(inputFile.getAbsolutePath()); ArrayList<ArrayList<Float>> totalVideoPose = new ArrayList<>(); int count = 0; while (true) { try { Bitmap bmp = mdr.getFrameAtIndex(count); InputImage inputImg = InputImage.fromBitmap(bmp, 0); poseDetector.process(inputImg) .addOnSuccessListener(new OnSuccessListener<Pose>() { @Override public void onSuccess(Pose pose) { Log.e("POSE DETECT: ", "success"); if(!(pose.getAllPoseLandmarks().isEmpty())) { ArrayList<Float> framePoseMarks = new ArrayList<Float>(); PoseLandmark left_shoulder = pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER); framePoseMarks.add(left_shoulder.getPosition().x); framePoseMarks.add(left_shoulder.getPosition().y); totalVideoPose.add(framePoseMarks); } } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.e("POSE DETECT: ", "pose detect on failure listener"); } }); Log.e("Pose processing: ", "incrementing count"); count++; } catch (IllegalArgumentException e) { Log.e("POSE DETEC:", "Pose detec ended"); Log.e("POSE DETEC length: ", String.valueOf(totalVideoPose.size())); for (ArrayList<Float> frame: totalVideoPose) { Log.e("POSE DETEC SUBS: ", String.valueOf(frame.size())); } break; } } return totalVideoPose; }
可能的原因及排查方案
1. PoseDetector初始化不规范
MLKit姿态检测器需要正确配置才能正常工作,检查初始化代码:
- 确认使用了匹配场景的检测模式(静态/动态):
PoseDetectorOptions options = new PoseDetectorOptions.Builder() .setDetectorMode(PoseDetectorOptions.STREAM_MODE) // 视频流场景选STREAM_MODE .build(); poseDetector = PoseDetection.getClient(options);
- 避免在主线程阻塞环境下初始化检测器,确保初始化完成后再调用
process。
2. 主线程阻塞导致异步回调无法执行
poseDetector.process()是异步操作,回调会在后台线程执行,但你的代码中无限while循环一直占用主线程,会阻塞Android消息队列,导致回调无法分发。
解决方法:将循环放到后台线程,同时同步每帧的处理流程,比如用CountDownLatch等待回调完成:
// 把extractPoses方法放到后台线程执行(比如用AsyncTask、Coroutine) try { Bitmap bmp = mdr.getFrameAtIndex(count); // 可选:压缩Bitmap减少内存占用 Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, 640, 480, true); bmp.recycle(); // 获取视频真实旋转角度 int rotation = mdr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); InputImage inputImg = InputImage.fromBitmap(scaledBitmap, rotation); final CountDownLatch latch = new CountDownLatch(1); poseDetector.process(inputImg) .addOnSuccessListener(pose -> { Log.e("POSE DETECT: ", "success"); if(!pose.getAllPoseLandmarks().isEmpty()) { ArrayList<Float> framePoseMarks = new ArrayList<>(); PoseLandmark left_shoulder = pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER); framePoseMarks.add(left_shoulder.getPosition().x); framePoseMarks.add(left_shoulder.getPosition().y); totalVideoPose.add(framePoseMarks); } latch.countDown(); }) .addOnFailureListener(e -> { Log.e("POSE DETECT: ", "pose detect failed", e); // 打印具体异常信息 latch.countDown(); }); // 等待当前帧处理完成,设置超时避免无限等待 latch.await(5, TimeUnit.SECONDS); Log.e("Pose processing: ", "incrementing count"); count++; } catch (IllegalArgumentException | InterruptedException e) { // 异常处理 }
3. 内存溢出导致检测器崩溃
循环提取Bitmap会快速占用内存,若发生OutOfMemoryError,检测器可能直接崩溃而不触发回调。
- 查看Logcat搜索
OutOfMemoryError确认问题 - 处理完每帧后调用
bmp.recycle()释放内存 - 对提取的帧进行压缩,缩小尺寸后再传入检测器
4. InputImage旋转参数错误
如果视频本身有旋转(比如竖屏拍摄),传入0作为旋转角度会导致检测失效,但可能不会触发失败回调。解决方法:获取视频的真实旋转角度传入InputImage:
int rotation = mdr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); InputImage inputImg = InputImage.fromBitmap(bmp, rotation);
5. PoseDetector生命周期异常
确保poseDetector是全局变量,在整个视频处理过程中保持存活,避免因局部变量被回收导致回调无法触发。
内容的提问来源于stack exchange,提问作者stackoverflowta8
相关产品推荐
相关产品推荐

