Skip to content

FFmpegKit Memory Protocol

Taner Sener edited this page Jul 5, 2026 · 2 revisions

ffkitmem: lets FFmpegKit expose memory as a seekable URL. Use it when the whole input already exists in memory and should be read by FFmpeg or FFprobe, or when you want FFmpeg's whole output returned as bytes after the command finishes.

Android

In-Memory Input

val bytes: ByteArray = loadInputBytes()
val input = FFmpegKitInputBuffer.fromByteArray(bytes, "mp3")

try {
    FFmpegKit.execute("-i ${input.getUrl()} -c:a aac ${context.cacheDir}/out.m4a")
} finally {
    input.close()
}

Android can also register a direct byte buffer:

val directBuffer: ByteBuffer = makeDirectBuffer()
val input = FFmpegKitInputBuffer.fromDirectByteBuffer(
    directBuffer,
    directBuffer.remaining(),
    "wav"
)

In-Memory Output

val output = FFmpegKitOutputBuffer.create("mp4")

try {
    FFmpegKit.execute("-i ${context.cacheDir}/input.mov -c:v mpeg4 ${output.getUrl()}")

    val resultBytes = output.toByteArray()
    saveResult(resultBytes)
} finally {
    output.close()
}

To limit memory growth:

val output = FFmpegKitOutputBuffer.create(
    "mp4",
    initialCapacity = 64L * 1024L,
    maxCapacity = 20L * 1024L * 1024L
)

The extension is a format hint for FFmpeg. Use values like "mp4", "wav", "mp3", or another suitable format name.

Apple

Apple uses the same wrapper names with Objective-C-style factory methods:

FFmpegKitInputBuffer *input =
    [FFmpegKitInputBuffer fromData:data extension:@"mp3"];

[FFmpegKit execute:
    [NSString stringWithFormat:@"-i %@ -c:a aac out.m4a", [input getUrl]]];

[input close];

For output:

FFmpegKitOutputBuffer *output = [FFmpegKitOutputBuffer create:@"mp4"];

[FFmpegKit execute:
    [NSString stringWithFormat:@"-i input.mov -c:v mpeg4 %@",
                               [output getUrl]]];

NSData *bytes = [output toData];
[output close];

Apple byte data is passed as NSData.

Linux

Linux uses C++ wrappers:

auto input = ffmpegkit::FFmpegKitInputBuffer::fromByteArray(data, "mp3");

ffmpegkit::FFmpegKit::execute(
    "-i " + input->getUrl() + " -c:a aac out.m4a");

input->close();

For output:

auto output = ffmpegkit::FFmpegKitOutputBuffer::create("mp4");

ffmpegkit::FFmpegKit::execute(
    "-i input.mov -c:v mpeg4 " + output->getUrl());

auto bytes = output->toByteArray();
output->close();

Linux byte data is passed as std::vector<uint8_t> or raw byte pointers, depending on the helper.

Flutter

Flutter exposes asynchronous wrappers:

final input = await FFmpegKitInputBuffer.fromByteArray(bytes, 'mp3');

try {
  await FFmpegKit.execute('-i ${input.getUrl()} -c:a aac out.m4a');
} finally {
  await input.close();
}

For output:

final output = await FFmpegKitOutputBuffer.create(extension: 'mp4');

try {
  await FFmpegKit.execute('-i input.mov -c:v mpeg4 ${output.getUrl()}');
  final bytes = await output.toByteArray();
} finally {
  await output.close();
}

Use initialCapacity and maxCapacity with FFmpegKitOutputBuffer.create when you want to bound output memory.

React Native

React Native exchanges binary data with the native layer as base64 strings.

const input = await FFmpegKitInputBuffer.fromBase64(base64Input, 'mp3');

try {
  await FFmpegKit.execute(`-i ${input.getUrl()} -c:a aac out.m4a`);
} finally {
  await input.close();
}

For output:

const output = await FFmpegKitOutputBuffer.create('mp4');

try {
  await FFmpegKit.execute(`-i input.mov -c:v mpeg4 ${output.getUrl()}`);
  const resultBase64 = await output.toBase64();
} finally {
  await output.close();
}

Notes

  • Input buffers are finite. Reading beyond the registered data ends the input.
  • Output buffers grow as FFmpeg writes, up to the configured maximum capacity.
  • Always call close() when done, even if the FFmpeg command fails.

Clone this wiki locally