Flutter视频处理插件ffipeg_builder的使用

ffipeg

轻松为您的项目生成 Dart FFI 绑定到 FFmpeg,只需三步:

  1. 添加库注解;
  2. 运行 build_runner
  3. 导入生成的文件并开始使用!

示例

ffmpeg.dart

@FFmpegGen(
  versionSpec: '>=7.1 <8.0',
  excludeAllByDefault: true,
  functions: FFInclude({
    'av_compare_ts',
    'av_interleaved_write_frame',
    'av_log_set_level',
    'av_packet_alloc',
    // ...
    'avio_open',
  }),
  structs: FFInclude({'AVFormatContext', 'AVIOContext', 'AVPacket'}),
  enums: FFInclude({'AVMediaType'}),
  macros: FFInclude({'AVIO_FLAG_WRITE', 'AV_NOPTS_VALUE', 'AV_LOG_.*'}),
)
library;

import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'package:ffipeg/ffipeg.dart'; // 导出 `@FFmpegGen` 注解
import 'ffmpeg.ffipeg.dart'; // 生成的 _name_.ffipeg.dart 文件,包含 FFI 绑定

void main() {
  final dylib = DynamicLibrary.open('/path/to/ffmpeg');
  final ffmpeg = FFmpeg(dylib);
  ffmpeg.av_log_set_level(AV_LOG_DEBUG);

  final videoInputCtx = calloc<Pointer<AVFormatContext>>(); // 视频输入上下文
  final videoPkt = ffmpeg.av_packet_alloc(); // 分配视频包
  final videoPktPtr = calloc<Pointer<AVPacket>>(); // 视频包指针
  final videoFile = "/path/to/video/file.mp4"; // 视频文件路径

  if (0 != ffmpeg.avformat_open_input(
      videoInputCtx, videoFile.toNativeUtf8().cast(), nullptr, nullptr)) {
    throw Exception('Failed to open video file: $videoFile');
  }

  // 清理资源
  ffmpeg
    ..avformat_close_input(videoInputCtx)
    ..av_packet_free(videoPktPtr);

  if (videoPktPtr != nullptr) {
    calloc.free(videoPktPtr);
  }
  if (videoInputCtx != nullptr) {
    calloc.free(videoInputCtx);
  }
}

特性

  • 此包基本上是一个围绕 <code>FfiGen()</code> 的包装器,使用 <code>build_runner</code> 并使其更易于作为标准构建过程的一部分。它为 FFmpeg 提供了合理的默认值。
  • 指定 FFmpeg 头文件的 <code>headerPaths</code>,或者使用默认包含的头文件。如果提供了 <code>headerPaths</code>,它们将按顺序尝试,以便支持多个构建平台。
  • 指定应包含的 FFmpeg 库(如 <code>FFmpegLibrary.avCodec</code> 等),所有库默认都包括。
  • 通过强类型的选项 <code>Set<String></code>(如 <code>FFInclude({...})</code><code>FFExclude({...})</code><code>ffAllowAll</code><code>ffDenyAll</code>)传递标准 <code>FfiGen()</code> 的包含/排除选项。
  • 自定义生成类名以用于函数(默认为 <code>FFmpeg</code>)。
  • 将自定义的 <code>llvmPaths</code> 传递给 <code>FfiGen()</code>(可选)。

开始使用

前提条件

  • Flutter 不是必需的。仅需要 Dart 和包依赖项即可进行代码生成。
  • 实际运行 FFI 代码需要一个 FFmpeg 二进制文件(可以是可执行命令行工具或动态库,例如在 <a href="https://pub.dev/packages/fvp"><code>fvp</code></a> 包中提供的用于 Flutter)。
  • 此包不依赖于 <code>fvp</code> 或其 <code>mdk-sdk</code>。任何与目标系统和用于构建绑定的头文件版本兼容的 FFmpeg 二进制文件都可以工作。

安装

添加四个必需的包:

dart pub add ffipeg
dart pub add ffi
dart pub add --dev ffipeg_builder
dart pub add --dev build_runner

更多关于Flutter视频处理插件ffipeg_builder的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter视频处理插件ffipeg_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


ffmpeg_builder 是一个用于 Flutter 的插件,它允许你在 Flutter 应用中使用 FFmpeg 进行视频处理。FFmpeg 是一个强大的多媒体框架,可以处理视频、音频、字幕等多媒体文件。通过 ffmpeg_builder,你可以在 Flutter 应用中执行 FFmpeg 命令,例如视频转码、剪辑、添加水印等操作。

安装

首先,你需要在 pubspec.yaml 文件中添加 ffmpeg_builder 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  ffmpeg_builder: ^0.0.1  # 请根据实际版本号进行替换

然后运行 flutter pub get 来安装依赖。

使用

1. 初始化 FFmpeg

在使用 ffmpeg_builder 之前,你需要初始化 FFmpeg。通常,你可以在应用的 main 函数中进行初始化。

import 'package:ffmpeg_builder/ffmpeg_builder.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FFmpegBuilder.initialize();
  runApp(MyApp());
}

2. 执行 FFmpeg 命令

你可以使用 FFmpegBuilder 来执行 FFmpeg 命令。下面是一个简单的例子,展示了如何将视频文件转码为另一种格式:

import 'package:ffmpeg_builder/ffmpeg_builder.dart';

Future<void> transcodeVideo() async {
  final inputPath = '/path/to/input.mp4';
  final outputPath = '/path/to/output.avi';

  final command = FFmpegBuilder()
    ..input(inputPath)
    ..output(outputPath)
    ..videoCodec('mpeg4')
    ..audioCodec('aac');

  try {
    await command.execute();
    print('视频转码成功!');
  } catch (e) {
    print('视频转码失败: $e');
  }
}

3. 处理命令执行结果

FFmpegBuilderexecute 方法会返回一个 Future,你可以使用 await 来等待命令执行完成,并处理可能出现的错误。

4. 其他常用操作

ffmpeg_builder 提供了许多方法来构建 FFmpeg 命令。以下是一些常用操作的示例:

  • 裁剪视频

    final command = FFmpegBuilder()
      ..input(inputPath)
      ..output(outputPath)
      ..startPosition(Duration(seconds: 10))
      ..duration(Duration(seconds: 20));
    
  • 添加水印

    final command = FFmpegBuilder()
      ..input(inputPath)
      ..output(outputPath)
      ..complexFilter('overlay=10:10');
    
  • 调整视频分辨率

    final command = FFmpegBuilder()
      ..input(inputPath)
      ..output(outputPath)
      ..size('640x480');
    
  • 提取音频

    final command = FFmpegBuilder()
      ..input(inputPath)
      ..output(outputPath)
      ..audioOnly();
回到顶部