【HarmonyOS 6.0】Media Kit:细粒度控制屏幕捕获,详解图像填充模式C API

【HarmonyOS 6.0】Media Kit:细粒度控制屏幕捕获,详解图像填充模式C API

文章目录


在这里插入图片描述

1 -> 概述:从“能录”到“录得好”——Media Kit的战略性升级

HarmonyOS 6.0(API level 20)为开发者带来了一系列深刻影响用户体验的系统能力升级。在媒体领域,Media Kit(媒体服务)本次更新中最引人注目的变化之一,便是对屏幕捕获(Screen Capture)能力的精细化控制。长久以来,开发者可以轻松实现屏幕录制或共享,但当捕获源的宽高比与输出目标(如编码器输入、显示Surface)的宽高比不一致时,如何优雅地处理图像的适配问题,始终是一个挑战。

传统的解决方案往往需要开发者自行计算裁剪区域或添加黑边,过程繁琐且容易出错。HarmonyOS 6.0 精准地回应了这一痛点,通过在 native_avscreen_capture.h 头文件中新增的 OH_AVScreenCapture_StrategyForFillMode 接口,将图像填充模式的控制权交给了开发者。这一看似微小的API新增,实际上是Media Kit在屏幕捕获领域从“功能完备”走向“体验精细”的重要里程碑

本文将以此为切入点,从基础概念讲起,深入剖析这一新API的使用方法、底层原理,并通过一个完整的代码实战场景,向您展示如何在实际开发中灵活运用填充模式,以构建更专业、更具适应性的屏幕录制与共享应用。

2 -> 基础概念:理解屏幕捕获中的“画布”与“填充”

在深入代码之前,我们有必要先建立几个核心概念。这有助于理解我们即将操纵的API究竟在解决什么问题。

2.1 -> 捕获源与目标区域

  • 捕获源图像:这是指被录制的屏幕内容本身,它可以是一个完整的屏幕、一个窗口,甚至是一个指定的区域。它有其原始的分辨率宽高比
  • 目标区域:这是指屏幕捕获数据最终要呈现或编码到的“画布”。这个画布有它自己设定的输出分辨率。例如,您可能设定输出一个 1920x1080 的视频流,但用户的手机屏幕可能是 2340x1080 的细长比例。

2.2 -> 矛盾的焦点:宽高比不一致

当捕获源图像的比例(如手机屏幕的 19.5:9)与目标区域的输出比例(如标准视频的 16:9)不同时,就产生了冲突。我们无法将一张细长的图像完美地塞进一个较宽的矩形中而不做任何处理。这时,就需要“填充模式”来定义如何处理这种不一致。

2.3 -> 填充模式 (OH_AVScreenCapture_FillMode)

HarmonyOS 6.0 通过 OH_AVScreenCapture_FillMode 枚举为开发者提供了两种标准化的处理策略:

  • OH_SCREEN_CAPTURE_FILLMODE_CROP (裁剪模式):此模式优先填满整个目标区域。它会放大捕获源图像,直到其能够完全覆盖目标区域的每一点。由于宽高比不同,图像超出目标区域的部分(通常是上下或左右两边)将被裁剪掉。这种模式的优点是输出画面无黑边,视觉上饱满,缺点是会丢失部分边缘内容。适用于对画面完整性要求不高,但强调沉浸感的场景,如游戏直播、全屏视频录制。
  • OH_SCREEN_CAPTURE_FILLMODE_LETTERBOX (留边模式/信箱模式):此模式优先保持捕获源图像的完整内容。它会等比缩放图像,直到图像能完整地放入目标区域内。由于比例不同,图像无法填充的部分将以黑边填充。这种模式的优点是保留了源图像的全部信息,缺点是输出画面会出现黑边,影响整体观感。适用于对内容完整性要求高的场景,如应用演示、技术教程录制。
特性裁剪模式 (CROP)留边模式 (LETTERBOX)
核心逻辑图像放大至填满目标区域图像等比缩放至完全放入目标区域
输出效果画面满屏,无黑边,但边缘被裁切画面完整,但有黑边
内容完整性损失边缘内容保留全部内容
适用场景游戏录制、全屏视频、沉浸式分享应用教学、UI演示、内容展示

理解了这两种模式的区别,就掌握了我们即将配置的核心。

3 -> API详解:设置捕获策略的完整链路

本次新增的功能并非孤立存在,它是 OH_AVScreenCapture 捕获策略体系的一部分。要成功设置填充模式,需要理解并遵循一套完整的API调用链。

3.1 -> 核心数据结构:OH_AVScreenCapture_CaptureStrategy

在API version 20中,引入了一个关键对象——捕获策略 (OH_AVScreenCapture_CaptureStrategy)。它是一个配置集合,用于集中管理屏幕捕获的各种高级行为,其中就包括我们关注的填充模式。可以将其视为一个“配置清单”,在录屏启动前统一设置。

3.2 -> 核心API函数

  • OH_AVScreenCapture_CreateCaptureStrategy():创建策略对象。这是所有配置的第一步。
  • OH_AVScreenCapture_StrategyForFillMode(OH_AVScreenCapture_CaptureStrategy *strategy, OH_AVScreenCapture_FillMode mode)本次新增的核心函数。用于向策略对象设置填充模式。
    • 参数 strategy:指向之前创建的策略对象的指针。
    • 参数 mode:指定填充模式,即上面介绍的 OH_AVScreenCapture_FillMode 枚举值。
    • 返回值OH_AVSCREEN_CAPTURE_ErrCode,成功返回 AV_SCREEN_CAPTURE_ERR_OK
  • OH_AVScreenCapture_SetCaptureStrategy(struct OH_AVScreenCapture *capture, OH_AVScreenCapture_CaptureStrategy *strategy):将配置好的策略对象关联到具体的 OH_AVScreenCapture 实例上。此接口必须在录屏启动之前调用
  • OH_AVScreenCapture_ReleaseCaptureStrategy(OH_AVScreenCapture_CaptureStrategy* strategy):释放不再使用的策略对象,防止内存泄漏。

3.3 -> 调用流程

整个设置的逻辑流程非常清晰:

  1. 创建OH_AVScreenCapture 实例。
  2. 创建OH_AVScreenCapture_CaptureStrategy 实例。
  3. 配置策略:调用 OH_AVScreenCapture_StrategyForFillMode 设置你想要的填充模式。
  4. 关联策略:调用 OH_AVScreenCapture_SetCaptureStrategy 将配置好的策略挂载到录屏实例上。
  5. 初始化并启动录屏(如调用 OH_AVScreenCapture_InitOH_AVScreenCapture_StartScreenCapture)。
  6. 资源回收:在录屏结束后,先释放策略对象,再释放录屏实例。

4 -> 实战场景:构建一个可切换填充模式的屏幕录制工具

为了更直观地展示这一新特性的威力,我们构想一个实战场景:开发一款面向企业内训的应用演示录制工具。培训师可能录制两种类型的内容:

  • 场景A(录制代码编辑器):需要完整展示代码,不能有任何裁剪,以保证所有字符可见。此时应使用 留边模式
  • 场景B(录制应用操作演示):希望视频画面填满屏幕,让观众更专注于操作区域,可以接受边缘部分UI被轻微裁剪。此时应使用 裁剪模式

以下代码示例展示了如何在应用中通过一个简单的开关,动态配置并启动这两种模式的录屏。代码中包含了必要的错误处理和详细的注释。

4.1 -> 代码示例:灵活配置屏幕捕获的填充模式

#include<stdio.h>#include<multimedia/player_framework/native_avscreen_capture.h>// 错误处理辅助宏#defineCHECK_CAPTURE_RESULT(func, result)\do{\if((result)!= AV_SCREEN_CAPTURE_ERR_OK){\printf("Error: %s failed with code %d\n",(func),(result));\goto ERROR;\}\}while(0)voidStartScreenCaptureWithFillMode(OH_AVScreenCapture_FillMode mode){ OH_AVSCREEN_CAPTURE_ErrCode result;structOH_AVScreenCapture*capture =NULL; OH_AVScreenCapture_CaptureStrategy *strategy =NULL;// 1. 创建屏幕捕获实例 capture =OH_AVScreenCapture_Create();if(capture ==NULL){printf("Failed to create OH_AVScreenCapture instance.\n");return;}// 2. 创建捕获策略对象 strategy =OH_AVScreenCapture_CreateCaptureStrategy();if(strategy ==NULL){printf("Failed to create capture strategy.\n");goto ERROR;}// 3. ⭐核心步骤:根据传入的模式参数,设置填充模式策略// 假设我们通过外部参数 mode 来控制,mode 可以是:// - OH_SCREEN_CAPTURE_FILLMODE_CROP (裁剪模式)// - OH_SCREEN_CAPTURE_FILLMODE_LETTERBOX (留边模式) result =OH_AVScreenCapture_StrategyForFillMode(strategy, mode);CHECK_CAPTURE_RESULT("OH_AVScreenCapture_StrategyForFillMode", result);// 4. 将配置好的策略设置到捕获实例中// 注意:此接口必须在 Init 之前调用 result =OH_AVScreenCapture_SetCaptureStrategy(capture, strategy);CHECK_CAPTURE_RESULT("OH_AVScreenCapture_SetCaptureStrategy", result);// 5. 配置其他录屏参数 (OH_AVScreenCaptureConfig)// 这部分是常规操作,需要根据实际场景填充。// 例如设置音频、视频的采集和编码参数。 OH_AVScreenCaptureConfig config;// ... 初始化 config 结构体,设置分辨率、音频源等 ...// 注意:这里设置的目标输出分辨率,是应用填充模式的基准“画布”。// 假设我们设置目标视频输出为 1920x1080 (16:9)// config.videoCaptureInfo.videoFrameWidth = 1920;// config.videoCaptureInfo.videoFrameHeight = 1080;// ...// 初始化录屏实例 result =OH_AVScreenCapture_Init(capture, config);CHECK_CAPTURE_RESULT("OH_AVScreenCapture_Init", result);// 6. 设置必要的回调(如状态回调、错误回调)// result = OH_AVScreenCapture_SetStateCallback(...);// result = OH_AVScreenCapture_SetErrorCallback(...);// ...// 7. 启动录屏 result =OH_AVScreenCapture_StartScreenCapture(capture);if(result == AV_SCREEN_CAPTURE_ERR_OK){printf("Screen capture started successfully in %s mode.\n", mode == OH_SCREEN_CAPTURE_FILLMODE_CROP ?"CROP":"LETTERBOX");}else{printf("Failed to start screen capture.\n");goto ERROR;}// ... 录屏过程中的其他逻辑,如数据处理等 ...// 模拟录屏过程// sleep(60);// 8. 停止录屏 result =OH_AVScreenCapture_StopScreenCapture(capture);if(result == AV_SCREEN_CAPTURE_ERR_OK){printf("Screen capture stopped.\n");}// 9. 资源清理OH_AVScreenCapture_ReleaseCaptureStrategy(strategy);OH_AVScreenCapture_Release(capture);printf("Resources released.\n");return; ERROR:// 错误处理:清理已分配的资源if(strategy !=NULL){OH_AVScreenCapture_ReleaseCaptureStrategy(strategy);}if(capture !=NULL){OH_AVScreenCapture_Release(capture);}printf("Screen capture terminated due to error.\n");}// 使用示例:以裁剪模式启动录屏intmain(){printf("Starting screen capture with CROP mode...\n");StartScreenCaptureWithFillMode(OH_SCREEN_CAPTURE_FILLMODE_CROP);// 也可以切换到留边模式// printf("\nStarting screen capture with LETTERBOX mode...\n");// StartScreenCaptureWithFillMode(OH_SCREEN_CAPTURE_FILLMODE_LETTERBOX);return0;}

4.2 -> 代码深度解析

  1. 模块化设计 (StartScreenCaptureWithFillMode 函数):我们将核心逻辑封装成一个函数,接受 OH_AVScreenCapture_FillMode 作为参数。这使得代码可以非常方便地在两种模式间切换,体现了良好的可扩展性。
  2. 策略对象的生命周期管理:代码严格遵循了“创建-配置-关联-释放”的流程。特别需要注意的是,策略对象 必须在 OH_AVScreenCapture_Init 之前通过 OH_AVScreenCapture_SetCaptureStrategy 与捕获实例关联。这符合“策略先行”的设计原则,确保录屏引擎在启动前就知晓所有高级配置。
  3. 关键步骤的显式注释:在设置填充模式的代码行(步骤3),我们添加了详细注释,强调这是本次新增功能的核心,并解释了不同 mode 参数的含义。这有助于阅读者迅速定位到关键点。
  4. 健壮的错误处理:通过 CHECK_CAPTURE_RESULT 宏和 goto ERROR 标签,我们构建了一个清晰的错误处理流程。在任何API调用失败时,程序都会跳转到统一的位置进行资源清理,避免因中途失败导致的内存泄漏。
  5. 模拟真实场景:代码中预留了 OH_AVScreenCaptureConfig 的初始化部分,并特意指出该配置中的输出分辨率是应用填充模式的基准画布。这至关重要:填充模式正是为了解决“捕获源”与这个“目标输出分辨率”之间的比例冲突。例如,如果手机屏幕是2340x1080,而 config 中设置的目标输出是1920x1080,那么当捕获全屏时,两种填充模式就会产生上述的裁剪或留边效果。

5 -> 总结与展望:精细化控制,开启屏幕捕获新可能

HarmonyOS 6.0 在 Media Kit 中新增的捕获图像填充模式设置,虽只是一个函数,但其背后体现了系统对开发者需求的深刻洞察和对用户体验的极致追求。通过 OH_AVScreenCapture_StrategyForFillMode 接口,Harmonys将屏幕捕获的输出控制权真正交还给了开发者。

5.1 -> 核心价值回顾

  • 解决历史痛点:标准化地解决了捕获源与输出目标比例不一致时的适配难题,避免了开发者自行处理裁剪、拉伸或添加黑边的繁琐工作。
  • 提升应用质量:开发者可以根据应用的具体场景(如游戏录制 vs. 教程录制),灵活选择最合适的填充模式,从而提升最终产物的专业度和观感。
  • 架构清晰合理:通过引入 OH_AVScreenCapture_CaptureStrategy 策略对象,将各类高级配置集中管理,API设计清晰,易于扩展和维护。

5.2 -> 未来的可能性

本次更新仅仅是Media Kit持续演进的一个缩影。随着HarmonyOS的不断发展,我们可以期待更多类似的精细化控制API。例如:

  • 更丰富的填充模式:未来是否会增加如“拉伸填充”(忽略比例,强制填满)或“智能裁剪”(基于内容分析进行裁剪)等模式?
  • 动态切换能力:目前填充模式必须在录屏前配置。在更复杂的场景中,是否能在录屏过程中动态切换填充模式,以满足实时变化的需求?
  • 与AI能力的结合:结合HarmonyOS的AI能力,未来或许可以实现自动识别录制内容(是游戏还是文档),并智能推荐或自动切换最佳填充模式。

总而言之,HarmonyOS 6.0 Media Kit 的这次更新,为开发者构建高质量的屏幕捕获应用铺平了道路。掌握 OH_AVScreenCapture_StrategyForFillMode 的使用,将使您的应用在面对复杂多变的屏幕内容时,表现得更加从容和专业。


感谢各位大佬支持!!!
互三啦!!!

Read more

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

免责声明:用户因使用公众号内容而产生的任何行为和后果,由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任 **本文以攻防世界部分题为例进行演示,后续会对攻防世界大部分的web题目进行演示,如果你感兴趣请关注** 目录 一:Lottery 二:ics-05 三:总结 一:Lottery 打开后发现这个靶场加载异常缓慢,然后他还给了源码,我们先不看源码先熟悉一下这个网站是什么 这应该是一个类似猜数字游戏,选对7个号码即可得到相应奖励 然后注册 随便输入7个数字发现一个也没中,白费2元 然后我们随便点击这个网站的功能发现如果想要flag需要有相对应的余额 我们这会的思路就是利用bp抓包看看能不能修改我们的余额 好像成功了,我们试一试能不能换flag 居然说没有足够的钱,这个方法不行只要将页面上的数字修改只要刷新就会变回原来的余额 居然不能修改余额那就看看在猜数字的页面有没有突破口,发现其访问了api.php我们继续代码审计 看到如下核心代码,首先随机生成七位数字(random_win_nums)然后将其赋值给$win_number。随后关

By Ne0inhk
【魅影AI远程控制】:基于WebRTC+AI的智能远程控制解决方案

【魅影AI远程控制】:基于WebRTC+AI的智能远程控制解决方案

魅影AI远程控制:基于WebRTC+AI的智能远程控制解决方案 📖 前言 在移动互联网时代,远程控制技术已经成为企业IT支持、无障碍辅助、智能家居等领域的重要工具。传统的远程控制方案往往需要用户手动操作,效率低下。今天,我将为大家介绍一款革命性的魅影AI远程控制应用,它通过WebRTC实时通信和AI智能识别技术,实现了"语音指令→智能理解→自动执行"的完整闭环,让远程控制变得像对话一样简单。 🎯 项目概述 什么是魅影AI远程控制? 魅影AI远程控制是一款双端合一的Android应用,集成了远程控制、AI语音助手、OCR识别等多项前沿技术。它最大的特点是智能化:用户只需说出需求,AI就能理解意图并自动完成操作。 核心价值 传统远控:手动点击、滑动 → 繁琐、低效 AI远控:语音命令、智能识别、自动执行 → 简单、高效、智能 一句话描述: "说出你的需求,AI帮你完成" - 让远程控制像对话一样简单

By Ne0inhk
Cursor 2.2更新:可视化编辑器+Debug Mode,写前端的有福了

Cursor 2.2更新:可视化编辑器+Debug Mode,写前端的有福了

加我进AI讨论学习群,公众号右下角“联系方式” 文末有老金的 开源知识库地址·全免费 这两天Cursor连续放大招 12月10日,Cursor发布了2.2版本,主打Debug Mode。 12月11日,又发了个重磅更新:Browser可视化编辑器。 说实话,看到这个功能的时候,我愣了好几秒。 这不就是我之前一直想要的东西吗?点哪改哪,拖拽布局,AI直接改代码。 写前端的朋友,这波真的有福了。 可视化编辑器:点哪改哪 这是12月11日刚发布的功能,老金我觉得比Debug Mode还炸裂。 简单说就是:在Cursor里打开一个内置浏览器,显示你的网页,然后你可以直接在上面拖拽、点击、修改,AI自动帮你改代码。 拖拽式布局 以前改布局,你得: 1. 1. 打开浏览器看效果 2. 2. 切回代码改CSS/HTML 3. 3. 保存刷新看效果 4.

By Ne0inhk
cann-recipes-train 仓库深度解读:昇腾平台下 DeepSeek-R1 与 Qwen2.5 强化学习训练优化实践

cann-recipes-train 仓库深度解读:昇腾平台下 DeepSeek-R1 与 Qwen2.5 强化学习训练优化实践

cann-recipes-train 仓库深度解读:昇腾平台下 DeepSeek-R1 与 Qwen2.5 强化学习训练优化实践 前言 自 DeepSeek-R1 发布以来,大模型的强化学习(RL)训练掀起了新一轮的技术热潮。各大厂商与开源社区纷纷投入实践,持续探索更高效的 RL 训练体系。本文将基于 cann-recipes-train 仓库,解读两个实践样例:DeepSeek-R1 的 RL 训练优化实践样例、基于 verl 框架的 Qwen2.5 强化学习实践样例 cann-recipes-train 仓库全景解析:昇腾训练优化的"实战底座" 大模型训练拼效率的阶段,CANN 直接帮我们搞定了底层异构硬件适配、资源调度这些麻烦事,不用再从零研究 GPU 和 NPU 怎么协同,现有模型代码也不用大改就能对接,训

By Ne0inhk