ARTIKEL WEB DEVELOPMENT 1+

Mengapa FFmpeg.wasm Gagal Memanfaatkan GPU Acceleration di Browser Modern

8 Februari 2026
Image for Mengapa FFmpeg.wasm Gagal Memanfaatkan GPU Acceleration di Browser Modern

Implementasi video processing di browser menggunakan FFmpeg.wasm sering kali menghadapi situasi yang membingungkan. Semuanya berfungsi seperti yang diharapkan, tetapi performa tidak sesuai ekspektasi. Laptop mulai memanas, kipas berputar kencang, dan CPU bekerja sangat keras. Sementara itu, monitoring tool menunjukkan bahwa GPU hampir tidak terpakai sama sekali. Padahal hardware encoder di GPU seperti NVENC atau QuickSync sudah tersedia dan seharusnya bisa membantu mempercepat proses encoding.

FFmpeg.wasm sepertinya mengabaikan keberadaan hardware acceleration ini. Bukan karena bug atau kesalahan konfigurasi. Ini adalah konsekuensi langsung dari bagaimana WebAssembly dirancang untuk bekerja di dalam browser.

Arsitektur WebAssembly Sandbox dan Limitasinya

WebAssembly dirancang dengan satu prinsip keamanan yang sangat ketat. Berbeda dengan virtual machine tradisional atau container, WebAssembly menggunakan isolasi berbasis software yang lebih rigid. Setiap modul WebAssembly tidak memiliki akses langsung ke memory sistem host. Alih-alih, modul diberikan sebuah blok memory kontinu yang terisolasi sempurna dari sistem host. Semua operasi dalam WebAssembly bersifat relatif terhadap awal blok memory ini, bukan terhadap alamat memory fisik sistem.

Browser runtime melakukan pengecekan pada setiap akses memory untuk memastikan tidak ada instruksi yang keluar dari batas memory yang dialokasikan. Ini adalah pertukaran antara keamanan versus performa yang disengaja. Modul WebAssembly dijamin tidak bisa membaca password di RAM Anda, tidak bisa mengakses file system Anda, dan tidak bisa mengeksekusi system call sembarangan. Konsekuensinya adalah modul WebAssembly tidak memiliki jalur langsung untuk berkomunikasi dengan hardware apapun di sistem host, termasuk GPU, video encoder hardware, atau bahkan network interface.

Model keamanan WebAssembly dimulai dengan zero akses. Tidak seperti container Docker yang dimulai dengan akses penuh kemudian perlu dibatasi, modul WebAssembly dimulai tanpa kemampuan apapun. Modul hanya bisa berinteraksi dengan dunia luar melalui fungsi yang disediakan oleh JavaScript host, fungsi yang diekspor yang bisa dipanggil dari luar, atau melalui WebAssembly System Interface yang merupakan standar API untuk akses terkontrol ke resources. Tidak ada system call. Tidak ada akses hardware langsung. Tidak ada jalan keluar.

FFmpeg.wasm dan Keterbatasan Fundamentalnya

FFmpeg.wasm adalah hasil transpilasi dari FFmpeg source code C/C++ ke WebAssembly menggunakan Emscripten. Proses ini mengkonversi function calls, pointer arithmetic, dan system calls menjadi instruksi WebAssembly yang bisa berjalan di browser. Yang tidak bisa ditranspilasi adalah akses langsung ke hardware untuk video encoding dan decoding acceleration.

Ketika FFmpeg native di sistem operasi melakukan video encoding dengan H.264, prosesnya bisa menggunakan dua jalur yang sangat berbeda. Jalur software menggunakan encoder CPU yang menggunakan optimisasi tingkat rendah. Saat dikompilasi ke WebAssembly, optimisasi ini ditranspilasi menjadi instruksi WebAssembly, tetapi performanya tidak sebanding dengan kode native. Benchmark menunjukkan FFmpeg.wasm berjalan pada 40fps untuk konversi 720p, sementara FFmpeg native bisa mencapai 500fps pada hardware yang sama.

Jalur hardware melewati CPU sepenuhnya. Frame video di-upload ke memory GPU, hardware encoder chip melakukan kompresi menggunakan sirkuit elektronik khusus yang dirancang untuk algoritma H.264 atau H.265. Tidak ada instruksi CPU yang dieksekusi untuk encoding itu sendiri. FFmpeg.wasm tidak bisa mengakses jalur kedua sama sekali. Sandbox memory WebAssembly mencegah modul untuk mengakses GPU memory space, memanggil driver APIs, atau mengeksekusi system call untuk hardware encoder. Hasilnya adalah FFmpeg.wasm terpaksa menggunakan software encoding murni, yang berjalan di CPU JavaScript engine, di dalam sandbox WebAssembly, dengan overhead tambahan pada setiap memory access.

Overhead Berlapis yang Membuat Performa Buruk

Ketika FFmpeg.wasm dijalankan, frame video melalui beberapa tahap dengan overhead masing-masing. File di-load ke JavaScript ArrayBuffer, kemudian di-copy ke memory WebAssembly. FFmpeg decoder dijalankan dalam WebAssembly dengan setiap pixel access melewati pengecekan batas memory. Encoder dijalankan tanpa akses ke optimisasi tingkat rendah native. Encoded bitstream di-copy dari memory WebAssembly kembali ke JavaScript untuk di-download. Tidak ada tahap dalam pipeline ini yang bisa di-offload ke GPU hardware encoder.

WebCodecs API sebagai Jalur Resmi

Browser vendors menyadari bottleneck ini. Mereka tidak membuka sandbox WebAssembly untuk hardware access langsung karena itu akan menghancurkan model keamanan, tetapi memberikan API JavaScript baru yang memiliki akses privileged ke hardware encoders. API ini disebut WebCodecs. WebCodecs diperkenalkan di Chrome 94 pada tahun 2021 dan memberikan akses tingkat rendah ke VideoDecoder untuk hardware-accelerated video decoding, VideoEncoder untuk hardware-accelerated video encoding, AudioDecoder dan AudioEncoder untuk codec audio, serta VideoFrame untuk akses langsung ke decoded video frames.

Yang krusial adalah WebCodecs tidak berjalan di dalam sandbox WebAssembly. API ini adalah JavaScript API native yang diimplementasikan langsung di browser engine dengan akses privileged ke codec APIs tingkat sistem operasi. Ketika video di-decode dengan WebCodecs, browser memanggil OS codec API seperti VA-API di Linux, Video Toolbox di macOS, atau Media Foundation di Windows. Encoded bitstream di-upload ke GPU memory. Hardware decoder melakukan decompression. Yang penting adalah decoded frame tetap di GPU memory sebagai texture. JavaScript mendapat handle ke VideoFrame yang reference GPU memory tersebut. Tidak ada copy dari GPU ke CPU. Tidak ada overhead sandbox. Frame bisa langsung di-pass ke Canvas rendering, WebGL shader, atau WebGPU compute pipeline.

Library yang Memanfaatkan WebCodecs

Karena WebCodecs API masih relatif tingkat rendah dan memerlukan handling manual untuk container format, multiplexing audio dan video tracks, codec configuration, dan compatibility checks, ekosistem library telah muncul untuk mengabstraksi kompleksitas ini.

MediaBunny adalah library TypeScript yang menyatukan kemampuan reading untuk demultiplex berbagai container format seperti MP4, MOV, WebM, MKV, WAV, MP3, FLAC, dan lainnya. Library ini juga menyediakan writing untuk multiplex video dan audio ke container dengan format yang bisa diganti, serta converting yang menggabungkan reading, decoding via WebCodecs, encoding via WebCodecs, dan writing.

Yang membedakan MediaBunny dari FFmpeg.wasm adalah cara kerjanya di balik layar. MediaBunny men-demux container menggunakan parser JavaScript murni yang cepat karena hanya parsing metadata. Kemudian men-decode compressed packets menggunakan WebCodecs VideoDecoder yang hardware accelerated. Men-encode decoded frames menggunakan WebCodecs VideoEncoder yang hardware accelerated. Dan men-mux encoded packets ke container baru menggunakan JavaScript murni yang cepat. Tidak ada sandbox WebAssembly. Tidak ada CPU encoding. Semuanya berjalan di GPU video engine yang sama yang digunakan oleh aplikasi native video editor.

Sebelum MediaBunny, developer menggunakan mp4-muxer dan webm-muxer. Keduanya adalah library TypeScript murni untuk writing MP4 containers dan WebM containers. Kedua library ini dirancang untuk bekerja dengan WebCodecs. Tidak ada intermediary WebAssembly. Tidak ada copy ke CPU. Encoded chunks langsung dari hardware encoder masuk ke muxer JavaScript. MediaBunny pada dasarnya adalah evolusi dan unifikasi dari mp4-muxer dan webm-muxer dengan tambahan kemampuan reading, demuxing, dan conversion.

Perbandingan Performa yang Dramatis

high-performance-mediabunny

Benchmark menunjukkan perbedaan yang sangat signifikan. FFmpeg.wasm untuk 1080p H.264 encoding mencapai sekitar 25fps pada MacBook Pro 2018 dengan CPU usage 100% pada semua cores, GPU usage 0%, dan memory usage lebih dari 2GB. Sementara itu WebCodecs dengan MediaBunny untuk 1080p H.264 encoding mencapai sekitar 200fps pada hardware yang sama, delapan kali lebih cepat. CPU usage hanya sekitar 15% yang digunakan hanya untuk demuxing dan muxing JavaScript. GPU usage sekitar 40% pada video encoder engine dan memory usage di bawah 500MB.

Perbedaan ini lebih dramatis lagi untuk resolusi 4K atau codec modern seperti H.265 atau AV1 yang jauh lebih intensif secara komputasi untuk software encoding.

Kapan Menggunakan Masing-Masing Solusi

FFmpeg.wasm masih memiliki tempatnya. Gunakan FFmpeg.wasm jika memerlukan codec atau format yang tidak didukung WebCodecs seperti ProRes, DNxHD, atau exotic containers. Gunakan juga jika perlu menggunakan FFmpeg filters yang kompleks seperti colorspace conversion, deinterlacing, atau complex filter graphs. Cross-browser compatibility termasuk browser yang belum support WebCodecs seperti Firefox yang masih partial support juga menjadi alasan. Portability ke non-browser environment seperti Node.js via WebAssembly adalah pertimbangan lain.

Gunakan WebCodecs ditambah MediaBunny jika performa adalah prioritas utama. Jika hanya berurusan dengan codec modern yang widely supported seperti H.264, H.265, VP8, VP9, atau AV1. Jika target audience menggunakan Chromium-based browsers seperti Chrome, Edge, atau Opera. Jika menginginkan efficient battery usage di mobile devices karena hardware encoding sekitar sepuluh kali lebih power-efficient. Atau jika aplikasi memerlukan real-time video processing seperti live streaming atau video conferencing.

Kesimpulan

FFmpeg.wasm tidak bisa menggunakan GPU acceleration bukan karena bug atau limitation teknis dari FFmpeg itu sendiri, melainkan karena design decision fundamental dari WebAssembly security model. Sandbox yang melindungi user dari malicious code juga menghalangi code tersebut dari mengakses hardware acceleration yang bisa meningkatkan performa secara drastis.

Browser vendors telah menyediakan jalur alternatif melalui WebCodecs API, sebuah JavaScript API privileged yang memiliki akses ke hardware encoder dan decoder yang sama yang digunakan oleh native applications. Library seperti MediaBunny, mp4-muxer, dan webm-muxer telah membuktikan bahwa dengan memanfaatkan jalur ini, browser-based video processing bisa mencapai performa yang comparable dengan native desktop applications sambil tetap menjaga security sandbox yang melindungi user.

Ketika mengalami CPU spike 100% saat menggunakan FFmpeg.wasm, ini bukan kesalahan konfigurasi. Ini adalah architectural limitation. Solusinya bukan mengoptimasi FFmpeg.wasm configuration, melainkan migrasi ke WebCodecs-based pipeline untuk task-task yang memerlukan hardware acceleration. Performa CPU, konsumsi battery, dan user experience akan meningkat signifikan dengan pendekatan ini.

WebCodecs API saat ini fully supported di Chromium-based browsers seperti Chrome 94+, Edge 94+, Safari 16.4+, dan partial support di Firefox. Untuk production deployment, lakukan feature detection dan fallback strategy.