flutter_ffmpeg

适用于 Flutter 的 FFmpeg 插件。支持 iOS 和 Android。

1. 特性

  • 基于 MobileFFmpeg

  • 支持

    • 支持 Android 和 IOS

    • FFmpeg v4.2-dev-x (master) 发布

    • Android 上的 arm-v7a, arm-v7a-neon, arm64-v8a, x86x86_64 架构

    • IOS 上的 armv7, armv7s, arm64, arm64e, i386x86_64 架构

    • 24 个外部库

      fontconfig, freetype, fribidi, gmp, gnutls, kvazaar, lame, libaom, libass, libiconv, libilbc, libtheora, libvorbis, libvpx, libwebp, libxml2, opencore-amr, opus, shine, snappy, soxr, speex, twolame, wavpack

    • 4 个 GPL 许可证的外部库

      vid.stab, x264, x265, xvidcore

    • Android 系统库 zlibMediaCodec

    • IOS 系统库 bzip2, zlib 以及 IOS 系统框架 AudioToolbox, CoreImage, VideoToolbox, AVFoundation

  • 根据 LGPL 3.0 许可,可定制以支持 GPL v3.0

  • 包含八种不同的软件包,在 FFmpeg 中启用了不同的外部库

min min-gpl https https-gpl audio video full full-gpl
外部库 - vid.stab
x264
x265
xvidcore
gmp
gnutls
gmp
gnutls
vid.stab
x264
x265
xvidcore
lame
libilbc
libvorbis
opencore-amr
opus
shine
soxr
speex
twolame
wavpack
fontconfig
freetype
fribidi
kvazaar
libaom
libass
libiconv
libtheora
libvpx
libwebp
snappy
fontconfig
freetype
fribidi
gmp
gnutls
kvazaar
lame
libaom
libass
libiconv
libilbc
libtheora
libvorbis
libvpx
libwebp
libxml2
opencore-amr
opus
shine
snappy
soxr
speex
twolame
wavpack
fontconfig
freetype
fribidi
gmp
gnutls
kvazaar
lame
libaom
libass
libiconv
libilbc
libtheora
libvorbis
libvpx
libwebp
libxml2
opencore-amr
opus
shine
snappy
soxr
speex
twolame
vid.stab
wavpack
x264
x265
xvidcore
Android 系统库 zlib
MediaCodec
IOS 系统库 zlib
AudioToolbox
AVFoundation
CoreImage
VideoToolbox
bzip2

2. 安装

在您的 pubspec.yaml 文件中将 flutter_ffmpeg 添加为 依赖项

2.1 软件包

通过 pub 安装 FlutterFFmpeg 会启用默认软件包,该软件包基于 LTS 发行版的 https 软件包。可以通过以下步骤启用其他软件包。

  1. 在您的 pubspec.yaml 文件中使用以下依赖项块。

    dependencies:
      flutter_ffmpeg:
        git:
          url: git://github.com/tanersener/flutter-ffmpeg.git
          ref: v0.1.1
          path: packages/flutter_ffmpeg_https
    
    
  2. 更新 ref: 参数中的版本。

  3. path: packages/flutter_ffmpeg_<package name>[_lts] 部分设置软件包名称。仅当您想依赖 LTS 发行版时,才包含 _lts 后缀。

2.2 LTS 发行版

flutter_ffmpeg 以两种不同的变体发布:主发行版LTS 发行版。两个发行版共享相同的源代码,但构建设置不同。下面您可以看到两者之间的区别。

主发行版 LTS 发行版
Android API 级别 24 21
Android 相机访问 x -
Android 架构 arm-v7a-neon
arm64-v8a
x86
x86-64
arm-v7a
arm-v7a-neon
arm64-v8a
x86
x86-64
IOS SDK 12.1 9.3
Xcode 支持 10.1 7.3.1
IOS 架构 arm64
arm64e
x86-64
armv7
arm64
i386
x86-64

3. 使用方法

  1. 执行命令。

    • 使用 execute() 方法执行单个命令
    import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
    
    final FlutterFFmpeg _flutterFFmpeg = new FlutterFFmpeg();
    
    _flutterFFmpeg.execute("-i file1.mp4 -c:v mpeg4 file2.mp4").then((rc) => print("FFmpeg process exited with rc $rc"));
    
    • 使用 executeWithArguments() 方法执行带有参数数组的命令
    import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
    
    final FlutterFFmpeg _flutterFFmpeg = new FlutterFFmpeg();
    
    var arguments = ["-i", "file1.mp4", "-c:v", "mpeg4", "file2.mp4"];
    _flutterFFmpeg.executeWithArguments(arguments).then((rc) => print("FFmpeg process exited with rc $rc"));
    
  2. 检查执行输出。零表示执行成功,非零值表示失败。

    _flutterFFmpeg.getLastReturnCode().then((rc) => print("Last rc: $rc"));
    
    _flutterFFmpeg.getLastCommandOutput().then((output) => print("Last command output: $output"));
    
  3. 停止正在进行的某个操作。请注意,此函数不会等待终止完成,而是立即返回。

    _flutterFFmpeg.cancel();
    
  4. 获取文件的媒体信息。

    • 打印所有字段
    _flutterFFmpeg.getMediaInformation("<file path or uri>").then((info) => print(info));
    
    • 打印选定字段
    _flutterFFmpeg.getMediaInformation("<file path or uri>").then((info) {
        print("Media Information");
    
        print("Path: ${info['path']}");
        print("Format: ${info['format']}");
        print("Duration: ${info['duration']}");
        print("Start time: ${info['startTime']}");
        print("Bitrate: ${info['bitrate']}");
    
        if (info['streams'] != null) {
            final streamsInfoArray = info['streams'];
    
            if (streamsInfoArray.length > 0) {
                for (var streamsInfo in streamsInfoArray) {
                    print("Stream id: ${streamsInfo['index']}");
                    print("Stream type: ${streamsInfo['type']}");
                    print("Stream codec: ${streamsInfo['codec']}");
                    print("Stream full codec: ${streamsInfo['fullCodec']}");
                    print("Stream format: ${streamsInfo['format']}");
                    print("Stream full format: ${streamsInfo['fullFormat']}");
                    print("Stream width: ${streamsInfo['width']}");
                    print("Stream height: ${streamsInfo['height']}");
                    print("Stream bitrate: ${streamsInfo['bitrate']}");
                    print("Stream sample rate: ${streamsInfo['sampleRate']}");
                    print("Stream sample format: ${streamsInfo['sampleFormat']}");
                    print("Stream channel layout: ${streamsInfo['channelLayout']}");
                    print("Stream sar: ${streamsInfo['sampleAspectRatio']}");
                    print("Stream dar: ${streamsInfo['displayAspectRatio']}");
                    print("Stream average frame rate: ${streamsInfo['averageFrameRate']}");
                    print("Stream real frame rate: ${streamsInfo['realFrameRate']}");
                    print("Stream time base: ${streamsInfo['timeBase']}");
                    print("Stream codec time base: ${streamsInfo['codecTimeBase']}");
                }
            }
        }
    
    
  5. 启用日志回调并将所有 FFmpeg 日志重定向到控制台/文件/小部件。

    void logCallback(int level, String message) {
        print(message);
    }
    ...
    _flutterFFmpeg.enableLogCallback(this.logCallback);
    
  6. 启用统计信息回调,并跟踪正在进行的操作的进度。

    void statisticsCallback(int time, int size, double bitrate, double speed, int videoFrameNumber, double videoQuality, double videoFps) {
        print("Statistics: time: $time, size: $size, bitrate: $bitrate, speed: $speed, videoFrameNumber: $videoFrameNumber, videoQuality: $videoQuality, videoFps: $videoFps");
    }
    ...
    _flutterFFmpeg.enableStatisticsCallback(this.statisticsCallback);
    
  7. 在不实现统计信息回调的情况下轮询统计信息。

    _flutterFFmpeg.getLastReceivedStatistics().then((stats) => print(stats));
    
  8. 在开始新操作之前重置统计信息。

    _flutterFFmpeg.resetStatistics();
    
  9. 设置日志级别。

    _flutterFFmpeg.setLogLevel(LogLevel.AV_LOG_WARNING);
    
  10. 通过指定自定义字体目录注册您自己的字体,以便在 FFmpeg 滤镜中使用。

    _flutterFFmpeg.setFontDirectory("<folder with fonts>");
    
  11. 使用您自己的 fontconfig 配置。

    _flutterFFmpeg.setFontconfigConfigurationPath("<fontconfig configuration directory>");
    
  12. 禁用库的日志功能。日志将不会打印到控制台,日志回调也将被禁用。

    _flutterFFmpeg.disableLogs();
    
  13. 禁用库的统计信息功能。统计信息回调将被禁用,但仍可获取上次收到的统计信息。

    _flutterFFmpeg.disableStatistics();
    
  14. 列出启用的外部库。

    _flutterFFmpeg.getExternalLibraries().then((packageList) {
         packageList.forEach((value) => print("External library: $value"));
    });
    

4. 版本

  • 0.1.x 系列发行版基于 FFmpeg v4.2-devMobileFFmpeg v4.2.LTS

5. 提示

  • 您不应使用双引号(")来定义复杂的滤镜或映射定义。

     -filter_complex [0:v]scale=1280:-1[v] -map [v]
    
  • 如果您的命令包含不必要的引号或空格,您的命令将因 No such filter: ' ' 错误而失败。请检查您的命令并删除它们。

  • 在 Android 上启用 ProGuard 会导致链接错误。请在您的 proguard-rules.pro 文件中添加以下规则,以保留必要的​​方法名称并防止链接错误。

    -keep class com.arthenica.mobileffmpeg.Config {
        native <methods>;
        void log(int, byte[]);
        void statistics(int, float, float, long , int, double, double);
    }
    
  • 默认情况下,Xcode 在打包期间会压缩 PNG 文件。如果您的命令中使用了 .png 文件,请确保将以下两个设置设为 NO。如果其中一个设置为 YES,您的操作可能会因 Error while decoding stream #0:0: Generic error in an external library 错误而失败。

    png_settings

GitHub

https://github.com/tanersener/flutter-ffmpeg