Skip to content

[camera_android_x] implement CameraX RecordingStats and VideoRecordEvent APIs - #13330

Merged
auto-submit[bot] merged 7 commits into
flutter:mainfrom
Mairramer:fix-camerax-video-recording-duration
Oct 29, 2026
Merged

auto-submit[bot] merged 7 commits into
flutter:mainfrom
Mairramer:fix-camerax-video-recording-duration

Conversation

@Mairramer

@Mairramer Mairramer commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Fixes flutter/flutter#148138

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2

@Mairramer Mairramer added the CICD Run CI/CD label Oct 19, 2026
@Mairramer

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Android CameraX implementation to resolve video recording discrepancies. It introduces Pigeon bindings for RecordingStats and VideoRecordEventStatus, and adds error-checking methods to VideoRecordEventFinalize. In AndroidCameraCameraX, startVideoCapturing now waits for the first frame to be recorded by monitoring status events, throwing a CameraException if finalization occurs prematurely. Additionally, stopVideoRecording now checks for finalization errors and throws a CameraException if any are found. Unit and integration tests have been updated to cover these new behaviors. There are no review comments to evaluate, and I have no feedback to provide.

@Mairramer Mairramer changed the title [WIP] implement CameraX RecordingStats and VideoRecordEvent APIs [camera_android_x] implement CameraX RecordingStats and VideoRecordEvent APIs Oct 19, 2026
@Mairramer
Mairramer marked this pull request as ready for review October 19, 2026 19:27

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses video recording duration discrepancies and short recording failures in the CameraX Android implementation. It introduces RecordingStats and VideoRecordEventStatus to wait for the first recorded frame before completing startVideoCapturing, and validates errors during finalization. Feedback suggests recreating the StreamQueue at the start of each recording session to prevent leftover finalize events from previous sessions from causing immediate failures, and defining error and hasError in VideoRecordEventFinalize as fields rather than asynchronous methods to avoid platform channel overhead.

Comment on lines +208 to +218
abstract class VideoRecordEventFinalize extends VideoRecordEvent {
/// The error code of the finalization.
///
/// See https://developer.android.com/reference/androidx/camera/video/VideoRecordEvent.Finalize#getError().
int getError();

/// Whether the recording finalized with an error.
///
/// See https://developer.android.com/reference/androidx/camera/video/VideoRecordEvent.Finalize#hasError().
bool hasError();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since VideoRecordEventFinalize is an immutable event, its error and hasError properties are constant once the event is created. Instead of defining them as asynchronous methods (getError() and hasError()), which require asynchronous platform channel calls every time they are accessed, you can define them as fields (similar to how you did for RecordingStats). This avoids unnecessary asynchronous IPC overhead and allows synchronous access to these properties in Dart (e.g., event.hasError and event.error instead of await event.hasError() and await event.getError()).

abstract class VideoRecordEventFinalize extends VideoRecordEvent {
  /// The error code of the finalization.
  ///
  /// See https://developer.android.com/reference/androidx/camera/video/VideoRecordEvent.Finalize#getError().
  late int error;

  /// Whether the recording finalized with an error.
  ///
  /// See https://developer.android.com/reference/androidx/camera/video/VideoRecordEvent.Finalize#hasError().
  late bool hasError;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there is an established pattern for doing this, so I'm pro. Is there some reason we can't do this here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues with that. I'll make the change.

@Mairramer
Mairramer requested a review from camsim99 October 20, 2026 11:51

@camsim99 camsim99 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this LGTM! This will be a great improvement for the plugin and its testing :)

One thing I'll point out is that ideally, we fix the issue of not knowing the video duration so we don't have to guess the delay in tests. flutter/flutter#101785 seems to cover that, which I'd be interested in prioritizing (bumped P3 --> P2). I'm ok with doing that here, though ideally, we plan for the smallest delay we can (left a comment about this re:350)

Comment on lines +208 to +218
abstract class VideoRecordEventFinalize extends VideoRecordEvent {
/// The error code of the finalization.
///
/// See https://developer.android.com/reference/androidx/camera/video/VideoRecordEvent.Finalize#getError().
int getError();

/// Whether the recording finalized with an error.
///
/// See https://developer.android.com/reference/androidx/camera/video/VideoRecordEvent.Finalize#hasError().
bool hasError();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there is an established pattern for doing this, so I'm pro. Is there some reason we can't do this here?

expect(duration, lessThan(postStopTime));
expect(duration, greaterThan(1700));
final int delta = (duration - 2000).abs();
expect(delta, lessThan(350));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 350? Is this the lowest value you found experimentally?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also leave a comment about the value you pick and link to flutter/flutter#101785?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, 350 ms isn't the lowest value observed experimentally. I tested this on my S23 and measured intervals of around 100–200 ms. I chose 350 ms to leave some headroom for timer jitter and dropped frames, and avoid flakiness on CI.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a code comment to clarify this.

@Mairramer

Mairramer commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Overall this LGTM! This will be a great improvement for the plugin and its testing :)

One thing I'll point out is that ideally, we fix the issue of not knowing the video duration so we don't have to guess the delay in tests. flutter/flutter#101785 seems to cover that, which I'd be interested in prioritizing (bumped P3 --> P2). I'm ok with doing that here, though ideally, we plan for the smallest delay we can (left a comment about this re:350)

I can take on flutter/flutter#101785 next. It'll be next in my queue, and I enjoy working on native code, so I'm happy to pick this one up.

@Mairramer
Mairramer requested a review from camsim99 October 26, 2026 23:19

@camsim99 camsim99 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick updates :) and your interest in flutter/flutter#101785!!

@camsim99 camsim99 added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 29, 2026
@auto-submit
auto-submit Bot merged commit faab724 into flutter:main Oct 29, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: camera platform-android

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[camera_android_camerax] Ensure startVideoCapturing and stopVideoRecording return video with expected duration

2 participants