Skip to content

[camera] add custom path ouput to recording#11774

Open
Mairramer wants to merge 31 commits into
flutter:mainfrom
Mairramer:feat/add-custom-path-ouput-to-recording
Open

[camera] add custom path ouput to recording#11774
Mairramer wants to merge 31 commits into
flutter:mainfrom
Mairramer:feat/add-custom-path-ouput-to-recording

Conversation

@Mairramer
Copy link
Copy Markdown
Contributor

@Mairramer Mairramer commented May 25, 2026

This PR introduces the ability to save videos to custom locations, taking into account the limitations and behavior of each platform.

Due to platform-specific security restrictions and limitations:

  • On Android, I was able to save videos directly to /storage/emulated/0/Download/video.mp4 without issues.
  • On iOS, I was able to save videos to On My iPhone -> Camera Example -> Movies.
  • On Windows, the behavior is similar to Android.

Closes flutter/flutter#91680

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
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown

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

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 adds support for a custom videoOutputPath to the startVideoRecording API across Android, iOS, Windows, and Web platforms. The changes include updates to the camera_platform_interface, native implementation logic for path validation, and a new interactive example app. Technical feedback identifies several improvement opportunities: the Android example should use path_provider instead of hardcoded paths, and the UI should be updated to reflect that content:// URIs are not supported. Additionally, the reviewer recommended properly managing TextEditingController lifecycles, using locale-aware string conversions in Java, fixing a potential logic error in the Swift path validation, and integrating the new demo into the existing example app structure rather than replacing the main entry point.

Comment thread packages/camera/camera/example/lib/video_recording_example.dart Outdated
Comment thread packages/camera/camera/example/lib/video_recording_example.dart Outdated
Comment thread packages/camera/camera/example/lib/video_recording_example.dart Outdated
Comment thread packages/camera/camera/example/lib/main.dart Outdated
Mairramer and others added 8 commits May 25, 2026 09:17
…urces/camera_avfoundation/DefaultCamera.swift

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…r/plugins/camera/Camera.java

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…o/flutter/plugins/camerax/RecorderProxyApi.java

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@Mairramer
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown

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

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 adds support for a custom videoOutputPath in the startVideoRecording method across the Android, iOS, and Windows implementations of the camera plugin. The changes include updates to the platform interface, implementation of path validation logic on both Dart and native sides, and the addition of a new example demonstrating the feature. Feedback identifies that the web implementation currently ignores the new parameter and that the example UI documentation incorrectly suggests support for multiple file extensions despite the implementation strictly enforcing .mp4. Additionally, inconsistent SDK and Flutter version constraints were noted in the web package compared to other packages in the pull request.

Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Comment thread packages/camera/camera_web/example/pubspec.yaml Outdated
Comment thread packages/camera/camera_web/lib/src/camera_web.dart
Comment thread packages/camera/camera_web/pubspec.yaml
Mairramer and others added 3 commits May 25, 2026 10:33
@Mairramer
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown

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

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 adds support for a custom video output path (videoOutputPath) to the startVideoRecording method across the Flutter camera plugin and its federated platform implementations (Android, iOS, and Windows). It includes platform-specific validation logic to ensure output paths are not directories, have valid parent directories, and end with the .mp4 extension. Additionally, a comprehensive video recording example app has been added to demonstrate this feature. Feedback on the changes highlights a type mismatch in the example app's validation helper, potential memory leaks from unhandled asynchronous initialization when widgets unmount, and a bug in the Windows path parsing logic when a parent directory contains a dot.

Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Comment thread packages/camera/camera_windows/windows/capture_controller.cpp
Mairramer and others added 5 commits May 25, 2026 14:32
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@Mairramer Mairramer marked this pull request as ready for review May 26, 2026 11:56
@Mairramer Mairramer changed the title WIP [camera] add custom path ouput to recording [camera] add custom path ouput to recording May 26, 2026
Copy link
Copy Markdown

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

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 adds support for a custom videoOutputPath to the startVideoRecording method across the federated camera packages, including Android, iOS, Web, and Windows implementations. It updates the platform interface, implements platform-specific path validation, adds unit and integration tests, and introduces a new video recording example app. The review feedback highlights three key improvements: ensuring the previous CameraController is properly disposed in the example app to prevent resource leaks, correcting path generation logic in the example app for Android and iOS, and deleting any pre-existing file at the destination path on iOS to prevent AVAssetWriter initialization failures.

Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Comment thread packages/camera/camera/example/lib/video_recording_example.dart
Copy link
Copy Markdown
Contributor

@bparrishMines bparrishMines left a comment

Choose a reason for hiding this comment

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

@Mairramer What's the use case you want to solve by adding this feature? From my understanding, it should currently be possible for the app to rename the file to change it's location without copying.

The issue linked mentions being able to save to an external SD card and finding the file if the app crashes during recording, but I dont think this PR would fix these.

@Mairramer
Copy link
Copy Markdown
Contributor Author

@Mairramer What's the use case you want to solve by adding this feature? From my understanding, it should currently be possible for the app to rename the file to change it's location without copying.

The issue linked mentions being able to save to an external SD card and finding the file if the app crashes during recording, but I dont think this PR would fix these.

Thanks for the review!
I get your point about rename, but the main issue here is cross-filesystem moves.

If we record a video to the internal cache and then try to rename() it to an external SD card, the OS can't just move the file pointer. It's forced to do a full byte-by-byte copy and delete. For large videos, this causes a huge I/O bottleneck and temporarily doubles the storage space needed (which can fail if internal storage is low). Writing directly to the target path avoids this completely.

Regarding the SD card: apps still have direct write access to their app-specific folders on external SD cards (for example, the second directory returned by getExternalStorageDirectories() in path_provider). By using videoOutputPath, we can record straight to the SD card from the start and bypass internal storage limits altogether.

Regarding the crash recovery scenario mentioned in flutter/flutter#91680, you're absolutely right that the MP4 may end up corrupted after a crash, especially if the final moov atom was never written.

The main issue today is that the native layer generates a random temporary filename, and Dart only receives that path after stopVideoRecording completes successfully. If the app crashes before that happens, the temporary file becomes orphaned and the application has no reliable way to discover or identify it afterward.

By providing the output path upfront, the application always knows where the recording is being written. After a restart, developers can at least locate the interrupted file, attempt MP4 recovery if possible, or simply clean up the orphaned file to avoid unnecessary storage leaks.

Let me know if this makes sense or if I should adjust anything in the implementation.

@Mairramer
Copy link
Copy Markdown
Contributor Author

Regarding crash recovery:

On iOS, we could use movieFragmentInterval, which allows the movie file to be fragmented periodically and can help reduce data loss in crash scenarios.

On Android, as far as I know, there is no equivalent native solution available. We would probably need a custom implementation using MediaMuxer or something similar to periodically fragment or remux the recording stream, but that’s not something I’d really like to introduce at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Camera]: Proposal to add set path file on startVideoRecording

2 participants