expo / expo

An open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.
https://docs.expo.dev
MIT License
34.69k stars 5.57k forks source link

Video recording fails on some older Android devices #32413

Open eebirke opened 3 weeks ago

eebirke commented 3 weeks ago

Minimal reproducible example

https://github.com/eebirke/expo-camera-stabilization-bug

What platform(s) does this occur on?

Android

Where did you reproduce the issue?

in a development build, in a standalone app

Summary

Discovered this after a user complained that video recording was not working on Lenovo M10 tablets (Android 12) after upgrading expo-camera. Not sure if this is a Lenovo M10 issue only or if it impacts other older devices. I could only reproduce this on a Lenovo M10 unit, not in emulator or on e.g. a Huawei P20 on EMUI/Android 10.

Checking the error from the recorder only yields "Unknown error", and adding print statements to the expo-camera native code yields error code 8 when stopping the recording. This seems to correspond to the ERROR_NO_VALID_DATA error from VideoRecordEvent.java in androidx.camera – the only other clues are warnings that the muxer isn't receving frame data.

Removing the line setVideoStabilizationEnabled(true) from ExpoCameraView.kt fixed the issue on our end. The docstring for setVideoStabilizationEnabled mentions the following:

It is recommended to query the device capability via VideoCapabilities. isStabilizationSupported() before enabling this feature, otherwise HAL error might be thrown.

As a fix to not completely disable video stabilization I run this patch locally for expo-camera (this yields stabilization supported false on first setup since camera is not initialized – but should be re-run as the camera object is recreated later if I understand the code correctly):

diff --git a/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt b/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt
index f4c3a00..da7da18 100644
--- a/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt
+++ b/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt
@@ -466,11 +466,16 @@ class ExpoCameraView(
         this.recorder = it
       }

+    val isStabilizationSupported = camera?.cameraInfo?.let { cameraInfo ->
+      val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo)
+      videoCapabilities.isStabilizationSupported
+    } ?: false
+
     return VideoCapture.Builder(recorder).apply {
       if (mirror) {
         setMirrorMode(MirrorMode.MIRROR_MODE_ON_FRONT_ONLY)
       }
-      setVideoStabilizationEnabled(true)
+      setVideoStabilizationEnabled(isStabilizationSupported)
     }.build()
   }

Edit: To be more concise, preview works and starting recording seems to work at first glance, but stopping recording causes an error to be thrown in the recordAsync Promise and no recording has been made/stored.

Environment

expo-env-info 1.2.0 environment info:
    System:
      OS: macOS 15.0.1
      Shell: 5.9 - /bin/zsh
    Binaries:
      Node: 20.16.0 - ~/.nvm/versions/node/v20.16.0/bin/node
      Yarn: 3.6.4 - ~/.nvm/versions/node/v20.16.0/bin/yarn
      npm: 10.8.2 - ~/.nvm/versions/node/v20.16.0/bin/npm
      Watchman: 2024.08.05.00 - /opt/homebrew/bin/watchman
    Managers:
      CocoaPods: 1.15.2 - /opt/homebrew/bin/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 24.0, iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0
    IDEs:
      Android Studio: 2024.2 AI-242.23339.11.2421.12483815
      Xcode: 16.0/16A242d - /usr/bin/xcodebuild
    npmPackages:
      expo: ^51.0.38 => 51.0.38
      react: 18.2.0 => 18.2.0
      react-native: 0.74.5 => 0.74.5
    Expo Workflow: bare

Expo Doctor Diagnostics

✔ Check Expo config for common issues
✔ Check package.json for common issues
✔ Check dependencies for packages that should not be installed directly
✔ Check for common project setup issues
✔ Check for issues with Metro config
✔ Check if the project meets version requirements for submission to app stores
✔ Check npm/ yarn versions
✖ Check for app config fields that may not be synced in a non-CNG project
✔ Check for legacy global CLI installed locally
✔ Check that packages match versions required by installed Expo SDK
✔ Check that native modules do not use incompatible support packages
✔ Check native tooling versions
✔ Check Expo config (app.json/ app.config.js) schema
✔ Check that native modules use compatible support package versions for installed Expo SDK
anthonybtedesco commented 3 weeks ago

I also am experiencing issues with Samsung Android devices. All other devices seem to work but samsung has a black screen when using the camera in web. The camera is loaded and shows as being used but its just black.

expo-bot commented 3 weeks ago

Thank you for filing this issue! This comment acknowledges we believe this may be a bug and there’s enough information to investigate it. However, we can’t promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If you’d like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.