Skip to content

[camera_android] stopVideoRecording() returns the JPEG path from takePicture() when a picture is taken during recording #192927

Closed
flutter/packages
#13070

Description

@PraveenGangula1392

Steps to reproduce
Take a picture while a video recording is in progress — a combination explicitly supported since camera_android 0.10.8+3 ("Adds support for concurrently capturing images and image streaming/recording").


final List<CameraDescription> cameras = await availableCameras();
final CameraController controller = CameraController(
  cameras.first,
  ResolutionPreset.high,
  enableAudio: false,
);
await controller.initialize();

await controller.startVideoRecording();
await Future<void>.delayed(const Duration(seconds: 3));

// Supported since 0.10.8+3.
await controller.takePicture();
await Future<void>.delayed(const Duration(seconds: 3));

final XFile video = await controller.stopVideoRecording();

print(video.path);
// .../cache/CAP7719046239.jpg      <-- a JPEG, not the recording

final Uint8List head = (await File(video.path).readAsBytes()).sublist(0, 4);
print(head);
// [255, 216, 255, 225]             <-- ff d8 ff e1 = JPEG SOI + APP1

Expected results
stopVideoRecording() returns the path of the REC*.mp4 created by startVideoRecording().

Actual results
It returns the path of the CAP*.jpg created by the intervening takePicture().

No exception is thrown. MediaRecorder finalizes the real REC*.mp4 correctly — the recording is fine, only the returned path is wrong, and that file is left orphaned in the cache directory with nothing referencing it.

Because the returned XFile is a plausible, non-empty, fully-written file, size- or readability-based validation does not catch it. An app that saves or uploads whatever stopVideoRecording() hands back will silently store a photo in place of the video. We hit this in production: a recording was stored and served as video/mp4 while the bytes were a complete JPEG, and the real video was lost when the OS reclaimed the cache directory.

Root cause

// Camera.java uses a single field for both still capture and video recording, and nothing saves or restores it:
private File captureFile;                                       // line 138

// takePicture()      — line 640
captureFile = File.createTempFile("CAP", ".jpg", outputDir);

// prepareRecording() — line 1303
captureFile = File.createTempFile("REC", ".mp4", outputDir);

// stopVideoRecording() — line 922
String path = captureFile.getAbsolutePath();                    // whichever was set last
captureFile = null;
return path;

takePicture() also has no recordingVideo guard — its only precondition is cameraCaptureCallback.getCameraState() != CameraState.STATE_PREVIEW, which an in-progress video recording passes — so it neither declines nor warns; it simply overwrites the field.

The only captureFile = null after a picture sits in startVideoRecording()'s catch block, so the JPEG path persists until stopVideoRecording() reads it.

Line numbers above are from 0.10.11+1; the same code exists in 0.10.10 at lines 131 / 620 / 1241 / 868.

Suggested fix
Separate the two paths — e.g. a dedicated videoRecordingFile field set by prepareRecording() and read by stopVideoRecording(), leaving captureFile to still capture. A narrower fix would be to save and restore captureFile around takePicture().

Code sample
See "Steps to reproduce" above.

Logs / evidence
The returned file's header, read straight from the path stopVideoRecording() returned:

magic bytes : ff d8 ff e1 -> JPEG SOI + APP1
trailer : ff d9 -> complete, valid JPEG
EXIF : samsung, SM-X205, Software Version v1.1.0
The EXIF capture timestamp matches the moment takePicture() was called, ~8 minutes before stopVideoRecording() was invoked — confirming it is the picture's file and not a truncated recording.

Affected versions
Reproduced on camera_android 0.10.10, and the same code is present in 0.10.11+1 (latest, published 2026-08-28). Nothing in the changelog between those versions touches it.

Note camera_android_camerax is not a workaround for apps that need bitrate/fps control: android_camera_camerax.dart calls proxy.newRecorder(qualitySelector: ...) without targetVideoEncodingBitRate, and has no fps handling at all (see #187149).

Related: #96676 (proposal to take a picture while video recording is in progress — the feature this bug breaks).

Device
Samsung SM-X205 (Galaxy Tab A8), Android.

flutter doctor
[√] Flutter (Channel stable, 3.27.0, on Microsoft Windows [Version 10.0.26200.8246], locale en-IN)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.14.35)
[√] Android Studio (version 2025.3.1)
[√] VS Code
[√] Connected device (4 available)
[√] Network resources
• No issues found!

Activity

  1. mbcorona commented on Sep 17, 2026

    @mbcorona
    Member

    hi @raggi , thanks for reporting.

    takePicture and video recording share one captureFile field, so a picture taken mid recording overwrites it and stopVideoRecording returns the JPEG path instead of the mp4.

    https://github.com/flutter/packages/blob/485671d24a9088fe8dfff850242ccf0ffc0b6b9a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java#L138

    Routing to team-android.

  2. added
    platform-androidAndroid applications specifically
    packageflutter/packages repository. See also p: labels.
    team-androidOwned by Android platform team
    fyi-ecosystemFor the attention of Ecosystem team
    and removed
    fyi-ecosystemFor the attention of Ecosystem team
    on Sep 17, 2026
  3. added
    P2Important issues not at the top of the work list
    P3Issues that are less important to the Flutter project
    triaged-androidTriaged by Android platform team
    team-androidOwned by Android platform team
    and removed
    P2Important issues not at the top of the work list
    platform-androidAndroid applications specifically
    packageflutter/packages repository. See also p: labels.
    P3Issues that are less important to the Flutter project
    team-androidOwned by Android platform team
    on Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projectp: cameraThe camera pluginteam-androidOwned by Android platform teamtriaged-androidTriaged by Android platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions