插件介绍

FlutterTPC Export Video Frame 是一个功能强大的 Flutter 插件,用于从视频文件中导出图片帧。该插件基于官方的 Export Video frame 插件开发,并针对鸿蒙(HarmonyOS)平台进行了定制和优化,支持在鸿蒙设备上高效地导出视频帧。

核心特性

  • 多平台支持:同时支持 Android、iOS 和 HarmonyOS 平台
  • 灵活的帧导出:支持按数量导出帧、按时间点导出单帧、导出 GIF 图像等多种方式
  • 水印功能:支持为导出的图片添加水印,并可自定义水印位置和缩放比例
  • 质量控制:可控制导出帧的质量和缩放比例
  • 相册保存:支持将导出的图片保存到相册
  • 缓存管理:支持清理图像缓存,优化存储空间使用

适用场景

  • 视频编辑应用中提取关键帧
  • 视频预览功能实现
  • 视频截图工具开发
  • 需要从视频中提取图像的各类应用

如何使用

1. 添加依赖

由于 FlutterTPC Export Video Frame 是一个自定义修改版本,需要通过 Git 形式引入。在您的 Flutter 项目的 pubspec.yaml 文件中添加以下依赖配置:

dependencies:
  export_video_frame:
    git:
      url: "https://atomgit.com/openharmony-sig/fluttertpc_export_video_frame.git"

然后执行以下命令获取依赖:

flutter pub get

2. 导入包

在需要使用插件的 Dart 文件中导入包:

import 'package:export_video_frame/export_video_frame.dart';
import 'dart:io';
import 'package:flutter/material.dart';

3. API 使用示例

3.1 清理图像缓存
// 清理图像缓存
bool success = await ExportVideoFrame.cleanImageCache();
if (success) {
  print('图像缓存清理成功');
} else {
  print('图像缓存清理失败');
}
3.2 导出指定数量的帧
// 从视频文件中导出指定数量的帧
List<File> frames = await ExportVideoFrame.exportImage(
  'path/to/video.mp4', // 视频文件路径
  5,                  // 导出的帧数
  0.8,                // 质量(0-1,0最低,1原始)
);

// 处理导出的帧
for (File frame in frames) {
  print('导出的帧路径:${frame.path}');
  // 可以将帧显示在界面上或进行其他处理
}
3.3 按时间点导出单帧
// 根据时间间隔从视频中导出单帧
File frame = await ExportVideoFrame.exportImageBySeconds(
  File('path/to/video.mp4'), // 视频文件
  Duration(seconds: 10),     // 导出第10秒的帧
  0.0,                       // 旋转角度(弧度)
);

print('导出的单帧路径:${frame.path}');
3.4 保存图像到相册
// 将导出的图像保存到相册
bool saved = await ExportVideoFrame.saveImage(
  frame,                     // 要保存的图像文件
  'MyAlbum',                 // 相册名称
  waterMark: 'images/water_mark.png', // 水印图片资源路径
  alignment: Alignment(1, 1), // 水印位置(右下角)
  scale: 1.0,                // 水印缩放比例
);

if (saved) {
  print('图像保存到相册成功');
} else {
  print('图像保存到相册失败');
}
3.5 从视频文件导出图像流

注意:该功能在鸿蒙平台上暂不支持

// 从视频文件获取图像流(鸿蒙平台暂不支持)
Stream<File> imageStream = ExportVideoFrame.exportImagesFromFile(
  File('path/to/video.mp4'), // 视频文件
  Duration(seconds: 1),      // 每帧之间的时间间隔
  0.0,                       // 旋转角度
);

// 处理图像流
imageStream.listen((File imageFile) {
  print('新的帧:${imageFile.path}');
});
3.6 导出 GIF 图像

注意:该功能在鸿蒙平台上暂不支持

// 从视频文件导出 GIF 图像(鸿蒙平台暂不支持)
List<File> gifFrames = await ExportVideoFrame.exportGifImage(
  'path/to/video.mp4', // 视频文件路径
  0.8,                // 质量
);

// 处理导出的 GIF 帧
for (File frame in gifFrames) {
  print('GIF 帧路径:${frame.path}');
}

4. 鸿蒙平台特定配置

4.1 权限配置

在使用插件之前,需要确保应用已获得必要的权限。在鸿蒙平台上,需要在 module.json5 文件中配置以下权限:

{
  "module": {
    "abilities": [
      {
        "permissions": [
          "ohos.permission.READ_MEDIA",
          "ohos.permission.WRITE_MEDIA"
        ]
      }
    ]
  }
}
4.2 鸿蒙平台支持情况

以下是鸿蒙平台对各 API 的支持情况:

API 方法 鸿蒙平台支持
cleanImageCache ✅ 支持
saveImage ✅ 支持
exportImage ✅ 支持
exportGifImage ❌ 暂不支持
exportImageBySeconds ✅ 支持
exportImagesFromFile ❌ 暂不支持
4.3 版本兼容性

已在以下版本中测试通过:

  • Flutter: 3.7.12-ohos-1.0.6
  • SDK: 5.0.0(12)
  • IDE: DevEco Studio: 5.0.13.200
  • ROM: 5.1.0.120 SP3

示例代码

以下是一个完整的示例,展示如何使用 FlutterTPC Export Video Frame 插件:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:export_video_frame/export_video_frame.dart';
import 'package:file_picker/file_picker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Export Video Frame Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  File? _videoFile;
  List<File> _exportedFrames = [];
  File? _singleFrame;

  // 选择视频文件
  Future<void> _pickVideo() async {
    FilePickerResult? result = await FilePicker.platform.pickFiles(
      type: FileType.video,
    );

    if (result != null) {
      setState(() {
        _videoFile = File(result.files.single.path!);
        _exportedFrames = [];
        _singleFrame = null;
      });
    }
  }

  // 导出多个帧
  Future<void> _exportMultipleFrames() async {
    if (_videoFile == null) return;

    try {
      List<File> frames = await ExportVideoFrame.exportImage(
        _videoFile!.path,
        5, // 导出5帧
        0.8, // 质量
      );

      setState(() {
        _exportedFrames = frames;
      });
    } catch (e) {
      print('导出失败: $e');
    }
  }

  // 导出单帧
  Future<void> _exportSingleFrame() async {
    if (_videoFile == null) return;

    try {
      File frame = await ExportVideoFrame.exportImageBySeconds(
        _videoFile!,
        Duration(seconds: 5), // 导出第5秒的帧
        0.0, // 不旋转
      );

      setState(() {
        _singleFrame = frame;
      });
    } catch (e) {
      print('导出失败: $e');
    }
  }

  // 保存图像到相册
  Future<void> _saveToAlbum() async {
    if (_singleFrame == null) return;

    try {
      bool saved = await ExportVideoFrame.saveImage(
        _singleFrame!,
        'MyVideoFrames',
        waterMark: 'assets/watermark.png',
        alignment: Alignment(1, 1), // 右下角
        scale: 1.0,
      );

      if (saved) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('保存成功')),
        );
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('保存失败')),
        );
      }
    } catch (e) {
      print('保存失败: $e');
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Export Video Frame Demo'),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            ElevatedButton(
              onPressed: _pickVideo,
              child: Text('选择视频文件'),
            ),
            SizedBox(height: 16.0),
            if (_videoFile != null)
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('已选择视频: ${_videoFile!.path.split('/').last}'),
                  SizedBox(height: 16.0),
                  ElevatedButton(
                    onPressed: _exportMultipleFrames,
                    child: Text('导出5帧'),
                  ),
                  SizedBox(height: 8.0),
                  ElevatedButton(
                    onPressed: _exportSingleFrame,
                    child: Text('导出第5秒的帧'),
                  ),
                  SizedBox(height: 8.0),
                  if (_singleFrame != null)
                    ElevatedButton(
                      onPressed: _saveToAlbum,
                      child: Text('保存到相册'),
                    ),
                  SizedBox(height: 16.0),
                ],
              ),
            if (_singleFrame != null)
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('导出的单帧:'),
                  SizedBox(height: 8.0),
                  Image.file(_singleFrame!, height: 200),
                  SizedBox(height: 16.0),
                ],
              ),
            if (_exportedFrames.isNotEmpty)
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('导出的帧:'),
                  SizedBox(height: 8.0),
                  Container(
                    height: 150,
                    child: ListView.builder(
                      scrollDirection: Axis.horizontal,
                      itemCount: _exportedFrames.length,
                      itemBuilder: (context, index) {
                        return Padding(
                          padding: EdgeInsets.only(right: 8.0),
                          child: Image.file(_exportedFrames[index], height: 150),
                        );
                      },
                    ),
                  ),
                ],
              ),
          ],
        ),
      ),
    );
  }
}

鸿蒙平台注意事项

  1. 功能限制

    • 目前暂不支持 exportGifImage 方法(导出 GIF 图像)
    • 目前暂不支持 exportImagesFromFile 方法(获取图像流)
  2. 性能优化

    • 导出大量帧时,建议分批处理,避免占用过多内存
    • 适当调整质量参数(quality)以平衡图像质量和导出速度
  3. 权限管理

    • 确保应用已获得必要的媒体读写权限
    • 在鸿蒙平台上,需要在 module.json5 文件中正确配置权限
  4. 版本兼容性

    • 已在 Flutter 3.7.12-ohos-1.0.6 和 HarmonyOS SDK 5.0.0(12) 上测试通过
    • 使用时请确保 Flutter 和 HarmonyOS SDK 版本与测试版本兼容

总结

FlutterTPC Export Video Frame 是一个功能强大的视频帧导出插件,为开发者提供了在 Flutter 应用中从视频文件导出图像帧的便捷方式。该插件针对鸿蒙平台进行了专门的适配和优化,使开发者能够在鸿蒙设备上轻松实现视频帧导出功能。

主要优势:

  • 简单易用的 API 接口
  • 丰富的导出选项和定制功能
  • 良好的跨平台支持,特别是对鸿蒙平台的深度适配
  • 支持水印、质量控制等高级功能

无论是开发视频编辑应用、视频预览功能,还是需要从视频中提取图像的其他应用,FlutterTPC Export Video Frame 都是一个值得推荐的选择。

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

Logo

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

更多推荐