项目简介:ffmpeg-for-HarmonyOS 是一个为纯血鸿蒙(HarmonyOS NEXT / OpenHarmony)打造的音视频基础库。它不仅打通了 FFmpeg 的全套音视频处理能力,还原生接入了鸿蒙的硬解/硬编接口,提供 HAR 和 C++ SDK 双形态。

项目:ffmpeg-for-HarmonyOS
当前版本:v0.2.2
定位:面向 HarmonyOS NEXT / OpenHarmony 的音视频基础库,不是一个成品播放器 App。

1. 开发背景与初衷

去年做鸿蒙音视频开发时,我遇到的最直接的问题是:找不到一个能直接在纯血鸿蒙上跑起来的完整 FFmpeg 库。

网上能搜到的方案大致有几类:

  • 直接拿 Linux/Android 的 .so 改后缀,ABI 和系统库对不上;
  • 只编译了 FFmpeg 的一两个组件,缺封装、缺重采样、缺滤镜;
  • 只有示例代码,没有可复现的双 ABI 构建,也没有 release 包;
  • 能跑软解,但没有接入鸿蒙的原生硬件 OH_AudioCodec / OH_VideoDecoder,高负荷作业下容易导致发热。

前两类是“编译不过”,后两类是“编译过了但不好用”。对于真正要做音视频功能的人来说,缺的不是一份 FFmpeg 源码,而是一套能和鸿蒙系统能力对接、能被工程化集成的基座。

这也是项目加入硬解的原因。

第一,纯软解在移动设备上的成本很直接。FFmpeg 的软件解码会持续占用 CPU,高分辨率、高码率视频尤其明显,设备发热、耗电、降频都会跟着来。对于播放器、转码器、相机处理这类场景,只靠软解很难长期维持体验。

第二,市面上不少同类开源产品,重点仍然放在“把 FFmpeg 编过鸿蒙”,对鸿蒙原生的硬件解码能力支持不完整。OH_AudioCodec、OH_VideoDecoder 这些系统接口和 FFmpeg 的 AVCodecContext 不是天然打通的,需要额外的解码器封装、Surface 绑定、时间戳和 EOS 处理。这部分工作不做,硬解就只是文档里的一个名词。

所以这个项目从开始就不是“再编译一遍 FFmpeg”,而是把三件事放在一起:

  1. FFmpeg 的完整封装、解复用、重采样、滤镜与封装能力;
  2. 鸿蒙原生硬解/硬编接口;
  3. 能被 ArkTS 和 C++ 项目直接消费的发布形态。

项目保持 LGPL-2.1-or-later,没有启用 GPL、nonfree、x264、x265。当前提供 arm64-v8a 和 x86_64 双 ABI,动态库按 16KB 页对齐。

2. 核心能力与边界

已具备的能力

  • 音频:AAC / MP3 / FLAC / Opus / WAV 等常见格式的解码、转码和重采样;支持鸿蒙原生音频硬解,并在硬解不可用时回退软解。
  • 视频:H.264 / H.265 的解封装、解码和 Surface 渲染;基础 H.264 硬编;MP4 / MKV / FLV 等常见容器的转码与提取。
  • 水印:文字水印和图片水印可以同时叠加,支持位置、字号、颜色、透明度、加粗描边;图片支持 PNG / JPEG 解码。
  • 滤镜:基于 libavfilter 的 scale、overlay、drawtext、format 链路,支持 original / 720p / 1080p 输出。
  • 工程形态:HAR 包和 ZIP SDK 双形态;8 个动态库;23 个 ArkTS 方法。

测试页面,图片和文字水印表现正常

必须说清楚的边界

当前 v0.2.2 只是公测初版,不是最终完成版。

  • 视频处理目前只覆盖基础能力,远没有达到原生 FFmpeg 的全功能覆盖。复杂的滤镜组合、更多编码器、更多容器、更多码流特性仍在后续计划中。
  • 图片水印目前还不够完善。PNG/JPEG 解码、缩放和叠加已经跑通,但透明通道、边缘混合、异常图片输入等细节还需要继续打磨。
  • 硬解能力依赖具体设备和系统版本。不同芯片、不同 HarmonyOS 版本支持的 codec、分辨率和像素格式并不完全一致,项目做了能力探测和软解回退,但不能保证所有设备行为一致。
  • API 仍可能调整,v0.x 阶段不承诺二进制兼容。生产环境接入前,请用自己的素材、目标设备和目标容器做完整验证。
  • 当前没有覆盖全部 FFmpeg 组件,也没有承诺替代系统媒体框架。它更适合作为“需要 FFmpeg 能力时的一块基础组件”,而不是万能播放器。

3. 双形态分发设计

不同开发者接入 FFmpeg 的方式不一样,所以 v0.2.2 同时提供两种形态。

在这里插入图片描述

HAR 包:给 ArkTS 前端开发者

ffmpeg_ohos-v0.2.2.har,约 18MB,包含 ArkTS 接口和双 ABI native 库。

适合:

  • 已经有 HarmonyOS 工程,只想在页面里调用转码、播放、水印;
  • 不想维护 CMake、不想手动拷贝 .so;
  • 希望用 ohpm 管理依赖。

HAR 不包含 libc++_shared.so,宿主 App 需要用自己的 NDK 版本提供 C++ runtime,避免和宿主工程的 C++ 运行时冲突。

ZIP SDK:给 C++ 底层开发者

ffmpeg-ohos-sdk-v0.2.2.zip,约 18.5MB,包含:

include/                 FFmpeg + freetype + harfbuzz + lame 头文件
lib/arm64-v8a/           7 个 FFmpeg/lame 库 + libffz.so.1
lib/x86_64/
CMakeLists.txt           可直接 add_subdirectory 的示例
BUILD-INFO.txt           ABI、SONAME、sha256 清单
NOTICE.md
LICENSES/

适合:

  • 独立转码器、离线处理工具、C++ 服务;
  • 需要直接拿 AVFormatContext、AVCodecContext 做更底层的控制;
  • 想把 FFmpeg 当成一个普通 C/C++ 依赖接入现有构建系统。

其中 libffz.so.1 是重命名后的 zlib。这样做的原因是鸿蒙系统环境里没有稳定可用的 libz.so,而宿主工程可能自带 zlib,直接叫 libz 会冲突。重命名后,libavcodec.so.63 和 libavformat.so.63 的 NEEDED 都指向 libffz.so.1。

4. 极简接入指南

4.1 ArkTS:通过 HAR 调用转码

先把 HAR 放进工程,作为本地依赖:

// entry/oh-package.json5
{
  "dependencies": {
    "@sirius/ffmpeg_ohos": "file:../ffmpeg_ohos"
  }
}

然后调用:

import { FFmpegOhos } from '@sirius/ffmpeg_ohos';

const src = `${ctx.filesDir}/input.mp4`;
const dst = `${ctx.filesDir}/output.mp4`;

const r = FFmpegOhos.videoTranscode(
  src,
  dst,
  'mp4',       // 容器格式
  '720p',      // original | 720p | 1080p
  1.0          // 音量 0.0 - 2.0
);

if (!r.ok) {
  console.error('transcode start failed:', r.data);
}

带文字 + 图片水印时,format 使用下面这串参数:

watermark|<text>|<position>|<fontSize>|<color>|<fontPath>|<alpha>|<bold>

示例:

const fontPath = `${ctx.filesDir}/SourceHanSansCN-Regular.otf`;
const logoPath = `${ctx.filesDir}/logo.png`;

const format =
  `watermark|FFmpeg-ohos|bottom-right|42|white@0.8|${fontPath}|80|1`;

FFmpegOhos.videoTranscode(
  src,
  dst,
  format,
  '1080p',
  1.0,
  logoPath       // 第 6 个参数:图片水印
);

position 支持 top-left / top-right / bottom-left / bottom-right / center;alpha 为 0–100;bold 为 0 或 1。字体和图片需要先放到 App 可读的沙箱路径。

转码是异步任务,可以通过状态接口查询进度:

const status = JSON.parse(FFmpegOhos.videoTranscodeStatus().data);
// status.state: 1 运行中,2 完成,3 失败

4.2 C++:通过 ZIP SDK 链接

解压 SDK 后,在 CMake 工程里直接引入:

cmake_minimum_required(VERSION 3.16)
project(my_media_tool CXX)

set(OHOS_ARCH arm64-v8a)
add_subdirectory(ffmpeg-ohos-sdk)

add_executable(my_tool main.cpp)
target_link_libraries(my_tool PRIVATE ffmpeg_ohos_sdk)
target_link_libraries(my_tool PRIVATE c++_shared)

ffmpeg_ohos_sdk 会自动带上 include 路径和 8 个 imported 库。业务代码可以直接使用 FFmpeg 原生头文件:

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

AVFormatContext *fmt = nullptr;
if (avformat_open_input(&fmt, path, nullptr, nullptr) < 0) {
    // error
}

如果宿主工程已经有自己的 C++ 运行时,请确保 libc++_shared.so 的版本和 SDK 的编译工具链一致;SDK 不会再随包携带一份 C++ runtime。

5. 踩坑与技术深度

这个项目里比较难的部分,大多不是“调通一个 API”,而是系统边界上的问题。

  • 海思芯片随机花屏:早期手写 AVCC 封装在特定帧上出现随机花屏,最终改成 AnnexB → MPEG-TS → FFmpeg 原生 remux → MP4 的两段式封装,绕开了自己维护 AVCC 的风险。
  • 单声道上混吞音:单声道源被强制上混成立体声时,瞬态峰值从 31517 掉到 22286,正好 -3dB。改成保留源声道数后,FLAC/WAV/Opus 的峰值和起音都恢复正常。
  • 假 zlib 桩:系统里没有可直接用的 libz.so,早期链到的是一个 8.9KB 的空壳,PNG 解码时 avcodec_open2 返回 AVERROR_EXTERNAL。最后交叉编译了真正的 zlib,并重命名为 libffz.so.1。
  • 全量重链:增量构建曾经留下过依赖旧 libz 的 libavformat.so.63,所以现在每次 FFmpeg 构建前都会强制删除 build/<abi>,发布门禁会检查所有 .so 的 DT_NEEDED 闭包。

这些工作不一定体现在 API 数量上,但决定了库拿到陌生工程里能不能直接跑。

6. 开源号召

开源基建不容易。一个人维护交叉编译、双 ABI、硬解适配、滤镜链、发布包和文档,进度不会像商业项目那样快,但每一步都尽量留下可复现的构建和验证记录。

当前 v0.2.2 只是初版,欢迎各位同行:

  • 在自己的鸿蒙设备上试用 HAR 或 ZIP SDK;
  • 遇到问题提 Issue,最好带上设备型号、系统版本、输入素材和完整日志;
  • 对 API 设计、容器支持、图片水印、硬解适配提出改进方向;
  • 如果这个项目帮你省下了几天编译和踩坑时间,点一个 Star 就很有帮助。

仓库与下载

  • GitHub:https://github.com/Sirius-Ji/ffmpeg-for-HarmonyOS
  • GitCode:https://gitcode.com/Sirius_Ji/ffmpeg-for-HarmonyOS
  • Release(HAR / SDK ZIP / per-ABI ZIP / SHA256SUMS):
    https://github.com/Sirius-Ji/ffmpeg-for-HarmonyOS/releases/tag/v0.2.2
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐