Condividi tramite


Quickstart: Capturing video by using the MediaCapture API

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

This topic shows you how to capture video to a file using the Windows.Media.Capture API. You can use the Windows.Media.Capture API to control the asynchronous capture operation, select an encoding profile and send the resulting video to a file.

For another example of capturing media in a Windows Runtime app on both Windows and Windows Phone, see the Media capture sample. For an example of a full-featured camera app, recommended as a starting place for building your own camera app, see Advanced Camera Sample. This sample is currently only available for Windows Phone.

Objective: This tutorial shows how to capture video using the Windows.Media.Capture API.

Prerequisites

This topic assumes that you know how to create a basic Windows Runtime app using C++, C#, or Visual Basic. For help creating your first app, see Create your first Windows Store app using C# or Visual Basic.

Instructions

Declare the webcam capability

Use the designer of the application manifest file to add the webcam capability. Select the Capabilities tab and then select Webcam from the list.

Initialize the MediaCaptureSettings

The MediaCaptureSettings property provides the configuration settings for the MediaCapture object. Use the MediaCaptureInitializationSettings class to initialize these properties, as in the following example.

private void InitCaptureSettings()
{
    _captureInitSettings = null;
    _captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
    _captureInitSettings.AudioDeviceId = "";
    _captureInitSettings.VideoDeviceId = "";
    _captureInitSettings.StreamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.AudioAndVideo;
    _captureInitSettings.PhotoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.VideoPreview;
    
    if (_deviceList.Count > 0)
        _captureInitSettings.VideoDeviceId = _deviceList[0].Id;
}

Create the MediaCapture object

The MediaCapture object contains the methods and asynchronous operations that you need to capture a video.

_mediaCapture = new Windows.Media.Capture.MediaCapture();

// Set the MediaCapture to a variable in App.xaml.cs to handle suspension.
(App.Current as App).MediaCapture = _mediaCapture;

Initialize the MediaCapture object

Use the MediaCapture.InitializeAsync method to initialize the MediaCapture object. By default, InitializeAsync uses the default video capture device and will capture either audio or video. Alternatively, you can create and initialize your own MediaCaptureInitializationSettings object and pass it to the InitializeAsync method.

// Create and initialze the MediaCapture object.
public async void InitMediaCapture()
{
    _mediaCapture = null;
    _mediaCapture = new Windows.Media.Capture.MediaCapture();

    // Set the MediaCapture to a variable in App.xaml.cs to handle suspension.
    (App.Current as App).MediaCapture = _mediaCapture;

    await _mediaCapture.InitializeAsync(_captureInitSettings);

    CreateProfile();
}

Create an encoding profile

The encoding profile contains all of the settings for how the destination file will be encoded. The MediaProperties API provides several options for creating a MediaEncodingProfile object.

The Windows.Media.MediaProperties namespace provides a set of predefined encoding profiles:

  • AAC audio (M4A)
  • MP3 audio
  • Windows Media Audio (WMA)
  • MP4 video (H.264 video plus AAC audio)
  • Windows Media Video (WMV)

The first three profiles in this list contain audio only. The other two contain video and audio.

The following code creates a profile for MP4 video.

// Create a profile.
private void CreateProfile()
{
    _profile = Windows.Media.MediaProperties.MediaEncodingProfile.CreateMp4(
    Windows.Media.MediaProperties.VideoEncodingQuality.Qvga);
}

The static CreateMp4 method creates an MP4 encoding profile. The parameter to this method gives the target resolution for the video. In this case, VideoEncodingQuality.HD720p means 1280 x 720 pixels at 30 frames per second. ("720p" stands for 720 progressive scan lines per frame.) The other methods for creating predefined profiles all follow this pattern.

Alternatively, you can create a profile that matches an existing media file by using the MediaProperties.MediaEncodingProfile.CreateFromFileAsync method. Or, if you know the exact encoding settings that you want, you can create a new MediaProperties.MediaEncodingProfile object and fill in all of the profile details.

Start recording

To start capturing video to a file, create a file for the captured video. Then call the StartRecordToStorageFileAsync method, passing in the MediaEncodingProfile and the destination storage file.

// Start the video capture.
private async void StartMediaCaptureSession()
{
    var storageFile = await Windows.Storage.KnownFolders.VideosLibrary.CreateFileAsync(
        "cameraCapture.mp4", Windows.Storage.CreationCollisionOption.GenerateUniqueName);

    await _mediaCapture.StartRecordToStorageFileAsync(_profile, storageFile);
    _recording = true;
}

Stop recording

To stop capturing video, call the StopRecordAsync method.

// Stop the video capture.
private async void StopMediaCaptureSession()
{
    await _mediaCapture.StopRecordAsync();
    _recording = false;
    (App.Current as App).IsRecording = false;
}

Complete example

The following example shows how the steps for capturing video to a file are put together.

MediaCaptureInitializationSettings _captureInitSettings;
List<Windows.Devices.Enumeration.DeviceInformation> _deviceList;
Windows.Media.MediaProperties.MediaEncodingProfile _profile;
Windows.Media.Capture.MediaCapture _mediaCapture;
bool _recording = false;
bool _previewing = false;

private async void EnumerateCameras()
{
    var devices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(
        Windows.Devices.Enumeration.DeviceClass.VideoCapture);

    _deviceList = new List<Windows.Devices.Enumeration.DeviceInformation>();

    // Add the devices to deviceList
    if (devices.Count > 0)
    {

        for (var i = 0; i < devices.Count; i++)
        {
            _deviceList.Add(devices[i]);
        }

        InitCaptureSettings();
        InitMediaCapture();
        rootPage.NotifyUser("Initialization complete.", NotifyType.StatusMessage);

    }
    else
    {
        rootPage.NotifyUser("No camera device is found ", NotifyType.ErrorMessage);
    }
}

// Begin initialization.
private void Initialization()
{
    rootPage.NotifyUser("Initialization started.", NotifyType.StatusMessage);
    EnumerateCameras();
}


private void InitCaptureSettings()
{
    _captureInitSettings = null;
    _captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
    _captureInitSettings.AudioDeviceId = "";
    _captureInitSettings.VideoDeviceId = "";
    _captureInitSettings.StreamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.AudioAndVideo;
    _captureInitSettings.PhotoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.VideoPreview;
    
    if (_deviceList.Count > 0)
        _captureInitSettings.VideoDeviceId = _deviceList[0].Id;
}

// Create a profile.
private void CreateProfile()
{
    _profile = Windows.Media.MediaProperties.MediaEncodingProfile.CreateMp4(
    Windows.Media.MediaProperties.VideoEncodingQuality.Qvga);
}

// Create and initialze the MediaCapture object.
public async void InitMediaCapture()
{
    _mediaCapture = null;
    _mediaCapture = new Windows.Media.Capture.MediaCapture();

    // Set the MediaCapture to a variable in App.xaml.cs to handle suspension.
    (App.Current as App).MediaCapture = _mediaCapture;

    await _mediaCapture.InitializeAsync(_captureInitSettings);

    CreateProfile();
}

// Start the video capture.
private async void StartMediaCaptureSession()
{
    var storageFile = await Windows.Storage.KnownFolders.VideosLibrary.CreateFileAsync(
        "cameraCapture.mp4", Windows.Storage.CreationCollisionOption.GenerateUniqueName);

    await _mediaCapture.StartRecordToStorageFileAsync(_profile, storageFile);
    _recording = true;
}

// Stop the video capture.
private async void StopMediaCaptureSession()
{
    await _mediaCapture.StopRecordAsync();
    _recording = false;
    (App.Current as App).IsRecording = false;
}

Cleaning up MediaCapture resources properly

Warning  

It is extremely important that you properly shut down and dispose of the MediaCapture object and related objects when your app is suspended. Failure to do so could interfere with other apps accessing the device's camera which will result in a negative user experience for your app.

On Windows Phone, clean up your MediaCapture resources in the handler for the Suspending app lifetime event and recreate them in the Resuming event. On Windows, use the SoundLevelChanged events and check if sound level was muted. If it was muted, then clean up the MediaCapture resources. If the event indicates any other sound level, use the event to recreate them. Note that this event will not trigger your code even if you manually mute/unmute the sound while the app is running. So, this event effectively serves the same purpose as Suspend and Resume on phone. This is necessary because, on Windows, the user may be able to switch between apps without the current app being suspended.

 

You should cleanup media capture resources in the Suspending event on Windows Phone or the SoundLevelChanged on Windows, as explained in the above note. In order to do this, your App class will need to access your MediaCapture object and its current state. A good way to do this is to declare some public properties in your app.xaml.cs file to store the MediaCapture object, the CaptureElement you are using for your preview, and booleans that indicate whether the app is currently recording or previewing video.

public MediaCapture MediaCapture { get; set; }
public CaptureElement PreviewElement { get; set; }
public bool IsRecording { get; set; }
public bool IsPreviewing { get; set; }

Create a function in App.xaml.cs that stops recording or previewing if they are in progress. If you are using a MediaElement, set its source to null. And finally, call Dispose on your MediaCapture object.

public async Task CleanupCaptureResources()
{
    if (IsRecording && MediaCapture != null)
    {
        await MediaCapture.StopRecordAsync();
        IsRecording = false;
    }
    if (IsPreviewing && MediaCapture != null)
    {
        await MediaCapture.StopPreviewAsync();
        IsPreviewing = false;
    }

    if (MediaCapture != null)
    {
        if (PreviewElement != null)
        {
            PreviewElement.Source = null;
        }
        MediaCapture.Dispose();
    }
}

Finally, add the following code to your OnSuspending event handler. It is very important that you get a deferral before calling your cleanup method. This ensures that the system lets the method complete before suspending your app.

private async void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();

    //cleanup camera resources
    await CleanupCaptureResources();

    deferral.Complete();
}

Summary

This topic described how to capture video using the MediaCapture class.

Roadmaps

Roadmap for Windows Runtime apps using C# or Visual Basic

Designing UX for apps

Adding multimedia

Samples

Media capture sample

Camera capture UI sample

Camera options UI sample

Device enumeration sample

Real-Time communication sample

Media extension sample

Tasks

Quickstart: capturing a photo or video using the camera dialog

Reference

Windows.Media

Windows.Media.Capture

Windows.Media.Devices

Windows.Media.MediaProperties

Other resources

Supported audio and video formats

Audio and video performance