Skip to content

FFmpegKit SAF Protocol

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

ffkitsaf: lets FFmpegKit use Android Storage Access Framework documents in FFmpeg and FFprobe commands. Use it when a user selected a content://... URI with Android's document picker.

This protocol is Android-only.

Android

Read from a selected document:

val inputUrl = FFmpegKitConfig.getSafParameterForRead(context, uri)

FFmpegKit.execute("-i $inputUrl -c:v mpeg4 ${context.cacheDir}/output.mp4")

Write to a selected document:

val outputUrl = FFmpegKitConfig.getSafParameterForWrite(context, uri)

FFmpegKit.execute("-i ${context.cacheDir}/input.mp4 -c:v mpeg4 $outputUrl")

For a custom Android file open mode:

val url = FFmpegKitConfig.getSafParameter(context, uri, "rw")

SAF URLs are single-use by default. To reuse one, create it with the reusable flag and unregister it after the last command:

val url = FFmpegKitConfig.getSafParameterForRead(context, uri, true)

// Use url in one or more FFmpeg commands.

FFmpegKitConfig.unregisterSafProtocolUrl(url)

You can also call FFmpegKitConfig.setSafUrlsReusable(true) to change the default for newly created SAF URLs. A per-url reusable flag overrides that default.

SAF support requires Android API level 19 or newer. On older Android versions, the helper returns an empty URL.

Flutter

Flutter exposes the SAF helpers through FFmpegKitConfig:

final inputUrl = await FFmpegKitConfig.getSafParameterForRead(uriString);
final outputUrl = await FFmpegKitConfig.getSafParameterForWrite(uriString);
final customUrl = await FFmpegKitConfig.getSafParameter(uriString, 'rw');

Use the returned URL in an FFmpeg command:

await FFmpegKit.execute('-i $inputUrl -c:v mpeg4 output.mp4');

Create a reusable URL when the same SAF document must be used in multiple commands:

final reusableInputUrl = await FFmpegKitConfig.getSafParameterForRead(uriString, true);

try {
  await FFprobeKit.execute('-hide_banner -show_streams $reusableInputUrl');
  await FFprobeKit.execute('-hide_banner -show_format $reusableInputUrl');
} finally {
  await FFmpegKitConfig.unregisterSafProtocolUrl(reusableInputUrl);
}

These Flutter methods are Android-only. They fail on iOS, macOS and Linux.

React Native

React Native exposes the SAF helpers through FFmpegKitConfig:

const inputUrl = await FFmpegKitConfig.getSafParameterForRead(uriString);
const outputUrl = await FFmpegKitConfig.getSafParameterForWrite(uriString);
const customUrl = await FFmpegKitConfig.getSafParameter(uriString, 'rw');

Use the returned URL in an FFmpeg command:

await FFmpegKit.execute(`-i ${inputUrl} -c:v mpeg4 output.mp4`);

Create a reusable URL when the same SAF document must be used in multiple commands:

const reusableInputUrl = await FFmpegKitConfig.getSafParameterForRead(uriString, true);

try {
  await FFprobeKit.execute(`-hide_banner -show_streams ${reusableInputUrl}`);
  await FFprobeKit.execute(`-hide_banner -show_format ${reusableInputUrl}`);
} finally {
  await FFmpegKitConfig.unregisterSafProtocolUrl(reusableInputUrl);
}

These React Native methods are Android-only.

Notes

  • Do not build ffkitsaf: URLs yourself. Use the helper methods.
  • ffkitsaf: URLs represent registered Android document descriptors, not real filesystem paths.
  • Delete, move, and existence-check operations are not supported through this protocol.

Clone this wiki locally