HarmonyOS 鸿蒙Next中视频添加水印;官网文档没有具体的API和实现流程;是只能用FFmpeg命令行实现嘛?后面官网文档会有具体的API实现和流程吗?

HarmonyOS 鸿蒙Next中视频添加水印;官网文档没有具体的API和实现流程;是只能用FFmpeg命令行实现嘛?后面官网文档会有具体的API实现和流程吗? 视频添加水印;官网文档没有具体的API和实现流程;是只能用FFmpeg命令行实现嘛?后面官网文档会有具体的API实现和流程吗?

3 回复

开发者您好,可以采取以下方式解决:

【解决方案】

方案一:不对视频本身进行修改,在视频窗口上覆盖需要添加的字块或者图像,可使用Video组件的controls(value: boolean)属性控制视频播放的控制栏是否显示。

  • 通过UI组件的overlay通用属性将自定义组件覆盖在Video组件显示页面上添加自定义水印效果。
@Builder
WatermarkBuilder() {
  Column() {
    // 自定义水印组件样式实现
    // ...
  }
}

Video({
  // ...
})
  .width('100%')
  .height(600)
  .alignItems(HorizontalAlign.Center)
  .overlay(this.watermarkBuilder())
  • 使用stack组件叠加在UI组件上层:
Stack({ alignContent: Alignment.Center }) {
  Column() {
    Image($r('app.media.empty'))
      .width(110)
      .height(88)
  }
  Watermark({ rotationAngle: 20 })
}

方案二:对视频本身进行修改,为每一帧视频添加水印效果。

获取视频的视频帧,对视频帧和水印内容在画布上绘制,绘制好的图像传递给视频编码器的buffer队列。例如在录像中需要对视频添加水印。在ArkTS侧通过监听相机预览流的imageArrival事件,获取预览帧,对每一帧图片添加水印,将添加水印后的图片buffer,传输给给编码器合成视频。具体实现步骤如下:

  1. 定义监听并绘制水印的函数: 注册ImageReceiver图像监听事件onImageArrival获取视频帧,并进行水印绘制。创建预览流获取数据的完整示例可见创建预览流获取数据
onImageArrival(receiver: image.ImageReceiver): void {
  // 注册imageArrival监听
  receiver.on('imageArrival', () => {
    // 获取视频帧图像
    receiver.readNextImage((err: BusinessError, nextImage: image.Image) => {
      if (err || nextImage === undefined) {
        return;
      }
      // 解析图像内容
      nextImage.getComponent(image.ComponentType.JPEG, async (err: BusinessError,imgComponent: image.Component) => {
        // 绘制水印到视频帧
        this.drawImage2Frame(nextImage, imgComponent)
        // 确保当前buffer没有在使用的情况下,可进行资源释放。如果对buffer进行异步操作,需要在异步操作结束后再释放该资源(nextImage.release())
        nextImage.release();
      })
    })
  })
}
  1. 初始化ImageReceiver,关联获取预览流的SurfaceId,对从相机预览流中的每帧数据调用之前定义的onImageArrival。
async initImageReceiver(): Promise<void> {
  if (!this.imageReceiver) {
    // 创建ImageReceiver,size宽高业务自行定义
    let size: image.Size = { width: this.imageWidth, height: this.imageHeight };
    this.imageReceiver = image.createImageReceiver(size, image.ImageFormat.JPEG, EIGHT);
    // 获取取第一路流SurfaceId
    this.imageReceiverSurfaceId = await this.imageReceiver.getReceivingSurfaceId();
    // 注册监听处理预览流每帧图像数据
    this.onImageArrival(this.imageReceiver);
  }
}
  1. 定义绘制水印的函数,在onImageArrival监听回调中,使用OffscreenCanvas.drawImage离屏画布接口,将帧图片和水印绘制到画布上。 绘制的过程可以在ArkTS侧完成,也可以在C++侧完成参考画布的获取与绘制结果的显示(ArkTS)/画布的获取与绘制结果的显示(C/C++)
async drawImage2Frame(nextImage: image.Image, imgComponent: image.Component){
  if (!imgComponent.byteBuffer) {
    return
  }
  let width = nextImage.size.width; 
  let height = nextImage.size.height; 
  let pixelmap: PixelMap | undefined  = await image.createPixelMap(imgComponent.byteBuffer, {
    size: { height: height, width: width },
    srcPixelFormat: EIGHT,
  })
  if (pixelmap && this.record) {
    const height1 = px2vp(height);
    const width1 = px2vp(width);
    const offScreenCanvas = new OffscreenCanvas(width1, height1);
    const offScreenContext = offScreenCanvas.getContext('2d');
    // 绘制视频帧和视频水印到画布上
    offScreenContext.drawImage(pixelmap, ZERO, ZERO, width1, height1);
    offScreenContext.drawImage(this.watermarkPixelmap, top, left, bottom, right);
    this.timer += 1;
    this.inputpath = this.filepath + '/' + this.timer + '.jpeg';
    let pixelmapshow: PixelMap = offScreenContext.getPixelMap(ZERO, ZERO, width1, height1);
    let packOpts: image.PackingOption = { format: 'image/jpeg', quality: QUALITY };
    let imagePackerApi = image.createImagePacker();
    let file = fs.openSync(this.inputpath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    imagePackerApi.packToFile(pixelmapshow, file.fd, packOpts, (err: BusinessError) => {
      imagePackerApi.release()
      fs.closeSync(file.fd);
    })
  }
}

注:推荐在C++侧用CPU完成绘制过程,C++侧使用离屏画布有CPU和GPU两种模式,使用CPU绘制时性能更佳。在C++侧调用Bitmap和Canvas来绘画,绘画的内容会输出到绑定的Bitmap内存中。具体可参考CPU后端Canvas的创建与显示

  1. 通过视频编码器将视频帧合成视频。参考视频编码

参考完整demo:VideoWaterMark

更多关于HarmonyOS 鸿蒙Next中视频添加水印;官网文档没有具体的API和实现流程;是只能用FFmpeg命令行实现嘛?后面官网文档会有具体的API实现和流程吗?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙Next视频水印可通过媒体处理框架实现。系统提供PixelMap API创建水印图像,通过AVMetadataExtractor和AVMetadataInjector处理媒体元数据。视频编辑模块支持图层合成,使用AVCompositeImageFilter将水印叠加到视频帧。FFmpeg非必需方案。官方路线图显示媒体能力持续增强,后续版本会提供更完整的多媒体处理API。

目前HarmonyOS Next的视频处理能力仍在完善中,官方暂未提供专门用于视频水印处理的API。现阶段可通过以下方式实现:

  1. FFmpeg方案:可通过调用Native层集成FFmpeg库实现水印添加,这是当前较稳定的方案。需要自行处理跨平台编译和性能优化。

  2. 媒体处理能力:可关注@ohos.multimedia.mediaLibrary和@ohos.image模块,现有API支持基础媒体文件操作和图像处理,可结合使用实现简单水印效果。

  3. 图形绘制能力:利用@ohos.graphics模块的Canvas或WebGL能力,在播放器上层叠加水印图层,但此方案不改变原始视频文件。

关于后续规划,华为通常会随着系统版本迭代逐步开放多媒体处理能力。建议:

  • 关注官方DevEco Studio更新日志
  • 查阅ArkTS/NDK开发文档的版本变更说明
  • 参与HDC开发者大会获取roadmap信息

当前建议优先采用FFmpeg方案保障功能完整性,同时保持对官方能力更新的关注。

回到顶部