Skip to content

Camera Video Recording #2710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open

Conversation

VladislavAntonyuk
Copy link
Collaborator

@VladislavAntonyuk VladislavAntonyuk commented Jun 12, 2025

Description of Change

Linked Issues

PR Checklist

Additional information

https://vladislavantonyuk.github.io/articles/Turn-any-phone-into-an-IP-Camera-in-30-Minutes-using-.NET-MAUI/

Copy link
Member

@pictos pictos left a comment

Choose a reason for hiding this comment

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

@VladislavAntonyuk I believe you're using the old Camera2 APi, you should use the CameraX API instead, it will be simpler and it's newer

here for reference https://developer.android.com/media/camera/camerax/video-capture

@VladislavAntonyuk
Copy link
Collaborator Author

@VladislavAntonyuk I believe you're using the old Camera2 APi, you should use the CameraX API instead, it will be simpler and it's newer

here for reference https://developer.android.com/media/camera/camerax/video-capture

I see we reference a NuGet for camera 2, that is why I used this implementation. According to Google camera 2 is not obsolete, but allows you to have a full control of the camera. CameraX just a convenient way to work with camera api. I will update to CameraX.

VladislavAntonyuk and others added 23 commits June 14, 2025 12:11
Ensures proper handling of the video recording stream by setting appropriate file access and share options.
Also, explicitly flushes the stream and nullifies the file after copying to prevent potential issues with file access or deletion.
Addresses an issue where the `VideoRecordEvent` was not correctly identified as the final event.
Updates the `PlatformStartVideoRecording` method signature on Tizen to accept a stream, allowing for greater flexibility in handling video data.
Updated CameraViewPage.xaml to include buttons for starting/stopping video recording and setting night mode. Changed "GetStream" button text to "Save Video Recording" and repositioned "Capture Image" button.

Simplified video file creation in CameraManager.android.cs by removing unnecessary ContentValues. Modified PlatformStopVideoRecording to change flow after stopping video recording.

Enhanced CreateStopVideoRecordingCommand to use async lambda for better asynchronous operation handling.
@VladislavAntonyuk VladislavAntonyuk marked this pull request as ready for review July 19, 2025 11:59
@VladislavAntonyuk VladislavAntonyuk requested review from Copilot and a team July 19, 2025 11:59
@VladislavAntonyuk VladislavAntonyuk self-assigned this Jul 19, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements video recording functionality for the .NET MAUI Community Toolkit's CameraView, adding comprehensive support across Android, iOS/macOS, and Windows platforms. The implementation includes new public APIs for starting and stopping video recording, along with extension capabilities for Android camera features.

Key changes include:

  • Addition of StartVideoRecording and StopVideoRecording methods to the CameraView API
  • Platform-specific implementations for video recording across all supported platforms
  • New command properties for XAML binding support
  • Sample application updates to demonstrate video recording functionality

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
CameraView.shared.cs Adds new bindable properties and commands for video recording functionality
CameraViewDefaults.shared.cs Implements default command factories for video recording operations
ICameraView.shared.cs Defines the public interface for video recording methods
CameraManager.*.cs Platform-specific implementations of video recording for Android, iOS/macOS, Windows, Tizen, and .NET
Sample project files Updates sample app to demonstrate video recording with UI controls and save functionality

@ne0rrmatrix
Copy link
Contributor

This is looking very well done! I am shocked at how nice some of the code looks. I have for over a year now wanted a solution to async - await for android in dotnet. From looking at this code I can see an easy example I can reference in the future for how to do that! Ty for that alone!

I am going to test on my Mac mini and my iPad later this morning but just looking at the code it looks good to go after you look at my comments. I think all that is left for now is finishing testing and starting the documentation. This is a great addition to the toolkit.

@ne0rrmatrix
Copy link
Contributor

Start video recording on iOS and iOS simulator is crashing on button click with message about not finding camera.

captureDevice = cameraView.SelectedCamera.CaptureDevice ?? throw new CameraException($"No Camera found");

@ne0rrmatrix
Copy link
Contributor

Managed to get a stacktrace for MacOS. For some reason the debugger was not working for either iOS simulator or device.

MacOS:

ObjCRuntime.ObjCException: Objective-C exception thrown.  Name: NSInvalidArgumentException Reason: *** -[AVCaptureDevice _setActiveFormat:resetVideoZoomFactorAndMinMaxFrameDurations:sessionPreset:] Unsupported format ((null)) - use -formats to discover valid formats
Native stack trace:
	0   CoreFoundation                      0x0000000196f6eca0 __exceptionPreprocess + 176
	1   libobjc.A.dylib                     0x0000000196a32b90 objc_exception_throw + 88
	2   AVFCapture                          0x00000001b76ca69c -[AVCaptureFigVideoDevice _setActiveFormat:resetVideoZoomFactorAndMinMaxFrameDurations:sessionPreset:] + 4584
	3   AVFCapture                          0x00000001b7732894 -[AVCaptureSession _updateDeviceActiveFormatsAndActiveConnections] + 2452
	4   AVFCapture                          0x00000001b77314f4 -[AVCaptureSession _buildAndRunGraph:] + 340
	5   AVFCapture                          0x00000001b7728528 -[AVCaptureSession _commitConfiguration] + 408
	6   AVFCapture                          0x00000001b772917c -[AVCaptureSession addInput:] + 764
	7   CommunityToolkit.Maui.Sample        0x00000001026d8a58 xamarin_dyn_objc_msgSend + 160
	8   CommunityToolkit.Maui.Sample        0x00000001029777a4 do_icall + 200
	9   CommunityToolkit.Maui.Sample        0x0000000102975d10 do_icall_wrapper + 356
	10  CommunityToolkit.Maui.Sample        0x000000010296a624 mono_interp_exec_method + 2456
	11  CommunityToolkit.Maui.Sample        0x0000000102968258 interp_runtime_invoke + 244
	12  CommunityToolkit.Maui.Sample        0x00000001028b0324 mono_jit_runtime_invoke + 1268
	13  CommunityToolkit.Maui.Sample        0x00000001028521f8 mono_runtime_try_invoke + 156
	14  CommunityToolkit.Maui.Sample        0x00000001028541d0 mono_runtime_invoke + 516
	15  CommunityToolkit.Maui.Sample        0x00000001029b18bc _ZL30native_to_managed_trampoline_9P11objc_objectP13objc_selectorPP11_MonoMethodj + 276
	16  CommunityToolkit.Maui.Sample        0x0000000102a04314 -[__MonoMac_NSAsyncSynchronizationContextDispatcher xamarinApplySelector] + 44
	17  Foundation                          0x00000001984e8f74 __NSThreadPerformPerform + 264
	18  CoreFoundation                      0x0000000196efdcd4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
	19  CoreFoundation                      0x0000000196efdc68 __CFRunLoopDoSource0 + 172
	20  CoreFoundation                      0x0000000196efd9d4 __CFRunLoopDoSources0 + 232
	21  CoreFoundation                      0x0000000196efc628 __CFRunLoopRun + 840
	22  CoreFoundation                      0x0000000196efbc58 CFRunLoopRunSpecific + 572
	23  HIToolbox                           0x00000001a299027c RunCurrentEventLoopInMode + 324
	24  HIToolbox                           0x00000001a29934e8 ReceiveNextEventCommon + 676
	25  HIToolbox                           0x00000001a2b1e484 _BlockUntilNextEventMatchingListInModeWithFilter + 76
	26  AppKit                              0x000000019ae23ab4 _DPSNextEvent + 684
	27  AppKit                              0x000000019b7c25b0 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 688
	28  AppKit                              0x000000019ae16c64 -[NSApplication run] + 480
	29  AppKit                              0x000000019aded35c NSApplicationMain + 880
	30  AppKit                              0x000000019b039cf4 +[NSWindow _savedFrameFromString:] + 0
	31  UIKitMacHelper                      0x00000001b2420164 UINSApplicationMain + 976
	32  UIKitCore                           0x00000001caa93c9c UIApplicationMain + 148
	33  CommunityToolkit.Maui.Sample        0x00000001026ac5a4 xamarin_UIApplicationMain + 60
	34  CommunityToolkit.Maui.Sample        0x0000000102977818 do_icall + 316
	35  CommunityToolkit.Maui.Sample        0x0000000102975d10 do_icall_wrapper + 356
	36  CommunityToolkit.Maui.Sample        0x000000010296a624 mono_interp_exec_method + 2456
	37  CommunityToolkit.Maui.Sample        0x0000000102968258 interp_runtime_invoke + 244
	38  CommunityToolkit.Maui.Sample        0x00000001028b0324 mono_jit_runtime_invoke + 1268
	39  CommunityToolkit.Maui.Sample        0x00000001028508e0 mono_runtime_invoke_checked + 148
	40  CommunityToolkit.Maui.Sample        0x0000000102856828 mono_runtime_exec_main_checked + 116
	41  CommunityToolkit.Maui.Sample        0x0000000102901bb4 mono_jit_exec + 364
	42  CommunityToolkit.Maui.Sample        0x00000001026d75f8 xamarin_main + 832
	43  CommunityToolkit.Maui.Sample        0x0000000102a52234 main + 64
	44  dyld                                0x0000000196a72b98 start + 6076

   at AVFoundation.AVCaptureSession.AddInput(AVCaptureInput input) in /Users/builder/azdo/_work/1/s/macios/src/build/dotnet/maccatalyst/generated-sources/AVFoundation/AVCaptureSession.g.cs:line 340
   at CommunityToolkit.Maui.Core.CameraManager.<PlatformStartCameraPreview>d__46.MoveNext() in /Users/jamescrutchley/Documents/MauiOld/MauiOld/src/CommunityToolkit.Maui.Camera/CameraManager.macios.cs:line 165
   at CommunityToolkit.Maui.Core.CameraManager.<PlatformConnectCamera>d__47.MoveNext() in /Users/jamescrutchley/Documents/MauiOld/MauiOld/src/CommunityToolkit.Maui.Camera/CameraManager.macios.cs:line 139
   at CommunityToolkit.Maui.Core.Handlers.CameraViewHandler.ConnectHandler(UIView platformView) in /Users/jamescrutchley/Documents/MauiOld/MauiOld/src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs:line 92
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
   at Foundation.NSAsyncSynchronizationContextDispatcher.Apply() in /Users/builder/azdo/_work/1/s/macios/src/Foundation/NSAction.cs:line 179
Native stack trace:
	0   CoreFoundation                      0x0000000196f6eca0 __exceptionPreprocess + 176
	1   libobjc.A.dylib                     0x0000000196a32b90 objc_exception_throw + 88
	2   AVFCapture                          0x00000001b76ca69c -[AVCaptureFigVideoDevice _setActiveFormat:resetVideoZoomFactorAndMinMaxFrameDurations:sessionPreset:] + 4584
	3   AVFCapture                          0x00000001b7732894 -[AVCaptureSession _updateDeviceActiveFormatsAndActiveConnections] + 2452
	4   AVFCapture                          0x00000001b77314f4 -[AVCaptureSession _buildAndRunGraph:] + 340
	5   AVFCapture                          0x00000001b7728528 -[AVCaptureSession _commitConfiguration] + 408
	6   AVFCapture                          0x00000001b772917c -[AVCaptureSession addInput:] + 764
	7   CommunityToolkit.Maui.Sample        0x00000001026d8a58 xamarin_dyn_objc_msgSend + 160
	8   CommunityToolkit.Maui.Sample        0x00000001029777a4 do_icall + 200
	9   CommunityToolkit.Maui.Sample        0x0000000102975d10 do_icall_wrapper + 356
	10  CommunityToolkit.Maui.Sample        0x000000010296a624 mono_interp_exec_method + 2456
	11  CommunityToolkit.Maui.Sample        0x0000000102968258 interp_runtime_invoke + 244
	12  CommunityToolkit.Maui.Sample        0x00000001028b0324 mono_jit_runtime_invoke + 1268
	13  CommunityToolkit.Maui.Sample        0x00000001028521f8 mono_runtime_try_invoke + 156
	14  CommunityToolkit.Maui.Sample        0x00000001028541d0 mono_runtime_invoke + 516
	15  CommunityToolkit.Maui.Sample        0x00000001029b18bc _ZL30native_to_managed_trampoline_9P11objc_objectP13objc_selectorPP11_MonoMethodj + 276
	16  CommunityToolkit.Maui.Sample        0x0000000102a04314 -[__MonoMac_NSAsyncSynchronizationContextDispatcher xamarinApplySelector] + 44
	17  Foundation                          0x00000001984e8f74 __NSThreadPerformPerform + 264
	18  CoreFoundation                      0x0000000196efdcd4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
	19  CoreFoundation                      0x0000000196efdc68 __CFRunLoopDoSource0 + 172
	20  CoreFoundation                      0x0000000196efd9d4 __CFRunLoopDoSources0 + 232
	21  CoreFoundation                      0x0000000196efc628 __CFRunLoopRun + 840
	22  CoreFoundation                      0x0000000196efbc58 CFRunLoopRunSpecific + 572
	23  HIToolbox                           0x00000001a299027c RunCurrentEventLoopInMode + 324
	24  HIToolbox                           0x00000001a29934e8 ReceiveNextEventCommon + 676
	25  HIToolbox                           0x00000001a2b1e484 _BlockUntilNextEventMatchingListInModeWithFilter + 76
	26  AppKit                              0x000000019ae23ab4 _DPSNextEvent + 684
	27  AppKit                              0x000000019b7c25b0 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 688
	28  AppKit                              0x000000019ae16c64 -[NSApplication run] + 480
	29  AppKit                              0x000000019aded35c NSApplicationMain + 880
	30  AppKit                              0x000000019b039cf4 +[NSWindow _savedFrameFromString:] + 0
	31  UIKitMacHelper                      0x00000001b2420164 UINSApplicationMain + 976
	32  UIKitCore                           0x00000001caa93c9c UIApplicationMain + 148
	33  CommunityToolkit.Maui.Sample        0x00000001026ac5a4 xamarin_UIApplicationMain + 60
	34  CommunityToolkit.Maui.Sample        0x0000000102977818 do_icall + 316
	35  CommunityToolkit.Maui.Sample        0x0000000102975d10 do_icall_wrapper + 356
	36  CommunityToolkit.Maui.Sample        0x000000010296a624 mono_interp_exec_method + 2456
	37  CommunityToolkit.Maui.Sample        0x0000000102968258 interp_runtime_invoke + 244
	38  CommunityToolkit.Maui.Sample        0x00000001028b0324 mono_jit_runtime_invoke + 1268
	39  CommunityToolkit.Maui.Sample        0x00000001028508e0 mono_runtime_invoke_checked + 148
	40  CommunityToolkit.Maui.Sample        0x0000000102856828 mono_runtime_exec_main_checked + 116
	41  CommunityToolkit.Maui.Sample        0x0000000102901bb4 mono_jit_exec + 364
	42  CommunityToolkit.Maui.Sample        0x00000001026d75f8 xamarin_main + 832
	43  CommunityToolkit.Maui.Sample        0x0000000102a52234 main + 64
	44  dyld                                0x0000000196a72b98 start + 6076

Hopefully that might help figure out what is going on. I don't have a camera attached to my mac mini. Which is probably an issue but should the sample app crash when you open the camera page? It just CTD when I navigate to camera page.

@VladislavAntonyuk
Copy link
Collaborator Author

The camera is not available on iOS simulators; you can only test it on real devices

Refactor video recording logic and improve null checks

- Updated `StartUseCase` in `CameraManager.android.cs` to use a builder pattern for `videoRecorder`, allowing for null checks on `Quality.Highest`.
- Changed executor retrieval in `PlatformStartVideoRecording` to enhance readability and error handling.
- Improved null safety in `EnableModes` by checking for nullability of `extensionsManager`.
- Updated `SupportedOSPlatform` in `CameraManager.windows.cs` to require a higher minimum Windows version.
- Refactored `PlatformStartVideoRecording` to use `var` for `profile` and modernized null-checking style for `frameSource` and `frameFormat`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Proposal] Camera Video Recording
3 participants