mpeg 1.0.0 copy "mpeg: ^1.0.0" to clipboard
mpeg: ^1.0.0 copied to clipboard

Spawn ffmpeg and ffprobe from dart:io, probe media metadata, and inspect supported formats.

mpeg #

mpeg is a small Dart wrapper around the system ffmpeg and ffprobe binaries. It uses dart:io processes directly, so it works well in server-side Dart apps, Docker containers, and macOS environments where FFmpeg is installed on the host.

Features #

  • Check whether ffmpeg and ffprobe are available with MpegClient.isSupported()
  • Read parsed ffmpeg and ffprobe version information
  • Run ffmpeg and ffprobe commands with Process.run or Process.start
  • Decode ffprobe JSON output with probeJson()
  • Pull out parsed format metadata, streams, duration, bitrate, and primary video/audio streams
  • Parse ffmpeg -formats / ffprobe -formats output into structured MpegFormat objects
  • Resolve common supported video file extensions from the detected format list for both input and output support
  • Use low-friction helpers for generic transcode, remux, and still-frame extraction
  • Configure executable paths, base arguments, environment variables, and shell behavior

Installation #

Add the package:

dart pub add mpeg

You also need FFmpeg installed on the machine that runs your Dart code.

Docker Linux #

For Debian/Ubuntu-based Docker images, install FFmpeg like this:

RUN apt-get update && apt-get install -y ffmpeg

That installs both ffmpeg and ffprobe.

macOS #

Install FFmpeg with Homebrew:

brew install ffmpeg

You can verify the install with:

ffmpeg -version
ffprobe -version

Usage #

Check whether FFmpeg is available #

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  bool supported = await MpegClient.isSupported();
  if (!supported) {
    throw StateError('ffmpeg/ffprobe are not installed or not on PATH.');
  }
}

Inspect supported formats #

getFormats() parses the real -formats output from ffprobe first, then falls back to ffmpeg if needed.

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  MpegClient client = MpegClient();

  List<MpegFormat> formats = await client.getFormats();
  for (MpegFormat format in formats.take(5)) {
    print(
      '${format.primaryName}: demux=${format.canDemux}, mux=${format.canMux}, '
      'device=${format.isDevice}',
    );
  }

  List<String> inputExtensions =
      await client.getSupportedVideoInputExtensions();
  List<String> outputExtensions =
      await client.getSupportedVideoOutputExtensions();
  print('Inputs: $inputExtensions');
  print('Outputs: $outputExtensions');
}

getSupportedVideoExtensions() resolves common video file extensions from the parsed format names. The input/output convenience methods are useful when you want to answer questions like "which video extensions can this machine decode?" versus "which containers can it mux?"

Read ffmpeg version information #

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  MpegClient client = MpegClient();

  MpegVersionInfo ffmpegVersion = await client.getFfmpegVersionInfo();
  MpegVersionInfo ffprobeVersion = await client.getFfprobeVersionInfo();

  print(ffmpegVersion.version);
  print(ffprobeVersion.configurationLine);
}

Probe targeted metadata helpers #

If you do not want to manually walk the full JSON payload, the client exposes small convenience helpers:

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  MpegClient client = MpegClient();

  Duration? duration = await client.probeDuration(inputPath: 'output.mp4');
  int? bitRate = await client.probeBitRate(inputPath: 'output.mp4');
  Map<String, dynamic>? videoStream = await client.probePrimaryVideoStream(
    inputPath: 'output.mp4',
  );

  print(duration);
  print(bitRate);
  print(videoStream?['width']);
}

Transcode a file and probe the result #

import 'dart:convert';
import 'dart:io';

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  MpegClient client = MpegClient();
  File inputFile = File('input.mov');
  File outputFile = File('output.mp4');

  ProcessResult result = await client.runFfmpeg([
    '-y',
    '-i',
    inputFile.path,
    '-vf',
    'scale=1280:720',
    '-c:v',
    'libx264',
    '-pix_fmt',
    'yuv420p',
    '-movflags',
    '+faststart',
    outputFile.path,
  ]);

  if (result.exitCode != 0) {
    stderr.writeln(result.stderr);
    return;
  }

  Map<String, dynamic> metadata = await client.probeJson(
    inputPath: outputFile.path,
  );
  print(const JsonEncoder.withIndent('  ').convert(metadata));
}

Use the convenience operations #

These are just thin wrappers around common ffmpeg command shapes, so you still control the real ffmpeg flags.

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  MpegClient client = MpegClient();

  await client.transcode(
    inputPath: 'input.mov',
    outputPath: 'output.mp4',
    ffmpegArguments: [
      '-vf',
      'scale=1280:720',
      '-c:v',
      'libx264',
      '-pix_fmt',
      'yuv420p',
    ],
  );

  await client.remux(
    inputPath: 'input.mov',
    outputPath: 'faststart.mp4',
    ffmpegArguments: ['-movflags', '+faststart'],
  );

  await client.extractFrame(
    inputPath: 'input.mov',
    outputPath: 'thumbnail.png',
    position: const Duration(milliseconds: 500),
    width: 320,
    height: 180,
  );
}

Stream process output with Process.start #

If you want progress events or long-running streaming output, use startFfmpeg() or startFfprobe():

import 'dart:convert';
import 'dart:io';

import 'package:mpeg/mpeg.dart';

Future<void> main() async {
  MpegClient client = MpegClient();
  Process process = await client.startFfmpeg(
    arguments: [
      '-i',
      'input.mov',
      '-progress',
      'pipe:2',
      'output.mp4',
    ],
  );

  await for (String line in process.stderr
      .transform(utf8.decoder)
      .transform(const LineSplitter())) {
    print(line);
  }

  int exitCode = await process.exitCode;
  print('ffmpeg exited with $exitCode');
}

Configuration #

You can point the client at custom binary paths or wrapper commands:

import 'package:mpeg/mpeg.dart';

MpegClient client = MpegClient(
  ffmpegExecutable: '/usr/local/bin/ffmpeg',
  ffprobeExecutable: '/usr/local/bin/ffprobe',
  workingDirectory: '/tmp',
  environment: {'FFREPORT': 'file=ffreport.log:level=32'},
);

API Overview #

  • MpegClient.isSupported() checks whether ffmpeg and optionally ffprobe can be started
  • runFfmpeg() and runFfprobe() wrap Process.run
  • startFfmpeg() and startFfprobe() wrap Process.start
  • probeJson() returns decoded ffprobe JSON
  • probeFormat(), probeStreams(), probeDuration(), probeBitRate(), probePrimaryVideoStream(), and probePrimaryAudioStream() provide targeted probe helpers
  • getFormats() returns parsed MpegFormat rows from -formats
  • getSupportedVideoExtensions(), getSupportedVideoInputExtensions(), and getSupportedVideoOutputExtensions() return common video extensions inferred from the detected formats
  • getFfmpegVersionInfo() and getFfprobeVersionInfo() parse version output into MpegVersionInfo
  • transcode(), remux(), and extractFrame() wrap common ffmpeg operations
  • MpegException includes the command, arguments, exit code, stdout, stderr, and original cause when available
0
likes
150
points
86
downloads

Documentation

API reference

Publisher

verified publisherarcane.art

Weekly Downloads

Spawn ffmpeg and ffprobe from dart:io, probe media metadata, and inspect supported formats.

Repository (GitHub)
View/report issues

License

GPL-3.0 (license)

More

Packages that depend on mpeg