使用 MediaCapture 捕获基本的照片、视频和音频Basic photo, video, and audio capture with MediaCapture

本文介绍了使用 MediaCapture 类捕获照片和视频的最简单方法。This article shows the simplest way to capture photos and video using the MediaCapture class. MediaCapture 类公布了一组强大的 API,可提供捕获管道的低级别控制和启用高级捕获方案,但本文旨在帮助你将基本的媒体捕获快速且轻松地添加到应用。The MediaCapture class exposes a robust set of APIs that provide low-level control over the capture pipeline and enable advanced capture scenarios, but this article is intended to help you add basic media capture to your app quickly and easily. 若要了解有关 MediaCapture 提供的功能的详细信息,请参阅相机To learn about more of the features that MediaCapture provides, see Camera.

如果你仅希望捕获照片或视频,不想添加任何其他媒体捕获功能,或者如果你不想创建自己的相机 UI,则可能希望使用 CameraCaptureUI 类,它允许你仅启动 Windows 内置相机应用,并且接收捕获的照片或视频文件。If you simply want to capture a photo or video and don't intend to add any additional media capture features, or if you don't want to create your own camera UI, you may want to use the CameraCaptureUI class, which allows you to simply launch the Windows built-in camera app and receive the photo or video file that was captured. 有关详细信息,请参阅使用 Windows 内置相机 UI 捕获照片和视频For more information, see Capture photos and video with Windows built-in camera UI

本文中的代码源自 Camera starter kit 示例。The code in this article was adapted from the Camera starter kit sample. 你可以下载该示例以查看上下文中使用的代码,或将该示例用作你自己的应用的起始点。You can download the sample to see the code used in context or to use the sample as a starting point for your own app.

向应用清单中添加功能声明Add capability declarations to the app manifest

为了让你的应用可以访问设备的相机,必须声明你的应用要使用 webcammicrophone 设备功能。In order for your app to access a device's camera, you must declare that your app uses the webcam and microphone device capabilities. 如果你想要将已捕获的照片和视频保存到用户的图片库或视频库,还必须声明 picturesLibraryvideosLibrary 功能。If you want to save captured photos and videos to the users's Pictures or Videos library, you must also declare the picturesLibrary and videosLibrary capability.

将功能添加到应用部件清单To add capabilities to the app manifest

  1. 在 Microsoft Visual Studio 的 解决方案资源管理器中,双击 " appxmanifest.xml " 项,打开应用程序清单的设计器。In Microsoft Visual Studio, in Solution Explorer, open the designer for the application manifest by double-clicking the package.appxmanifest item.
  2. 选择“功能”选项卡。Select the Capabilities tab.
  3. 选中 " 网络摄像机 " 和 " 麦克风" 框。Check the box for Webcam and the box for Microphone.
  4. 对于 "图片和视频库" 的访问权限,请选中 " 图片库 " 和 " 视频库" 复选框。For access to the Pictures and Videos library check the boxes for Pictures Library and the box for Videos Library.

初始化 MediaCapture 对象Initialize the MediaCapture object

本文介绍的所有捕获方法都需要通过依次调用构造函数和 InitializeAsync,首先初始化 MediaCapture 对象。All of the capture methods described in this article require the first step of initializing the MediaCapture object by calling the constructor and then calling InitializeAsync. 由于在应用中可从多个位置访问 MediaCapture 对象,所以请声明某个类变量以保留该对象。Since the MediaCapture object will be accessed from multiple places in your app, declare a class variable to hold the object. 如果捕获操作失败,请为待通知的 MediaCapture 对象的 Failed 事件实现处理程序。Implement a handler for the MediaCapture object's Failed event to be notified if a capture operation fails.

MediaCapture mediaCapture;
bool isPreviewing;
mediaCapture = new MediaCapture();
await mediaCapture.InitializeAsync();
mediaCapture.Failed += MediaCapture_Failed;

设置相机预览Set up the camera preview

使用 MediaCapture 无需显示相机预览即可捕获照片、视频和音频,但通常需要显示预览流,以便用户可以看到捕获的内容。It's possible to capture photos, videos, and audio using MediaCapture without showing the camera preview, but typically you want to show the preview stream so that the user can see what's being captured. 此外,一些 MediaCapture 功能在可以启用前需要运行预览流,这些功能包括自动对焦、自动曝光以及自动白平衡。Also, a few MediaCapture features require the preview stream to be running before they can be enbled, including auto focus, auto exposure, and auto white balance. 若要了解如何设置相机预览,请参阅显示相机预览To see how to set up the camera preview, see Display the camera preview.

将照片捕获到 SoftwareBitmapCapture a photo to a SoftwareBitmap

Windows 10 引入了 SoftwareBitmap 类,可跨多项功能提供图像的通用表示形式。The SoftwareBitmap class was introduced in Windows 10 to provide a common representation of images across multiple features. 如果你想捕获照片并立即在应用中使用捕获的图像(例如在 XAML 中显示它,而非捕获到某个文件),则应捕获到 SoftwareBitmapIf you want to capture a photo and then immediately use the captured image in your app, such as displaying it in XAML, instead of capturing to a file, then you should capture to a SoftwareBitmap. 你仍可选择在以后将图像保存到磁盘。You still have the option of saving the image to disk later.

初始化 MediaCapture 对象后,可使用 LowLagPhotoCapture 类将照片捕获到 SoftwareBitmapAfter initializing the MediaCapture object, you can capture a photo to a SoftwareBitmap using the LowLagPhotoCapture class. 通过调用 PrepareLowLagPhotoCaptureAsync(该函数在指定所需图像格式的 ImageEncodingProperties 对象中传递),获取此类的实例。Get an instance of this class by calling PrepareLowLagPhotoCaptureAsync, passing in an ImageEncodingProperties object specifying the image format you want. CreateUncompressed 使用指定的像素格式创建未压缩的编码。CreateUncompressed creates an uncompressed encoding with the specified pixel format. 通过调用返回 CapturedPhoto 对象的 CaptureAsync 捕获照片。Capture a photo by calling CaptureAsync, which returns a CapturedPhoto object. 通过依次访问 Frame 属性和 SoftwareBitmap 属性,获取 SoftwareBitmapGet a SoftwareBitmap by accessing the Frame property and then the SoftwareBitmap property.

如果需要,可重复调用 CaptureAsync 来捕获多张照片。If you want, you can capture multiple photos by repeatedly calling CaptureAsync. 在完成捕获后,调用 FinishAsync 以关闭 LowLagPhotoCapture 会话,并释放关联的资源。When you are done capturing, call FinishAsync to shut down the LowLagPhotoCapture session and free up the associated resources. 调用 FinishAsync 后,若要开始重新捕获照片,需要在调用 CaptureAsync 之前重新调用 PrepareLowLagPhotoCaptureAsync 以重新初始化捕获会话。After calling FinishAsync, to begin capturing photos again you will need to call PrepareLowLagPhotoCaptureAsync again to reinitialize the capture session before calling CaptureAsync.

// Prepare and capture photo
var lowLagCapture = await mediaCapture.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8));

var capturedPhoto = await lowLagCapture.CaptureAsync();
var softwareBitmap = capturedPhoto.Frame.SoftwareBitmap;

await lowLagCapture.FinishAsync();

自 Windows 版本 1803 起,可访问从 CaptureAsync 返回的 CapturedFrame 类的 BitmapProperties 属性,以检索与捕获的照片相关的元数据。Starting with Windows, version 1803, you can access the BitmapProperties property of the CapturedFrame class returned from CaptureAsync to retrieve metadata about the captured photo. 可将此数据传入 BitmapEncoder,进而将元数据保存到某个文件。You can pass this data into a BitmapEncoder to save the metadata to a file. 之前无法访问未压缩的图像格式的此数据。Previously, there was no way to access this data for uncompressed image formats. 还可访问 ControlValues 属性来检索描述捕获帧的控件值(如曝光度和白平衡)的 CapturedFrameControlValues 对象。You can also access the ControlValues property to retrieve a CapturedFrameControlValues object that describes the control values, such as exposure and white balance, for the captured frame.

若要了解如何使用 BitmapEncoderSoftwareBitmap 对象(包括如何在 XAML 页面显示此类对象),请参阅创建、编辑和保存位图图像For information about using BitmapEncoder and about working with the SoftwareBitmap object, including how to display one in a XAML page, see Create, edit, and save bitmap images.

若要详细了解如何设置捕获设备控件值,请参阅用于照片和视频的捕获设备控件For more information on setting capture device control values, see Capture device controls for photo and video.

自 Windows 10 版本 1803 起,可通过访问 MediaCapture 返回的 CapturedFrameBitmapProperties 属性,获取以未压缩格式捕获的照片的元数据,如 EXIF 信息。Starting with Windows 10, version 1803, you can get the metadata, such as EXIF information, for photos captured in uncompressed format by accessing the BitmapProperties property of the CapturedFrame returned by MediaCapture. 在以前的版本中,仅能在以压缩文件格式捕获的照片的标题中访问此数据。In previous releases this data was only accessible in the header of photos captured to a compressed file format. 手动写入图像文件时,可向 BitmapEncoder 提供此数据。You can provide this data to a BitmapEncoder when manually writing an image file. 有关位图编码的详细信息,请参阅创建、编辑和保存位图图像For more information on encoding bitmaps, see Create, edit, and save bitmap images. 还可通过访问 ControlValues 属性访问捕获图像时使用的帧控件值,如曝光度和闪光设置。You can also access the frame control values, such as exposure and flash settings, used when the image was captured by accessing the ControlValues property. 有关详细信息,请参阅用于照片和视频捕获的捕获设备控件For more information, see Capture device controls for photo and video capture.

将照片捕获到文件Capture a photo to a file

典型的摄影应用会将捕获的照片保存到磁盘或云存储,并且需要将元数据(例如照片方向)添加到文件。A typical photography app will save a captured photo to disk or to cloud storage and will need to add metadata, such as photo orientation, to the file. 以下示例显示如何将照片捕获到文件。The following example shows you how to capture an photo to a file. 你仍可选择在以后从图像文件中创建 SoftwareBitmapYou still have the option of creating a SoftwareBitmap from the image file later.

此示例中显示的技术将照片捕获到内存流,然后从该内存流将照片转码到磁盘上的某个文件。The technique shown in this example captures the photo to an in-memory stream and then transcode the photo from the stream to a file on disk. 此示例使用 GetLibraryAsync 获取用户的图片库,然后使用 SaveFolder 属性获取参考默认保存文件夹。This example uses GetLibraryAsync to get the user's pictures library and then the SaveFolder property to get a reference default save folder. 请记得将 " 图片库 " 功能添加到应用程序清单以访问此文件夹。Remember to add the Pictures Library capability to your app manifest to access this folder. CreateFileAsync 创建保存照片的新 StorageFileCreateFileAsync creates a new StorageFile to which the photo will be saved.

创建 InMemoryRandomAccessStream,然后调用 CapturePhotoToStreamAsync 以将照片捕获到流,该照片在流和指定应使用的图像格式的 ImageEncodingProperties 对象中传递。Create an InMemoryRandomAccessStream and then call CapturePhotoToStreamAsync to capture a photo to the stream, passing in the stream and an ImageEncodingProperties object specifying the image format that should be used. 可通过自行初始化对象来创建自定义编码属性,但类提供用于常见编码格式的静态方法,例如 ImageEncodingProperties.CreateJpegYou can create custom encoding properties by initializing the object yourself, but the class provides static methods, like ImageEncodingProperties.CreateJpeg for common encoding formats. 接下来,通过调用 OpenAsync 创建输出文件的文件流。Next, create a file stream to the output file by calling OpenAsync. 创建 BitmapDecoder 以解码内存流中的图像,然后创建 BitmapEncoder 以通过调用 CreateForTranscodingAsync 将图像编码到文件。Create a BitmapDecoder to decode the image from the in memory stream and then create a BitmapEncoder to encode the image to file by calling CreateForTranscodingAsync.

可选择创建 BitmapPropertySet 对象,然后在图像编码器上调用 SetPropertiesAsync,以将照片相关元数据包含在图像文件中。You can optionally create a BitmapPropertySet object and then call SetPropertiesAsync on the image encoder to include metadata about the photo in the image file. 有关编码属性的详细信息,请参阅图像元数据For more information about encoding properties, see Image metadata. 大多数摄影应用需要合理处理设备方向。Handling device orientation properly is essential for most photography apps. 有关详细信息,请参阅使用 MediaCapture 处理设备方向For more information, see Handle device orientation with MediaCapture.

最后,在编码器对象上调用 FlushAsync 以将照片从内存流转码到文件。Finally, call FlushAsync on the encoder object to transcode the photo from the in-memory stream to the file.

var myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
StorageFile file = await myPictures.SaveFolder.CreateFileAsync("photo.jpg", CreationCollisionOption.GenerateUniqueName);

using (var captureStream = new InMemoryRandomAccessStream())
{
    await mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), captureStream);

    using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        var decoder = await BitmapDecoder.CreateAsync(captureStream);
        var encoder = await BitmapEncoder.CreateForTranscodingAsync(fileStream, decoder);

        var properties = new BitmapPropertySet {
            { "System.Photo.Orientation", new BitmapTypedValue(PhotoOrientation.Normal, PropertyType.UInt16) }
        };
        await encoder.BitmapProperties.SetPropertiesAsync(properties);

        await encoder.FlushAsync();
    }
}

若要详细了解如何使用文件和文件夹,请参阅文件、文件夹和库For more information about working with files and folders, see Files, folders, and libraries.

捕获视频Capture a video

通过使用 LowLagMediaRecording 类将视频捕获快速添加到应用。Quickly add video capture to your app by using the LowLagMediaRecording class. 首先,声明对象的类变量。First, declare a class variable to for the object.

LowLagMediaRecording _mediaRecording;

接下来,创建将保存视频的 StorageFile 对象。Next, create a StorageFile object to which the video will be saved. 请注意,若要保存到用户的视频库(如本示例所示),必须将 视频库 功能添加到应用程序清单。Note that to save to the user's video library, as shown in this example, you must add the Videos Library capability to your app manifest. 调用 PrepareLowLagRecordToStorageFileAsync 以初始化媒体录制,该媒体录制在存储文件和指定视频编码的 MediaEncodingProfile 对象中传递。Call PrepareLowLagRecordToStorageFileAsync to initialize the media recording, passing in the storage file and a MediaEncodingProfile object specifying the encoding for the video. 该类提供用于创建常见视频编码配置文件的静态方法,例如 CreateMp4The class provides static methods, like CreateMp4, for creating common video encoding profiles.

最后,调用 StartAsync 以开始捕获视频。Finally, call StartAsync to begin capturing video.

var myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
StorageFile file = await myVideos.SaveFolder.CreateFileAsync("video.mp4", CreationCollisionOption.GenerateUniqueName);
_mediaRecording = await mediaCapture.PrepareLowLagRecordToStorageFileAsync(
        MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto), file);
await _mediaRecording.StartAsync();

若要停止录制视频,请调用 StopAsyncTo stop recording video, call StopAsync.

await _mediaRecording.StopAsync();

可继续调用 StartAsyncStopAsync 以捕获其他视频。You can continue to call StartAsync and StopAsync to capture additional videos. 完成视频捕获后,调用 FinishAsync 以释放捕获会话并清理关联的资源。When you are done capturing videos, call FinishAsync to dispose of the capture session and clean up associated resources. 完成此调用后,必须重新调用 PrepareLowLagRecordToStorageFileAsync 以重新初始化捕获会话,然后才可 StartAsyncAfter this call, you must call PrepareLowLagRecordToStorageFileAsync again to reinitialize the capture session before calling StartAsync.

await _mediaRecording.FinishAsync();

在捕获视频时,应为 MediaCapture 对象的 RecordLimitationExceeded 事件注册处理程序,如果超过单次录制的时限(当前为三小时),操作系统将引发该事件。When capturing video, you should register a handler for the RecordLimitationExceeded event of the MediaCapture object, which will be raised by the operating system if you surpass the limit for a single recording, currently three hours. 在事件的处理程序中,应通过调用 StopAsync 完成录制。In the handler for the event, you should finalize your recording by calling StopAsync.

mediaCapture.RecordLimitationExceeded += MediaCapture_RecordLimitationExceeded;
private async void MediaCapture_RecordLimitationExceeded(MediaCapture sender)
{
    await _mediaRecording.StopAsync();
    System.Diagnostics.Debug.WriteLine("Record limitation exceeded.");
}

播放和编辑捕获的视频文件Play and edit captured video files

将视频捕获到文件后,你可能想要在应用的 UI 中加载并播放该文件。Once you have captured a video to a file, you may want to load the file and play it back within your app's UI. 可使用 MediaPlayerElement XAML 控件和关联的 MediaPlayer 执行此操作。You can do this using the MediaPlayerElement XAML control and an associated MediaPlayer. 若要了解如何在 XAML 页面播放媒体,请参阅使用 MediaPlayer 播放音频和视频For information on playing media in a XAML page, see Play audio and video with MediaPlayer.

还可通过调用 CreateFromFileAsync 从视频文件创建 MediaClip 对象。You can also create a MediaClip object from a video file by calling CreateFromFileAsync. MediaComposition 提供基本的视频编辑功能,如排列 MediaClip 对象的序列、剪裁视频长度、创建层、添加背景音乐和应用视频效果。A MediaComposition provides basic video editing functionality like arranging the sequence of MediaClip objects, trimming video length, creating layers, adding background music, and applying video effects. 若要详细了解如何使用媒体合成功能,请参阅媒体合成和编辑For more information on working with media compositions, see Media compositions and editing.

暂停和恢复视频录制Pause and resume video recording

通过依次调用 PauseAsyncResumeAsync,可暂停并恢复视频录制,无需创建单独的输出文件。You can pause a video recording and then resume recording without creating a separate output file by calling PauseAsync and then calling ResumeAsync.

await _mediaRecording.PauseAsync(Windows.Media.Devices.MediaCapturePauseBehavior.ReleaseHardwareResources);
await _mediaRecording.ResumeAsync();

从 Windows 10 版本 1607 开始,可暂停视频录制,并接收暂停录制前最后捕获的帧。Starting with Windows 10, version 1607, you can pause a video recording and receive the last frame captured before the recording was paused. 然后可在相机预览上覆盖此帧,以允许用户在恢复录制前将相机与暂停的帧保持一致。You can then overlay this frame on the camera preview to allow the user to align the camera with the paused frame before resuming recording. 调用 PauseWithResultAsync 将返回 MediaCapturePauseResult 对象。Calling PauseWithResultAsync returns a MediaCapturePauseResult object. LastFrame 属性是表示最后一帧的 VideoFrame 对象。The LastFrame property is a VideoFrame object representing the last frame. 若要在 XAML 中显示帧,请获取视频帧的 SoftwareBitmap 表示形式。To display the frame in XAML, get the SoftwareBitmap representation of the video frame. 目前仅支持预乘或空 alpha 通道且格式为 BGRA8 的图像,因此如果需要获取正确的格式,请调用 ConvertCurrently, only images in BGRA8 format with premultiplied or empty alpha channel are supported, so call Convert if necessary to get the correct format. 创建新 SoftwareBitmapSource 对象,并调用 SetBitmapAsync 以对其进行初始化。Create a new SoftwareBitmapSource object and call SetBitmapAsync to initialize it. 最后,设置 XAML Image 控件的 Source 属性以显示该图像。Finally, set the Source property of a XAML Image control to display the image. 若要使此技巧有效,图像必须与 CaptureElement 控件保持一致,并且不透明度值应小于 1。For this trick to work, your image must be aligned with the CaptureElement control and should have an opacity value less than one. 请记住,仅可在 UI 线程上修改 UI,因为请在 RunAsync 内部进行此次调用。Don't forget that you can only modify the UI on the UI thread, so make this call inside RunAsync.

PauseWithResultAsync 也会返回在上一段中录制的视频持续时间,以防你需要跟踪录制的总时长。PauseWithResultAsync also returns the duration of the video that was recorded in the preceeding segment in case you need to track how much total time has been recorded.

MediaCapturePauseResult result = 
    await _mediaRecording.PauseWithResultAsync(Windows.Media.Devices.MediaCapturePauseBehavior.RetainHardwareResources);

var pausedFrame = result.LastFrame.SoftwareBitmap;
if(pausedFrame.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || pausedFrame.BitmapAlphaMode != BitmapAlphaMode.Ignore)
{
    pausedFrame = SoftwareBitmap.Convert(pausedFrame, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore);
}

var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(pausedFrame);

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    PauseImage.Source = source;
    PauseImage.Visibility = Visibility.Visible;
});

_totalRecordedTime += result.RecordDuration;

在恢复录制时,可将图像源设置为 NULL 以将其隐藏。When you resume recording, you can set the source of the image to null and hide it.

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    PauseImage.Source = null;
    PauseImage.Visibility = Visibility.Collapsed;
});

await _mediaRecording.ResumeAsync();

请注意,在通过调用 StopWithResultAsync 停止视频时还可获得结果帧。Note that you can also get a result frame when you stop the video by calling StopWithResultAsync.

捕获音频Capture audio

使用上述用于捕获视频的相同技术,可将音频捕获快速添加到应用。You can quickly add audio capture to your app by using the same technique shown above for capturing video. 以下示例在应用程序数据文件夹中创建 StorageFileThe example below creates a StorageFile in the application data folder. 调用 PrepareLowLagRecordToStorageFileAsync 以初始化捕获会话,该会话在文件和 MediaEncodingProfile(本例中由 CreateMp3 静态方法生成)中传递。Call PrepareLowLagRecordToStorageFileAsync to initialize the capture session, passing in the file and a MediaEncodingProfile which is generated in this example by the CreateMp3 static method. 若要开始录制,请调用 StartAsyncTo begin recording, call StartAsync.

mediaCapture.RecordLimitationExceeded += MediaCapture_RecordLimitationExceeded;

var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.CreateFileAsync("audio.mp3", CreationCollisionOption.GenerateUniqueName);
_mediaRecording = await mediaCapture.PrepareLowLagRecordToStorageFileAsync(
        MediaEncodingProfile.CreateMp3(AudioEncodingQuality.High), file);
await _mediaRecording.StartAsync();

若要停止音频录制,请调用 StopAsyncCall StopAsync to stop the audio recording.

await _mediaRecording.StopAsync();

可多次调用 StartAsyncStopAsync 以录制多个音频文件。You can call StartAsync and StopAsync multiple times to record several audio files. 完成音频捕获后,调用 FinishAsync 以释放捕获会话并清理关联的资源。When you are done capturing audio, call FinishAsync to dispose of the capture session and clean up associated resources. 完成此调用后,必须重新调用 PrepareLowLagRecordToStorageFileAsync 以重新初始化捕获会话,然后才可 StartAsyncAfter this call, you must call PrepareLowLagRecordToStorageFileAsync again to reinitialize the capture session before calling StartAsync.

await _mediaRecording.FinishAsync();

检测系统的音频级别更改并做出响应Detect and respond to audio level changes by the system

自 Windows 10 版本 1803 起,应用可检测到系统何时降低其音频捕获和音频渲染流的音频级别或何时将其静音。Starting with Windows 10, version 1803, your app can detect when the system lowers or mutes the audio level of your app's audio capture and audio render streams. 例如,应用进入后台状态时,系统可能将应用的流设为静音。For example, the system may mute your app's streams when it goes into the background. AudioStateMonitor 类可用于注册以接收系统修改音频流的音量时出现的事件。The AudioStateMonitor class allows you to register to receive an event when the system modifies the volume of an audio stream. 通过调用 CreateForCaptureMonitoring 获取用于监视音频捕获流的 AudioStateMonitor 实例。Get an instance of AudioStateMonitor for monitoring audio capture streams by calling CreateForCaptureMonitoring. 通过调用 CreateForRenderMonitoring 获取用于监视音频渲染流的实例。Get an instance for monitoring audio render streams by calling CreateForRenderMonitoring. 针对系统更改相应流类别的音频时要通知的每个监视器的 SoundLevelChanged 事件,注册一个处理程序。Register a handler for the SoundLevelChanged event of each monitor to be notified when the audio for the corresponding stream category is changed by the system.

// Namespaces for monitoring audio state
using Windows.Media;
using Windows.Media.Audio;
AudioStateMonitor captureAudioStateMonitor;
AudioStateMonitor renderAudioStateMonitor;
captureAudioStateMonitor = AudioStateMonitor.CreateForCaptureMonitoring();
captureAudioStateMonitor.SoundLevelChanged += CaptureAudioStateMonitor_SoundLevelChanged; ;

renderAudioStateMonitor = AudioStateMonitor.CreateForRenderMonitoring();
renderAudioStateMonitor.SoundLevelChanged += RenderAudioStateMonitor_SoundLevelChanged; ;

在捕获流的 SoundLevelChanged 处理程序中,可查看 AudioStateMonitor 发件人的 SoundLevel 属性来确定新的音量。In the SoundLevelChanged handler for the capture stream, you can check the SoundLevel property of the AudioStateMonitor sender to determine the new sound level. 请注意:系统决不可让捕获流的音量降低或忽高忽低。Note that a capture stream should never be lowered, or "ducked", by the system. 系统仅可将其静音或切换回最大音量。It should only ever be muted or switched back to full volume. 如果音频流已静音,你可以停止正在进行的捕获。If the audio stream is muted, you can stop a capture in progress. 音频流还原到最大音量后,可再次启动捕获。If the audio stream is restored to full volume, you can start capturing again. 以下示例使用一些布尔类变量来跟踪应用当前是否正在捕获音频以及捕获是否因音频状态而停止。The following example uses some boolean class variables to track whether the app is currently capturing audio and if the capture was stopped due to the audio state change. 这些变量用于确定何时适合以编程方式停止或启动音频捕获。These variables are used to determine when it's appropriate to programmatically stop or start audio capture.

bool isCapturingAudio = false;
bool capturingStoppedForAudioState = false;
private void CaptureAudioStateMonitor_SoundLevelChanged(AudioStateMonitor sender, object args)
{
    switch (sender.SoundLevel)
    {
        case SoundLevel.Full:
            if(capturingStoppedForAudioState)
            {
                StartAudioCapture();
                capturingStoppedForAudioState = false;
            }  
            break;
        case SoundLevel.Muted:
            if(isCapturingAudio)
            {
                StopAudioCapture();
                capturingStoppedForAudioState = true;
            }
            break;
        case SoundLevel.Low:
            // This should never happen for capture
            Debug.WriteLine("Unexpected audio state.");
            break;
    }
}

以下代码示例演示了如何将 SoundLevelChanged 处理程序用于音频渲染。The following code example illustrates an implementation of the SoundLevelChanged handler for audio rendering. 根据应用方案以及正在播放的内容类型,你可能想要在音量忽高忽低时暂停音频播放。Depending on your app scenario, and the type of content you are playing, you may want to pause audio playback when the sound level is ducked. 若要详细了解如何处理媒体播放的音量更改,请参阅使用 MediaPlayer 播放音频和视频For more information on handling sound level changes for media playback, see Play audio and video with MediaPlayer.

private void RenderAudioStateMonitor_SoundLevelChanged(AudioStateMonitor sender, object args)
{
    if ((sender.SoundLevel == SoundLevel.Full) ||
  (sender.SoundLevel == SoundLevel.Low && !isPodcast))
    {
        mediaPlayer.Play();
    }
    else if ((sender.SoundLevel == SoundLevel.Muted) ||
         (sender.SoundLevel == SoundLevel.Low && isPodcast))
    {
        // Pause playback if we’re muted or if we’re playing a podcast and are ducked
        mediaPlayer.Pause();
    }
}