仓颉语言接入 ohos.multimedia.media 媒体服务:AVImageGenerator 视频缩略图获取实战指南

原创2026-10-15 13:21:351,336 阅读
文章标签:文档知识库

仓颉语言接入 ohos.multimedia.media 媒体服务:AVImageGenerator 视频缩略图获取实战指南

导读

ohos.multimedia.media(媒体服务)是 OpenHarmony 媒体子系统的核心仓颉 API 模块,为开发者提供一套简单且易于理解的接口,方便应用接入系统媒体资源。本指南聚焦其中与视频缩略图获取强相关的能力——AVImageGenerator 视频缩略图生成器,系统讲解从创建实例、描述媒体文件、按时间点抓帧到释放资源的完整调用链,并结合 CangjieCorpus 仓库中的错误码文档与关联 Kit 源码,帮助读者在仓颉模板工程中快速落地"从任意时间点截取视频帧"的实战方案。

一、模块概览:媒体子系统与 AVImageGenerator 的定位

媒体子系统包含音视频相关媒体业务,ohos.multimedia.media 模块为开发者提供接入系统媒体资源的能力。在仓颉侧,该模块当前以 Beta 特性 形式提供(见 Media Kit 模块说明),其中与本文主题直接相关的常用功能是:

  • 获取视频缩略图(AVImageGenerator)

AVImageGenerator 是一个典型的同步抓帧器:开发者向它描述一段媒体文件(文件句柄 + 偏移量 + 长度),指定目标时间点与取帧策略,即可获得对应的 PixelMap 缩略图。这一能力在视频列表封面、视频剪辑预览、短视频应用等场景中非常实用。

二、开发前置准备

2.1 导入模块

在仓颉代码中通过 Kit 导入方式引入媒体能力:

import kit.MediaKit.*

Kit 封装了同一 Kit 下各接口模块,开发者通过导入 MediaKit 即可使用 AVImageGenerator、AVFileDescriptor、PixelMapParams、AVImageQueryOptions 等接口(关于 Kit 导入机制的说明可参考 开发说明)。

2.2 权限列表

调用本模块接口需要申请权限:

ohos.permission.MICROPHONE

需要在应用配置文件(如 module.json5)中声明该权限,并遵守应用运行时权限申请流程。

2.3 示例工程使用说明

文档中的 API 示例代码遵循以下约定(详见仓颉示例代码说明):

  • 若示例代码首行有 // index.cj 注释,表示该示例可在仓颉模板工程的 index.cj 文件中直接编译运行;
  • 若示例需获取 Context 应用上下文,需在仓颉模板工程中的 main_ability.cj 文件中进行配置;
  • 获取当前应用沙箱所在路径可通过 UIAbilityContext.filesDir 获取。

三、核心调用链总览

视频缩略图获取的完整生命周期包含四个步骤:

  1. 创建实例:调用 createAVImageGenerator() 构建 AVImageGenerator;
  2. 描述数据源:构造 AVFileDescriptor 并赋给 generator.fdSrc;
  3. 按时间抓帧:调用 fetchFrameByTime() 获取 PixelMap 缩略图;
  4. 释放资源:调用 release() 释放底层资源。

下面逐一展开。

四、创建实例:func createAVImageGenerator()

public func createAVImageGenerator(): AVImageGenerator
  • 功能:创建 AVImageGenerator 实例。
  • 系统能力:SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本:22

返回值

类型 说明
AVImageGenerator 返回 AVImageGenerator 实例。

异常

错误码 ID 错误信息
5400101 No memory.

示例(可在 index.cj 中编译运行)

// index.cj

import kit.MediaKit.*
import kit.PerformanceAnalysisKit.*
import ohos.business_exception.BusinessException

try {
    let generator = createAVImageGenerator()
} catch (e: BusinessException) {
    Hilog.error(0, "AppLogCj", e.message)
}

五、描述媒体数据源:class AVFileDescriptor

AVFileDescriptor 是音视频文件资源描述类型,对应一种特殊资源的播放方式:当应用中的音频/视频资源被连续存储在同一个文件中时,需要根据偏移量和长度进行播放(或抓帧)。

public class AVFileDescriptor {
    public var fd: Int32
    public var offset: Int64
    public var length: Int64
    public init(
        fd: Int32,
        offset!: Int64 = 0,
        length!: Int64 = -1
    )
}
  • 系统能力:SystemCapability.Multimedia.Media.Core
  • 起始版本:22

5.1 var fd(资源句柄)

public var fd: Int32
  • 功能:资源句柄。
  • 类型:Int32
  • 读写能力:可读写

该句柄有两种典型获取方式:

  • 通过 getRawFd 获取 HAP 内置 rawfile 资源的文件描述符(返回 RawFileDescriptor,其包含 fd、offset、length 三个字段);
  • 通过 open 打开应用沙箱内的文件获得句柄(默认以 OpenMode.READ_ONLY 只读方式打开)。

5.2 var offset(资源偏移量)

public var offset: Int64
  • 功能:资源偏移量,默认值为 0。
  • 类型:Int64
  • 读写能力:可读写

需要基于预置资源的信息输入,非法值会造成音视频资源解析错误。

5.3 var length(资源长度)

public var length: Int64
  • 功能:资源长度,默认值为文件中从偏移量开始的剩余字节。
  • 类型:Int64
  • 读写能力:可读写

需要基于预置资源的信息输入,非法值会造成音视频资源解析错误。

5.4 init(Int32, Int64, Int64)

public init(
    fd: Int32,
    offset!: Int64 = 0,
    length!: Int64 = -1
)

参数说明

参数名 类型 必填 默认值 说明
fd Int32 是 - 资源句柄,通过 getRawFd 获取,也可以通过 open 获取。
offset Int64 否 0 命名参数。 资源偏移量,需要基于预置资源的信息输入,非法值会造成音视频资源解析错误。
length Int64 否 -1 命名参数。 资源长度,默认值为文件中从偏移量开始的剩余字节,需要基于预置资源的信息输入,非法值会造成音视频资源解析错误。

六、抓帧核心类:class AVImageGenerator

public class AVImageGenerator {}
  • 功能:视频缩略图获取类,用于从视频资源中获取缩略图。在调用 AVImageGenerator 的方法前,需要先通过 createAVImageGenerator() 构建一个 AVImageGenerator 实例。
  • 系统能力:SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本:22

6.1 prop fdSrc(媒体文件描述)

public mut prop fdSrc: AVFileDescriptor
  • 功能:媒体文件描述,通过该属性设置数据源。
  • 类型:AVFileDescriptor
  • 读写能力:可读写
  • 系统能力:SystemCapability.Multimedia.Media.AVMetadataExtractor

使用示例:假设一个连续存储的媒体文件,地址偏移为 0、字节长度为 100,则其文件描述为:

AVFileDescriptor { fd = 资源句柄; offset = 0; length = 100; }

说明(重要)

将资源句柄(fd)传递给 AVImageGenerator 实例之后,不允许通过该资源句柄再执行其他读写操作,包括但不限于将同一个资源句柄传递给多个 AVPlayer/AVMetadataExtractor/AVImageGenerator/AVTranscoder。同一时间通过同一个资源句柄读写文件时存在竞争关系,将导致视频缩略图数据获取异常。

异常

  • BusinessException:错误码如下表。
错误码 ID 错误信息
5400101 No memory.
5400102 Operation not allowed.

6.2 func fetchFrameByTime(Int64, AVImageQueryOptions, PixelMapParams)

public func fetchFrameByTime(timeUs: Int64, options: AVImageQueryOptions, param: PixelMapParams): PixelMap
  • 功能:获取视频缩略图。
  • 系统能力:SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本:22

参数说明

参数名 类型 必填 默认值 说明
timeUs Int64 是 - 需要获取的缩略图在视频中的时间点,单位为微秒(μs)。
options AVImageQueryOptions 是 - 需要获取的缩略图时间点与视频帧的对应关系。
param PixelMapParams 是 - 需要获取的缩略图的格式参数。

返回值

类型 说明
PixelMap 视频缩略图。

返回的 PixelMap 是图像像素类,可用于读取或写入图像数据以及获取图像信息,例如进一步交给 Image Kit 进行编码保存(注意其序列化大小存在上限,见 Image Kit 文档说明)。

异常

  • BusinessException:错误码如下表。
错误码 ID 错误信息
5400101 No memory.
5400102 Operation not allowed.
5400106 Unsupported format.

完整示例(可在 index.cj 中编译运行)

// index.cj

import kit.MediaKit.*
import kit.LocalizationKit.*
import ohos.business_exception.BusinessException
import kit.PerformanceAnalysisKit.Hilog

try {
    let timeUs = 0
    let queryOption = AVImageQueryOptions.AvImageQueryNextSync
    let param = PixelMapParams(width: 300, height: 300)
    let generator = createAVImageGenerator()
    let abilityContext = Global.abilityContext // 此处需手动配置模板,获取Context上下文。上下文获取方式请参见使用说明。
    let rawFd = abilityContext.resourceManager.getRawFd("trailer.mp4")    // 请替换您的资源路径,获取文件路径参考本文使用说明
    generator.fdSrc = AVFileDescriptor(rawFd.fd, offset: rawFd.offset, length: rawFd.length)
    let pic = generator.fetchFrameByTime(timeUs, queryOption, param)
    generator.release()
} catch (e: BusinessException) {
    Hilog.info(0, "test", "${e.message}")
}

6.3 func release()

public func release(): Unit
  • 功能:释放资源。
  • 系统能力:SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本:22

异常

  • BusinessException:错误码如下表。
错误码 ID 错误信息
5400101 No memory.

示例(可在 index.cj 中编译运行)

// index.cj

import kit.MediaKit.*
import kit.LocalizationKit.*
import kit.PerformanceAnalysisKit.*
import ohos.business_exception.BusinessException

try {
    let timeUs = 0
    let queryOption = AVImageQueryOptions.AvImageQueryNextSync
    let param = PixelMapParams(width: 300, height: 300)
    let generator = createAVImageGenerator()
    let abilityContext = Global.abilityContext // 此处需手动配置模板,获取Context上下文。上下文获取方式请参见使用说明。
    let rawFd = abilityContext.resourceManager.getRawFd("trailer.mp4")
    generator.fdSrc = AVFileDescriptor(rawFd.fd, offset:rawFd.offset, length:rawFd.length)
    let pic = generator.fetchFrameByTime(timeUs, queryOption, param)
    generator.release()
} catch (e: BusinessException) {
    Hilog.error(0, "AppLogCj", e.message)
}

release() 是实例生命周期的收尾动作,与 createAVImageGenerator() 成对使用;尤其在反复创建实例、频繁抓帧的场景下,及时释放可避免句柄与内存资源占用。

七、输出格式参数:class PixelMapParams

PixelMapParams 用于描述获取视频缩略图时输出缩略图的格式参数。

public class PixelMapParams {
    public var width: Int32
    public var height: Int32
    public init(width!: Int32 = -1, height!: Int32 = -1)
}
  • 系统能力:SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本:22

7.1 var width / var height

public var width: Int32
public var height: Int32
  • 功能:
    • width:输出的缩略图宽度,应保证大于 0 且不大于原始视频宽度,否则返回的缩略图不会进行缩放;
    • height:输出的缩略图高度,应保证大于 0 且不大于原始视频高度,否则返回的缩略图不会进行缩放。
  • 类型:Int32
  • 读写能力:可读写

7.2 init(Int32, Int32)

public init(width!: Int32 = -1, height!: Int32 = -1)

参数说明

参数名 类型 必填 默认值 说明
width Int32 否 -1 命名参数。 输出的缩略图宽度。应保证大于 0 且不大于原始视频宽度,否则返回的缩略图不会进行缩放。
height Int32 否 -1 命名参数。 输出的缩略图高度。应保证大于 0 且不大于原始视频高度,否则返回的缩略图不会进行缩放。

八、取帧策略枚举:enum AVImageQueryOptions

在获取视频缩略图时,传入的时间点与实际取得的视频帧所在时间点不一定相等,因此需要指定传入时间点与实际取得的视频帧的时间关系。AVImageQueryOptions 即用于描述这一对应关系。

public enum AVImageQueryOptions <: Equatable<AVImageQueryOptions> & ToString {
    | AvImageQueryNextSync
    | AvImageQueryPreviousSync
    | AvImageQueryClosestSync
    | AvImageQueryClosest
    | ...
}
  • 系统能力:SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本:22

父类型

  • Equatable<AVImageQueryOptions>
  • ToString

8.1 枚举取值语义

取值 功能
AvImageQueryClosest 表示选取离传入时间点最近的帧,该帧不一定是关键帧。
AvImageQueryClosestSync 表示选取离传入时间点最近的关键帧。
AvImageQueryNextSync 表示选取传入时间点或之后的关键帧。
AvImageQueryPreviousSync 表示选取传入时间点或之前的关键帧。

实际应用中,若追求"又快又稳"的封面图,通常选用 AvImageQueryNextSync 或 AvImageQueryClosestSync(只取关键帧,解码开销小、成功率高);若对时间点精度要求高、需要逐帧呈现画面内容,则可选用 AvImageQueryClosest。

8.2 运算符与字符串化

枚举通过实现 Equatable<AVImageQueryOptions> 与 ToString 提供了三个成员方法:

public operator func ==(other: AVImageQueryOptions): Bool
public operator func !=(other: AVImageQueryOptions): Bool
public func toString(): String
  • ==(other):比较两个 AVImageQueryOptions 是否相等,相等返回 true,否则返回 false;
  • !=(other):比较两个 AVImageQueryOptions 是否不等,不等返回 true,否则返回 false;
  • toString():返回 AVImageQueryOptions 的字符串表示,便于日志输出与调试。

九、异常与错误码速查

ohos.multimedia.media 相关接口抛出的 BusinessException 对应 Media 特有错误码,完整定义见 Media 错误码。其中与 AVImageGenerator 直接相关的错误码如下:

9.1 5400101 内存分配失败(No memory.)

  • 可能原因:① 实例数量超过 16 个;② new 或 malloc 流程失败导致空指针。
  • 处理步骤:销毁当前实例并重新创建;如果重新创建失败,则停止相关操作。

9.2 5400102 当前状态机不支持此操作(Operation not allowed.)

  • 可能原因:当前状态机不支持该操作。
  • 处理步骤:确认当前状态是否支持当前操作,把实例切换到正确的状态后再执行正确操作。

9.3 5400106 不支持的规格(Unsupported format.)

  • 可能原因:不支持的文件或格式。
  • 处理步骤:当前使用的格式规格不支持,需切换为支持的规格。

除上述特有错误码外,通用错误码请参考通用错误码说明文档。

十、数据源获取路径深入:rawfile 与沙箱文件

前文示例通过 abilityContext.resourceManager.getRawFd("trailer.mp4") 获取内置资源的句柄,这是最常用的数据源获取方式。围绕这一环节,仓库中相关 Kit 提供了两类路径:

方式一:rawfile 内置资源

  • getRawFd(String):获取 resources/rawfile 目录下 rawfile 文件所在 HAP 的文件描述符,返回 RawFileDescriptor(含 fd、offset、length 三字段,恰好与 AVFileDescriptor 一一对应,可直接透传);
  • 注意:getRawFd 获取的 fd 使用完毕后需调用 closeRawFd 关闭,避免资源泄露。

方式二:应用沙箱文件

  • 先通过 UIAbilityContext.filesDir 取得应用沙箱目录路径,再通过 open(path, mode) 打开文件获取 File 对象及对应句柄,之后填充 AVFileDescriptor 的 fd、offset、length 字段。

十一、实战要点汇总

  1. 生命周期完整:createAVImageGenerator() → 设置 fdSrc → fetchFrameByTime() → release(),四步缺一不可;
  2. 时间单位:fetchFrameByTime 的 timeUs 单位为微秒,如取视频开头帧传入 0 即可;
  3. 输出尺寸:PixelMapParams 的宽高需大于 0 且不超过原始视频宽高,否则不缩放;示例中 width: 300, height: 300 即为典型的封面缩略图尺寸;
  4. fd 独占性:句柄传给 AVImageGenerator 后不得再用于其他读写或传给其他媒体组件,否则可能因竞争导致缩略图数据异常;
  5. 异常兜底:所有调用均建议使用 try/catch 捕获 BusinessException,并按错误码(5400101/5400102/5400106)执行销毁重建或规格切换策略;
  6. 工程落地:示例代码需放入仓颉模板工程的 index.cj,涉及 Global.abilityContext 的需在 main_ability.cj 中配置 Context 上下文,具体可参考仓颉示例代码说明。

通过以上步骤,开发者即可在仓颉应用中稳定获取视频任意时间点的缩略图,为视频列表封面、预览封面等功能提供统一的实现范式。

登录后查看全文
CangjieCorpus