Skip to content

[camera_avfoundation] AVAssetWriter::startWriting should not be called inside didOutputSampleBuffer #151319

@misos1

Description

@misos1

Steps to reproduce

  1. run code sample
  2. record some motion
  3. stop recording
  4. observe big lag at beginning

Video player here is used only to show the resulting video.

Expected results

No big lag at the beginning.

Actual results

Big lag at beginning of video. AVAssetWriter::startWriting can take a considerable amount of time to execute, like even 300 ms on a tested device. When first frame arrives startWriting is called in didOutputSampleBuffer and during those 300 ms are skipped some upcoming frames then after it finally writes the first frame and didOutputSampleBuffer returns can arrive more frames and video continues, this causes that big lag at beginning of video. In the attached video is shown the recorded video in loop and it plays 3x. This big lag completely disappears when startWriting is moved into startVideoRecordingWithCompletion for example.

Code sample

Code sample
import "dart:io";
import "package:flutter/material.dart";
import "package:camera/camera.dart";
import "package:video_player/video_player.dart";

void main()
{
	runApp(const MaterialApp(home: MyHomePage()));
}

class MyHomePage extends StatefulWidget
{
	const MyHomePage({super.key});
	@override State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
{
	bool loading = true;
	bool recording = false;
	late CameraController camera_cont;
	String? file;

	@override void initState()
	{
		super.initState();
		init_camera();
	}

	init_camera() async
	{
		final cameras = await availableCameras();
		camera_cont = CameraController(cameras.firstWhere((camera) => camera.lensDirection == CameraLensDirection.back), ResolutionPreset.ultraHigh, enableAudio: false);
		await camera_cont.initialize();
		setState(() => loading = false);
		await camera_cont.prepareForVideoRecording();
	}

	void record() async
	{
		await camera_cont.startVideoRecording();
		setState(() => recording = true);
	}

	void stop() async
	{
		final f = await camera_cont.stopVideoRecording();
		setState(() => file = f.path);
	}

	@override Widget build(BuildContext context)
	{
		if(loading)return const Center(child: CircularProgressIndicator());
		if(file != null)return VideoPlayer(VideoPlayerController.file(File(file!))..initialize()..setLooping(true)..play());
		return Stack(
			alignment: Alignment.bottomLeft,
			children: [
				Stack(
					alignment: Alignment.bottomCenter,
					children: [
						CameraPreview(camera_cont),
						if(recording)FilledButton(onPressed: stop, child: const Text("Stop"))
						else FilledButton(onPressed: record, child: const Text("Record")),
					],
				),
			],
		);
	}
}

Screenshots or Video

Screenshots / Video demonstration
test.mov

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.22.2, on macOS 14.5 23F79 darwin-x64)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listfound in release: 3.22Found to occur in 3.22has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: cameraThe camera pluginpackageflutter/packages repository. See also p: labels.platform-iosiOS applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions