Skip to content

dra11y/ffipeg-dart

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ffipeg

Easily generate Dart FFI bindings to FFmpeg for use in your project in 3 steps:

  1. Add a library annotation;
  2. Run build_runner;
  3. Import the generated file, ffi, and go!

Example

(Incomplete; for illustrative purposes only; see ffipeg_muxer package for full working example.)

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'; // Exports `@FFmpegGen` Annotation
import 'ffmpeg.ffipeg.dart'; // Generated _name_.ffipeg.dart file with FFI bindings

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');
    }
    // ... do more stuff ...
    // We're dealing with C ... be sure to clean up resources!
    ffmpeg
        ..avformat_close_input(videoInputCtx)
        ..av_packet_free(videoPktPtr);
    if (videoPktPtr != nullptr) {
        calloc.free(videoPktPtr);
    }
    if (videoInputCtx != nullptr) {
        calloc.free(videoInputCtx);
    }
}

Features

  • This package is basically a wrapper around FfiGen() that uses build_runner and makes it more accessible as part of a standard build process. It offers reasonable defaults for FFmpeg.
  • Specify your own headerPaths to FFmpeg header files, or use default included headers. If supplied, headerPaths will be tried in order, so multiple build platforms can be supported.
  • Specify which FFmpeg libraries (FFmpegLibrary.avCodec, etc.), (all by default), should be included.
  • Pass standard FfiGen() include/exclude options via strongly-typed options of Set<String> for functions, structs, macros, enums, etc. using FFInclude({...}), FFExclude({...}), ffAllowAll, or ffDenyAll.
  • Customize the generated class name for functions (FFmpeg by default).
  • Pass custom llvmPaths to FfiGen() (optional).

Getting started

Prerequisites

  • Flutter is not required. Only Dart + the package dependencies are required for code generation.
  • Actually running your FFI code requires an FFmpeg binary (either executable CLI or dylib, e.g. in the fvp package for Flutter).
  • This package does not require fvp or its mdk-sdk. Any FFmpeg binary built with the functions/features used and compatible with both the target system and the version of headers used to build the bindings will work.

Installation

  • Add the 4 required packages:
dart pub add ffipeg
dart pub add ffi
dart pub add --dev ffipeg_builder
dart pub add --dev build_runner

Usage

  • You will need to ensure the FFmpeg binary is available in your built Flutter app or Dart executable's path.
    • You may need a specific Platform switch to specify the path/name passed into the DynamicLibrary() constructor.

Refer to the FFmpegGen class source documentation for specific usage of the annotation.

Refer to the example code above to get started, or ffipeg_muxer package for a working CLI/Dart class example demonstratng how to mux an audio and video file without transcoding (copies the codecs).

Premise

There is currently no simple way of including the FFmpeg binary in a cross-platform Flutter desktop app. ffmpeg_kit_flutter does not offer a Windows or Linux version (Why not? They already have a build pipeline for 3 platforms...).

The only solution I found was fvp, which includes the FFmpeg binary via its bundled mdk-sdk, but it offers no FFmpeg API itself. And including both fvp and a built FFmpeg binary in my app would introduce too much bloat for the one function I needed.

Therefore, I learned to use FFmpeg through FFI and created this package.

Contributing

Contributions are welcome, especially if any bugs are found. Please open an issue in the repo at https://github.com/dra11y/ffipeg-dart.

About

Dart FFI bindings generator for FFmpeg

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages