I'm trying to get ffmpeg-kit-audio-6.0-2.LTS.arr to compile and function in my Android App. The arr file is located in the Assets/Plugins/Android folder and so are the smart-exception-java-0.2.1.jar and the smart-exception-common-0.2.1.jar. I Try to use the library like this:
using UnityEngine;
using System.IO;
namespace Mixer
{
public class AndroidFFmpegKitEncoder : IAudioEncoder
{
public int Encode(float[] stereoBuffer, int sampleRate, string outputPath, string format, int bitrate = 320)
{
try
{
// TEST: FFmpeg-Version
using (AndroidJavaClass ffmpegKit = new AndroidJavaClass("com.arthenica.ffmpegkit.FFmpegKit"))
{
AndroidJavaObject versionSession = ffmpegKit.CallStatic<AndroidJavaObject>("execute", new object[] { "-version" });
if (versionSession != null)
{
string verOutput = versionSession.Call<string>("getOutput", new object[] { });
Debug.Log($"[AndroidFFmpegKitEncoder] FFmpeg Version:\n{verOutput}");
}
else
{
Debug.LogError("[AndroidFFmpegKitEncoder] Version-Session is null!");
}
}
}
catch (System.Exception ex)
{
Debug.LogError($"[AndroidFFmpegKitEncoder] Version-Test failed: {ex.Message}");
}
try
{
// 1. Float-Buffer → 16-Bit PCM
short[] pcm16 = ConvertToPCM16(stereoBuffer);
byte[] pcmBytes = new byte[pcm16.Length * 2];
System.Buffer.BlockCopy(pcm16, 0, pcmBytes, 0, pcmBytes.Length);
// 2. Temp WAV-Datei write
string tempWavPath = Path.Combine(Path.GetDirectoryName(outputPath),
Path.GetFileNameWithoutExtension(outputPath) + "_temp.wav");
WriteTempWav(pcm16, sampleRate, tempWavPath);
// 3. FFmpeg-Command as single String (wie in der Doku)
string ffmpegCmd = $"-y -i \"{tempWavPath}\" -c:a libmp3lame -b:a {bitrate}k -ar {sampleRate} -ac 2 \"{outputPath}\"";
// 4. ignore SIGXCPU-Signal
using (AndroidJavaClass configClass = new AndroidJavaClass("com.arthenica.ffmpegkit.FFmpegKitConfig"))
using (AndroidJavaClass signalClass = new AndroidJavaClass("com.arthenica.ffmpegkit.Signal"))
{
AndroidJavaObject sigxcpu = signalClass.GetStatic<AndroidJavaObject>("SIGXCPU");
configClass.CallStatic("ignoreSignal", new object[] { sigxcpu });
}
// 5. execute() - returns session ID
AndroidJavaObject session;
using (AndroidJavaClass ffmpegKit = new AndroidJavaClass("com.arthenica.ffmpegkit.FFmpegKit"))
{
session = ffmpegKit.CallStatic<AndroidJavaObject>("execute", new object[] { ffmpegCmd });
}
// 6. Check result (see documentation)
if (session != null)
{
AndroidJavaObject returnCode = session.Call<AndroidJavaObject>("getReturnCode", new object[] { });
int rc = returnCode.Call<int>("getValue", new object[] { });
string output = session.Call<string>("getOutput", new object[] { });
Debug.Log($"[AndroidFFmpegKitEncoder] FFmpeg Output:\n{output}");
if (rc == 0)
{
Debug.Log($"[AndroidFFmpegKitEncoder] {format.ToUpper()} gespeichert: {outputPath}");
TryDelete(tempWavPath);
return 0;
}
else
{
Debug.LogError($"[AndroidFFmpegKitEncoder] FFmpeg failed (Code: {rc}). Output:\n{output}");
return -1;
}
}
else
{
Debug.LogError("[AndroidFFmpegKitEncoder] FFmpegKit.execute() null.");
return -1;
}
}
catch (System.Exception ex)
{
Debug.LogError($"[AndroidFFmpegKitEncoder] Fehler: {ex.Message}");
return -1;
}
}
private short[] ConvertToPCM16(float[] stereoBuffer)
{
short[] pcm16 = new short[stereoBuffer.Length];
for (int i = 0; i < stereoBuffer.Length; i++)
{
float clamped = Mathf.Clamp(stereoBuffer[i], -1f, 1f);
pcm16[i] = (short)(clamped * 32767f);
}
return pcm16;
}
private void WriteTempWav(short[] pcm16, int sampleRate, string path)
{
int totalSamples = pcm16.Length;
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
using (BinaryWriter bw = new BinaryWriter(fs))
{
int channels = 2;
int bitsPerSample = 16;
int byteRate = sampleRate * channels * (bitsPerSample / 8);
int blockAlign = channels * (bitsPerSample / 8);
int dataSize = totalSamples * (bitsPerSample / 8);
int chunkSize = 36 + dataSize;
bw.Write(new[] { 'R', 'I', 'F', 'F' });
bw.Write(chunkSize);
bw.Write(new[] { 'W', 'A', 'V', 'E' });
bw.Write(new[] { 'f', 'm', 't', ' ' });
bw.Write(16);
bw.Write((short)1); // PCM
bw.Write((short)channels);
bw.Write(sampleRate);
bw.Write(byteRate);
bw.Write((short)blockAlign);
bw.Write((short)bitsPerSample);
bw.Write(new[] { 'd', 'a', 't', 'a' });
bw.Write(dataSize);
byte[] bytes = new byte[totalSamples * 2];
System.Buffer.BlockCopy(pcm16, 0, bytes, 0, bytes.Length);
bw.Write(bytes);
}
}
private string GetCodec(string format)
{
return format.ToLower() switch
{
"mp3" => "-c:a libmp3lame -b:a 320k",
"flac" => "-c:a flac",
"aac" => "-c:a aac -b:a 320k",
"ogg" => "-c:a libvorbis -q:a 5",
"wav" => "-c:a pcm_s16le",
_ => "-c:a libmp3lame -b:a 320k"
};
}
private void TryDelete(string path)
{
try { if (File.Exists(path)) File.Delete(path); }
catch { }
}
}
}
But I'm constantly getting errors like:
2026.07.26 12:36:33.470 7684 8113 Error Unity [AndroidFFmpegKitEncoder] FFmpegKit.execute null. 2026.07.26 12:36:33.470 7684 8113 Error Unity Mixer.AndroidFFmpegKitEncoder:Encode(Single[], Int32, String, String, Int32) 2026.07.26 12:36:33.470 7684 8113 Error Unity Mixer.MixdownFileWriter:WriteFormatted(String, Single[], Int32, String, Int32) 2026.07.26 12:36:33.470 7684 8113 Error Unity Mixer.<>c__DisplayClass62_0:<RenderMasterMixdownCoroutine>b__0() 2026.07.26 12:36:33.470 7684 8113 Error Unity System.Threading.Tasks.Task`1:InnerInvoke() 2026.07.26 12:36:33.470 7684 8113 Error Unity System.Threading.Tasks.Task:Execute() 2026.07.26 12:36:33.470 7684 8113 Error Unity System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean) 2026.07.26 12:36:33.470 7684 8113 Error Unity System.Threading.Tasks.Task:ExecuteWithThreadLocal(Task&) 2026.07.26 12:36:33.470 7684 8113 Error Unity System.Threading.Tasks.Task:ExecuteEntry(Boolean) 2026.07.26 12:36:33.470 7684 8113 Error Unity System.Threading.ThreadPoolWorkQueue:Dispatch()
Even the Version testing Code in the beginning always returns null:
Has anyone experienced similar problems while working with FFmpeg in Unity or does someone know a Code Source where FFmpeg integration for Unity Android is successful?