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
ffmpegandffprobeare available withMpegClient.isSupported() - Read parsed
ffmpegandffprobeversion information - Run
ffmpegandffprobecommands withProcess.runorProcess.start - Decode
ffprobeJSON output withprobeJson() - Pull out parsed format metadata, streams, duration, bitrate, and primary video/audio streams
- Parse
ffmpeg -formats/ffprobe -formatsoutput into structuredMpegFormatobjects - 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 whetherffmpegand optionallyffprobecan be startedrunFfmpeg()andrunFfprobe()wrapProcess.runstartFfmpeg()andstartFfprobe()wrapProcess.startprobeJson()returns decodedffprobeJSONprobeFormat(),probeStreams(),probeDuration(),probeBitRate(),probePrimaryVideoStream(), andprobePrimaryAudioStream()provide targeted probe helpersgetFormats()returns parsedMpegFormatrows from-formatsgetSupportedVideoExtensions(),getSupportedVideoInputExtensions(), andgetSupportedVideoOutputExtensions()return common video extensions inferred from the detected formatsgetFfmpegVersionInfo()andgetFfprobeVersionInfo()parse version output intoMpegVersionInfotranscode(),remux(), andextractFrame()wrap common ffmpeg operationsMpegExceptionincludes the command, arguments, exit code, stdout, stderr, and original cause when available
Libraries
- mpeg
- A lightweight Dart wrapper around
ffmpegandffprobe.