插件介绍

Flutter外接纹理(External Texture)机制已成功适配OpenHarmony平台,为开发者提供了高效的原生内容渲染能力。在视频播放、相机预览等场景中,外接纹理能够直接渲染OpenHarmony平台的原生内容,实现无缝对接。

本指南将介绍如何使用Flutter OHOS外接纹理第一帧自定义功能,通过flutterRenderer.setTextureBackGroundColorflutterRenderer.setTextureBackGroundPixelMap方法,在视频加载或播放之前设置纹理的背景颜色和图像,提升用户体验。

环境搭建

前置条件

  • Flutter SDK 3.0.0及以上
  • OpenHarmony SDK API 9及以上
  • DevEco Studio 3.0及以上

项目配置

确保你的Flutter项目已经支持OpenHarmony平台,若尚未配置,可参考官方文档进行设置。

包的引入

由于本功能为自定义修改版本,需要以Git形式引入。在项目的pubspec.yaml文件中添加以下依赖配置:

dependencies:
  external_texture_customization:
    git:
      url: "https://atomgit.com/"
      path: "packages/external_texture_customization"

添加依赖后,执行flutter pub get命令获取包资源。

FlutterState与TextureRegistry

在使用外接纹理第一帧自定义功能前,需要了解FlutterState类和TextureRegistry接口:

FlutterState类

FlutterState类管理着与Flutter引擎的通信和纹理注册,是访问flutterRenderer的关键:

export class FlutterState {
  private binaryMessenger: BinaryMessenger;
  private textureRegistry: TextureRegistry;

  constructor(binaryMessenger: BinaryMessenger, textureRegistry: TextureRegistry) {
    this.binaryMessenger = binaryMessenger;
    this.textureRegistry = textureRegistry;
  }

  getBinaryMessenger(): BinaryMessenger {
    return this.binaryMessenger;
  }

  getTextureRegistry(): TextureRegistry {
    return this.textureRegistry;
  }
}

TextureRegistry接口

TextureRegistry是管理纹理的核心接口,flutterRenderer就是TextureRegistry的实例,通过它可以调用设置背景的相关方法:

// 获取flutterRenderer实例
TextureRegistry flutterRenderer = flutterState.getTextureRegistry();

API调用方法

1. 设置纹理背景颜色

使用setTextureBackGroundColor方法设置纹理的背景颜色:

/// 设置纹理背景颜色
/// textureId: 纹理的唯一标识
/// color: 32位十六进制颜色值,格式为0xAABBGGRR
flutterRenderer.setTextureBackGroundColor(textureId, 0xFF0000FF);

颜色值格式说明:

  • AA: Alpha通道,控制透明度(00完全透明,FF完全不透明)
  • BB: 蓝色分量
  • GG: 绿色分量
  • RR: 红色分量

例如:0xFF0000FF表示不透明的红色背景。

2. 设置纹理背景图像

使用setTextureBackGroundPixelMap方法将图像设置为纹理的背景:

/// 设置纹理背景图像
/// textureId: 纹理的唯一标识
/// pixelMap: 图像的PixelMap对象
flutterRenderer.setTextureBackGroundPixelMap(textureId, pixelMap);

代码示例

示例1:设置红色背景

// 在纹理创建后设置背景颜色
int textureId = // 注册纹理后获取的ID
TextureRegistry flutterRenderer = flutterState.getTextureRegistry();

// 设置红色背景
flutterRenderer.setTextureBackGroundColor(textureId, 0xFF0000FF);

示例2:设置视频第一帧作为背景

下面是一个完整的示例,展示如何从视频中提取第一帧并设置为纹理背景:

import 'dart:async';
import 'package:media_kit/media_kit.dart';

// 获取视频第一帧并设置为纹理背景
Future<void> setVideoFirstFrameAsBackground(
    int textureId,
    FlutterState flutterState,
    String videoPath
) async {
  TextureRegistry flutterRenderer = flutterState.getTextureRegistry();

  try {
    // 创建AVImageGenerator实例
    let avImageGenerator = await media.createAVImageGenerator();

    // 设置视频源
    if (videoPath.startsWith('assets/')) {
      // 处理资产文件
      avImageGenerator.fdSrc = await this.getContext().resourceManager.getRawFd(
          "flutter_assets/" + videoPath.replaceFirst('assets/', '')
      );
    } else if (videoPath.startsWith('fd://')) {
      // 处理本地文件
      avImageGenerator.fdSrc = {
        fd: Number.parseInt(videoPath.replace("fd://", ""))
      };
    }

    // 提取第一帧图像
    let pixelMap = await avImageGenerator.fetchFrameByTime(
        0,
        media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC,
        {
          width: -1, // 使用原始宽度
          height: -1 // 使用原始高度
        }
    );

    // 设置为纹理背景
    flutterRenderer.setTextureBackGroundPixelMap(textureId, pixelMap);

    // 释放资源
    avImageGenerator.release();
  } catch (e) {
    print('设置视频第一帧失败: $e');
    // 设置默认背景颜色作为 fallback
    flutterRenderer.setTextureBackGroundColor(textureId, 0xFF000000);
  }
}

示例3:在video_player_ohos中的实际应用

以下是在video_player_ohos插件中使用这些方法的完整示例:

if (asset != null) {
  Log.i(TAG, "asset create called, asset is" + asset);
  let avMetaExtractor = await media.createAVMetadataExtractor();
  avMetaExtractor.fdSrc = await this.getContext().resourceManager.getRawFd("flutter_assets/" + asset);
  let mateData = await avMetaExtractor.fetchMetadata();
  if (mateData.hasVideo == CommonConstants.YES) {
    let avImageGenerator = await media.createAVImageGenerator();
    Log.i(TAG, "asset video create");
    avImageGenerator.fdSrc = await this.getContext().resourceManager.getRawFd("flutter_assets/" + asset);
    let pixelMap = await avImageGenerator.fetchFrameByTime(0, media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC, {
      width: -1,
      height: -1
    });
    this.pixelMaps.set(JSON.stringify(arg), pixelMap);
    avImageGenerator.release();
    flutterRenderer.setTextureBackGroundPixelMap(textureId, this.pixelMaps.get(JSON.stringify(arg)));
  }
  avMetaExtractor.release();
} else if (uri != null && uri.startsWith("fd://")) {
  Log.i(TAG, "local create called, file is" + uri);
  let avMetaExtractor = await media.createAVMetadataExtractor();
  avMetaExtractor.fdSrc = {
    fd: Number.parseInt(uri.replace("fd://", ""))
  };
  let mateData = await avMetaExtractor.fetchMetadata();
  if (mateData.hasVideo == CommonConstants.YES) {
    let avImageGenerator = await media.createAVImageGenerator();
    Log.i(TAG, "local video create");
    avImageGenerator.fdSrc = {
      fd: Number.parseInt(uri.replace("fd://", ""))
    };
    let pixelMap = await avImageGenerator.fetchFrameByTime(0, media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC, {
      width: -1,
      height: -1
    });
    this.pixelMaps.set(JSON.stringify(arg), pixelMap);
    avImageGenerator.release();
    flutterRenderer.setTextureBackGroundPixelMap(textureId, this.pixelMaps.get(JSON.stringify(arg)));
  }
  avMetaExtractor.release();
}
// 设置红色背景作为fallback
flutterRenderer.setTextureBackGroundColor(textureId, 0xFF0000FF);

注意事项

  1. 纹理ID有效性:确保在调用背景设置方法前,已经为纹理分配了有效的textureId

  2. 内存管理:使用setTextureBackGroundPixelMap后,注意适当管理PixelMap的内存,避免内存泄漏

  3. 资源路径:确保视频或图像资源的路径正确,特别是资产文件需要放在flutter_assets目录下

  4. 兼容性考虑

    • Flutter 3.7版本之前,外接纹理默认第一帧为白色背景
    • Flutter 3.22版本之后,外接纹理默认没有背景色
    • 建议同时设置背景颜色和背景图像,以确保在不同版本下都有良好的显示效果
  5. 错误处理:在实际应用中,建议添加适当的错误处理机制,确保在资源加载失败时能够提供合理的fallback方案

总结

Flutter OHOS外接纹理第一帧自定义功能为开发者提供了灵活的背景设置能力,通过flutterRenderer.setTextureBackGroundColorflutterRenderer.setTextureBackGroundPixelMap方法,可以:

  1. 根据业务需求自定义纹理背景颜色
  2. 将视频第一帧作为纹理背景,提升用户体验
  3. 为不同场景提供个性化的视觉效果

这些功能的实现,解决了之前外接纹理默认白色背景无法满足所有业务场景的问题,特别是在视频播放等场景中,能够提供更加合理和专业的视觉呈现。

与iOS和Android平台相比,OpenHarmony平台的实现提供了类似的功能,但具有更好的灵活性和可定制性,为跨平台开发提供了统一的解决方案。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

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

更多推荐