UWP平台录屏与截屏技术需求:实现逐帧采集转视频
在UWP平台实现屏幕录制/截屏并合成视频
嘿,我来帮你搞定UWP里的屏幕录制和截屏转视频的需求!下面是一步步的实现方案,都是用UWP原生API搞定的,不用依赖第三方库,直接上手就能用。
1. 先搞定权限配置
屏幕录制需要系统授权,首先得在Package.appxmanifest里添加必要的权限声明:
<Capabilities> <Capability Name="internetClient" /> <DeviceCapability Name="microphone" /> <!-- 可选,需要录声音就加 --> <uap:Capability Name="screenRecording" /> <!-- 核心的屏幕录制权限 --> </Capabilities>
另外,第一次启动时要主动向用户请求权限,不然会直接失败:
var accessStatus = await MediaCapture.RequestAccessAsync(MediaCaptureAccessKind.Video); if (accessStatus != MediaCaptureAccessStatus.Allowed) { // 这里提示用户开启权限,或者做容错处理 }
2. 初始化屏幕捕获会话
用MediaCapture类来建立和屏幕设备的连接,这是所有操作的基础:
private MediaCapture _mediaCapture; private bool _isRecording = false; private async Task InitializeMediaCaptureAsync() { _mediaCapture = new MediaCapture(); // 获取屏幕设备组 var screenDeviceGroups = await MediaCapture.FindAllVideoDeviceGroupsAsync(VideoDeviceGroupType.Screen); if (screenDeviceGroups.Count == 0) { throw new Exception("找不到屏幕捕获设备"); } // 获取屏幕视频设备ID var screenVideoDevices = await MediaCapture.FindAllVideoDevicesAsync(VideoDeviceGroupType.Screen); if (screenVideoDevices.Count == 0) { throw new Exception("找不到屏幕视频设备"); } var initSettings = new MediaCaptureInitializationSettings { SourceGroup = screenDeviceGroups[0], SharingMode = MediaCaptureSharingMode.ExclusiveControl, StreamingCaptureMode = StreamingCaptureMode.Video, // 如果要录声音就改成AudioAndVideo VideoDeviceId = screenVideoDevices[0].Id }; await _mediaCapture.InitializeAsync(initSettings); }
3. 两种实现路径:直接录制VS手动抓帧合成
路径一:直接录制为视频(推荐,高效省心)
如果不需要单独处理每一帧,直接让系统帮你完成录制和编码,这是效率最高的方式:
// 开始录制 private async Task StartRecordingAsync() { if (_isRecording) return; // 保存到视频库,文件名自动避免重复 var outputFile = await KnownFolders.VideosLibrary.CreateFileAsync("ScreenRecord.mp4", CreationCollisionOption.GenerateUniqueName); // 选择编码格式,这里用1080P的MP4 var encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p); await _mediaCapture.StartRecordToStorageFileAsync(encodingProfile, outputFile); _isRecording = true; } // 停止录制 private async Task StopRecordingAsync() { if (!_isRecording) return; await _mediaCapture.StopRecordAsync(); _isRecording = false; // 录制完成后,outputFile就是生成的视频文件,可以做后续处理 }
路径二:手动逐帧截屏再合成视频(适合需要自定义处理帧的场景)
如果必须对每一帧做滤镜、裁剪等自定义操作,就先抓帧再手动合成:
// 捕获单帧画面 private async Task<SoftwareBitmap> CaptureSingleFrameAsync() { using (var photoCapture = await _mediaCapture.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8))) { var captureResult = await photoCapture.CaptureAsync(); return captureResult.Frame.SoftwareBitmap; } } // 将收集到的帧合成视频 private async Task ComposeFramesToVideoAsync(List<SoftwareBitmap> frames, StorageFile outputFile) { var composition = new MediaComposition(); var frameDuration = TimeSpan.FromSeconds(1.0 / 30); // 设置帧率为30fps foreach (var frame in frames) { // 把帧保存为临时PNG文件(MediaClip需要文件源) var tempFrameFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("tempFrame.png", CreationCollisionOption.GenerateUniqueName); using (var stream = await tempFrameFile.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); encoder.SetSoftwareBitmap(frame); await encoder.FlushAsync(); } // 创建视频片段并添加到合成队列 var clip = await MediaClip.CreateFromImageFileAsync(tempFrameFile, frameDuration); composition.Clips.Add(clip); } // 渲染合成视频到文件 await composition.RenderToFileAsync(outputFile, MediaTrimmingPreference.Fast); }
一些关键注意事项
- 记得处理异常:比如权限被拒绝、设备初始化失败、文件保存失败等情况,给用户友好提示
- 低功耗设备上,手动合成视频可能会有性能瓶颈,优先用直接录制的方式
- 如果要录制声音,记得在初始化
MediaCapture时把StreamingCaptureMode设为AudioAndVideo,并确保麦克风权限已申请
内容的提问来源于stack exchange,提问作者hmak.soft
相关产品推荐
相关产品推荐

