FFmpeg in Unity for Android and iOS Build


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?

0
Jul 26 at 1:34 PM
User AvatarMisterIX
#android#unity-game-engine#ffmpeg#android-ffmpeg

No answer found for this question yet.