仓颉媒体服务 Media Kit(Beta)开发指南:AVImageGenerator 视频缩略图获取 API 全解析

原创2026-10-15 13:19:491,354 阅读
文章标签:文档知识库

仓颉媒体服务 Media Kit(Beta)开发指南:AVImageGenerator 视频缩略图获取 API 全解析

Media Kit(媒体服务)是 OpenHarmony-仓颉 SDK 提供的音视频媒体能力套件,其中 ohos.multimedia.media 模块为开发者提供了一套简单且易于理解的接口,用于接入系统并获取视频资源的关键帧画面。本文以 Media Kit 参考文档 为主线,围绕 AVImageGenerator(视频缩略图获取) 这一核心功能,系统讲解从实例创建、数据源描述、帧查询选项到错误码排查的完整链路,并结合仓库内 API 参考 与 Media 错误码 文档给出可直接运行的仓颉代码示例。读完本文,你将能够在仓颉应用模板工程中实现“按时间点提取视频任意帧作为缩略图”的完整流程。

Media Kit 与 ohos.multimedia.media 模块概览

ohos.multimedia.media 是 Media Kit 中面向仓颉语言的媒体服务接口模块,归属于媒体子系统,涵盖音视频相关的媒体业务。当前版本(起始版本 22)下,该模块提供的常用功能为:

其能力分层清晰:createAVImageGenerator() 负责创建实例,AVImageGenerator 负责帧抓取与资源释放,AVFileDescriptor 描述数据源,PixelMapParams 描述输出图像规格,AVImageQueryOptions 决定取帧策略。各接口的系统能力归属如下:

接口 / 类 系统能力(SysCap)
createAVImageGenerator()、AVImageGenerator、PixelMapParams、AVImageQueryOptions SystemCapability.Multimedia.Media.AVImageGenerator
AVFileDescriptor SystemCapability.Multimedia.Media.Core

说明: Media Kit 当前标注为 Beta 特性,接口以“起始版本:22”为准。系统能力(SystemCapability)是判断接口在当前设备上是否可用的依据,具体可参考 系统能力使用指南。

开发前置准备

导入模块

所有相关接口均通过 Kit 导入语句引入:

import kit.MediaKit.*

示例代码中还会用到 kit.LocalizationKit.*(获取资源文件描述符)、kit.PerformanceAnalysisKit.*(Hilog 日志)以及 ohos.business_exception.BusinessException(业务异常捕获)。

权限声明

调用本模块接口需要申请以下权限(在 module.json5 中配置):

ohos.permission.MICROPHONE

若不需要访问麦克风场景,开发者应在配置文件中按实际需求声明;权限申请方式详见 访问控制开发指导。

示例工程与运行前提

API 文档中的仓颉示例并非完整程序,而是对应 API 的主要代码。若希望编译运行,需要将示例拷贝到仓颉模板工程中,具体流程参见 仓颉示例代码说明:

  • 示例代码首行带有 // index.cj 注释时,表示该示例可在仓颉模板工程的 index.cj 文件中编译运行;
  • 示例需要获取 Context 应用上下文时,需在仓颉模板工程的 main_ability.cj 文件中定义 Global 类并赋值,即通过 Global.abilityContext 访问上下文;
  • 获取当前应用沙箱路径可通过 UIAbilityContext 的 filesDir 属性。

main_ability.cj 中需要补充的 Global 类模板如下(节选自 开发说明):

// main_ability.cj 中定义
public class Global {
    public static var _abilityContext: Option<UIAbilityContext> = None
    public static var _windowStage: Option<WindowStage> = None
    public static prop abilityContext: UIAbilityContext {
        get() {
            match (_abilityContext) {
                case Some(context) => context
                case None => throw Exception("Global.abilityContext is not set")
            }
        }
    }
}

同时,仓颉 API 目前仅可在 Stage 模型下使用。

createAVImageGenerator():创建缩略图生成器

一切视频缩略图操作都从创建 AVImageGenerator 实例开始。接口签名如下:

public func createAVImageGenerator(): AVImageGenerator
  • 系统能力: SystemCapability.Multimedia.Media.AVImageGenerator
  • 起始版本: 22
  • 返回值: AVImageGenerator 实例
  • 异常: BusinessException,对应 Media 错误码,详见 Media 错误码:
错误码 ID 错误信息
5400101 No memory.

最小创建示例:

// 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)
}

AVFileDescriptor:音视频文件资源描述

AVFileDescriptor 用于描述音视频文件资源,其典型使用场景是:应用中的音频资源被连续存储在同一个文件中,需要根据偏移量(offset)和长度(length)进行定位播放或抓帧。

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
    )
}

字段说明

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

其中 offset 与 length 均为命名参数(!: 语法),可省略:

// 等价于 offset = 0, length = 文件中从偏移量开始的剩余字节
let desc = AVFileDescriptor(rawFd.fd)
// 或显式指定
let desc = AVFileDescriptor(rawFd.fd, offset: rawFd.offset, length: rawFd.length)

fd 的来源:getRawFd 与 FileIo.open

  • 预置资源(rawfile):通过 ResourceManager 的 getRawFd(path) 获取 resources/rawfile 目录下文件所在 HAP 的文件描述符,返回 RawFileDescriptor(内含 fd、offset、length 三个字段,与 AVFileDescriptor 一一对应)。注意:getRawFd 获取的 fd 使用完毕后需调用 closeRawFd 关闭,避免资源泄露。
  • 沙箱文件:通过 FileIo.open(path, mode) 打开应用沙箱路径或 URI,默认以 OpenMode.READ_ONLY 只读方式打开,返回值 File 对象提供句柄。

AVImageGenerator:视频缩略图获取类

AVImageGenerator 是本文的核心类,用于从视频资源中获取缩略图。调用其方法前,必须先通过 createAVImageGenerator() 构建实例。

public class AVImageGenerator {}

prop fdSrc:设置数据源

通过 fdSrc 属性将 AVFileDescriptor 设置为数据源:

public mut prop fdSrc: AVFileDescriptor

假设一个连续存储的媒体文件,地址偏移为 0、字节长度为 100,其文件描述为 AVFileDescriptor { fd = 资源句柄; offset = 0; length = 100; }。

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

该属性可能抛出 BusinessException,错误码包括:

错误码 ID 错误信息
5400101 No memory.
5400102 Operation not allowed.

func fetchFrameByTime():按时间点抓取视频帧

这是获取缩略图的核心方法:

public func fetchFrameByTime(timeUs: Int64, options: AVImageQueryOptions, param: PixelMapParams): PixelMap

参数说明:

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

返回值: PixelMap,即视频缩略图。PixelMap 是图像像素类,用于读取或写入图像数据以及获取图像信息,可将结果直接用于界面展示或后续图像处理。

异常(BusinessException):

错误码 ID 错误信息
5400101 No memory.
5400102 Operation not allowed.
5400106 Unsupported format.

调用示例(抓取第 0 微秒处的下一关键帧):

let timeUs = 0
let queryOption = AVImageQueryOptions.AvImageQueryNextSync
let param = PixelMapParams(width: 300, height: 300)
let pic = generator.fetchFrameByTime(timeUs, queryOption, param)

func release():释放资源

缩略图获取完成后,应显式释放 AVImageGenerator 占用的资源:

public func release(): Unit

该方法可能抛出 BusinessException(错误码 5400101 No memory.)。

PixelMapParams:缩略图输出格式参数

PixelMapParams 用于描述输出缩略图的尺寸规格:

public class PixelMapParams {
    public var width: Int32
    public var height: Int32
    public init(width!: Int32 = -1, height!: Int32 = -1)
}
字段 类型 默认值 说明
width Int32 -1 输出的缩略图宽度。应保证大于 0 且不大于原始视频宽度,否则返回的缩略图不会进行缩放。
height Int32 -1 输出的缩略图高度。应保证大于 0 且不大于原始视频高度,否则返回的缩略图不会进行缩放。

width 与 height 均为命名参数,可只指定其一:

// 仅指定宽度
let param = PixelMapParams(width: 320)
// 指定宽高
let param = PixelMapParams(width: 300, height: 300)

AVImageQueryOptions:时间点与视频帧的对应关系

在获取视频缩略图时,传入的时间点与实际取得的视频帧所在时间点不一定相等,因此需要指定二者的对应关系。该枚举实现了 Equatable<AVImageQueryOptions> 与 ToString 父类型,并重载了 ==、!= 运算符及 toString() 方法:

public enum AVImageQueryOptions <: Equatable<AVImageQueryOptions> & ToString {
    | AvImageQueryNextSync
    | AvImageQueryPreviousSync
    | AvImageQueryClosestSync
    | AvImageQueryClosest
    | ...
}
枚举值 语义
AvImageQueryNextSync 选取传入时间点或之后的关键帧。
AvImageQueryPreviousSync 选取传入时间点或之前的关键帧。
AvImageQueryClosestSync 选取离传入时间点最近的关键帧。
AvImageQueryClosest 选取离传入时间点最近的帧,该帧不一定是关键帧。

选帧策略建议: 若追求解码效率与画面稳定,优先使用带 Sync(关键帧)语义的选项;若追求时间点精确对齐,可选用 AvImageQueryClosest(非关键帧)。实际编码中,视频关键帧间隔(GOP)直接决定取帧结果与请求时间点的偏差,开发者应根据视频源特性选择策略。

完整实战示例:从预置视频中抓取缩略图

将以下代码放入仓颉模板工程的 index.cj(资源文件 trailer.mp4 放置于 resources/rawfile 目录,并替换为实际路径):

// 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}")
}

执行流程拆解:

  1. 通过 createAVImageGenerator() 创建实例;
  2. 通过 Global.abilityContext.resourceManager.getRawFd("trailer.mp4") 获取预置资源的 RawFileDescriptor(fd / offset / length);
  3. 将其转换为 AVFileDescriptor 并赋值给 generator.fdSrc 设置数据源;
  4. 指定时间点(timeUs = 0)、查询策略(AvImageQueryNextSync)与输出规格(300 × 300),调用 fetchFrameByTime 得到 PixelMap 缩略图;
  5. 调用 release() 释放资源。

若数据源为应用沙箱文件,可将第 2~3 步替换为:

// 沙箱路径可通过 UIAbilityContext.filesDir 获取
let file = FileIo.open(path, mode: FileIo.OpenMode.READ_ONLY)
let desc = AVFileDescriptor(file.fd)
generator.fdSrc = desc

Media 错误码排查指南

本模块错误码均为 BusinessException 抛出,下表汇总了 Media 错误码 中的特有错误码(通用错误码请参考 通用错误码说明):

错误码 ID 错误信息 错误描述 可能原因 处理步骤
5400101 No memory. 分配内存失败 实例数量超过 16 个;new 或 malloc 流程失败导致空指针 销毁当前实例并重新创建,若重新创建失败则停止相关操作
5400102 Operation not allowed. 当前操作不允许 当前状态机不支持此操作 确认当前状态是否支持该操作,将实例切换到正确状态
5400103 I/O error. 出现 IO 错误 媒体与其他模块(图形、音频、网络、HDI、相机)的数据交互发生问题 确认网络是否通畅,销毁并重新创建实例
5400104 Operation timeout. 操作超时 网络超时(默认 15 秒,从开始缓存的事件上报后计时);访问其他模块超时 确认网络通畅;销毁并重新创建实例
5400105 Service died. 播放服务死亡 播放服务死亡 销毁当前实例并重新创建
5400106 Unsupported format. 不支持的规格 不支持的文件或格式 切换为支持的规格
5400107 Audio interrupted. 音频焦点冲突导致录制失败 有其他进程占用音频焦点 停止其他进程占用后重新创建
5411001 Can not find host. 解析或链接服务端地址错误 链接地址错误;地址解析失败 更换正确的服务端地址
5411002 Connection time out. 网络连接超时 网络异常 确认网络通畅;销毁并重新创建实例
5411003 NetWork abnormal. 网络异常导致的数据或链路异常 网络异常 销毁并重新创建实例
5411004 NetWork unavailable. 网络被禁用 网络被禁用 确认网络是否被禁用;销毁并重新创建实例
5411005 No permission. 无访问权限 无访问权限 确认访问权限;销毁并重新创建实例
5411006 Network access denied. 客户端请求参数错误或超出处理能力 请求参数错误或超出处理能力 确认请求参数是否正常;销毁并重新创建实例
5411007 Cannot find available network resources. 无可用网络资源 链接服务端地址异常 确认链接地址正常;销毁并重新创建实例
5411008 SSL client cert needed. SSL 客户端不可信,服务端校验客户端证书失败 未携带证书、证书不合法、证书过期 确认 SSL 证书正常;销毁并重新创建实例
5411009 SSL connection failed. SSL 链接失败 SSL 链接失败 确认 SSL 链接是否失效;销毁并重新创建实例
5411010 SSL server cert needed. SSL 服务端不可信,客户端校验服务端证书失败 未携带证书、证书不合法、证书过期 确认 SSL 证书正常;销毁并重新创建实例
5411011 Unsupportted request. 客户端请求参数错误或超出处理能力 请求参数错误或超出处理能力 确认请求参数正常;销毁并重新创建实例

其中与视频缩略图获取直接相关的错误码为 5400101、5400102、5400106:内存不足时检查实例数量(上限 16 个);Operation not allowed 时检查状态机与操作时序;Unsupported format 时确认视频文件格式与编码规格是否受支持。

最佳实践与注意事项

  • 资源句柄独占: fd 传给 AVImageGenerator 后,禁止再通过该句柄做读写,也不要将同一句柄同时传给多个 AVPlayer / AVMetadataExtractor / AVImageGenerator / AVTranscoder,避免竞争导致缩略图数据异常。
  • 及时释放: 抓帧完成后调用 release();通过 getRawFd 获取的 fd 在不再使用时调用 closeRawFd(path) 关闭,防止资源泄露。
  • 合理设置输出尺寸: PixelMapParams 的宽高应大于 0 且不大于原始视频宽高,否则不会缩放;同时留意 PixelMap 序列化大小限制(最大 128MB,大小约为宽 × 高 × 每像素字节数),过大尺寸可能导致送显失败。
  • 选帧策略按需取舍: 需要快速返回且对时间精度要求不高时优先选择关键帧选项(AvImageQueryNextSync 等);需要精确对齐指定时间点时选择 AvImageQueryClosest。
  • 异常兜底: 所有媒体接口调用都应使用 try-catch (e: BusinessException) 包裹,并结合错误码进行差异化处理(如内存不足时销毁重建、格式不支持时切换规格)。
  • 示例工程校验: 需要 Context 的示例必须在 main_ability.cj 中配置 Global 类;沙箱文件路径通过 filesDir 获取,具体模板参见 仓颉示例代码说明。

至此,从 createAVImageGenerator() 创建实例、AVFileDescriptor 描述数据源、AVImageQueryOptions 确定取帧策略、fetchFrameByTime 抓取帧画面,到 release() 释放资源与错误码排查,一条完整的视频缩略图获取链路已经全部打通,可直接应用于仓颉应用的媒体预览、视频列表封面等场景。

登录后查看全文
CangjieCorpus