FFmpeg.wasm: Analisis Teknologi WebAssembly untuk Menjalankan FFmpeg di Browser

FFmpeg.wasm Browser

FFmpeg.wasm adalah versi alat pemrosesan audio dan video sumber terbuka terkenal FFmpeg yang dikompilasi ke WebAssembly melalui Emscripten. Teknologi ini memungkinkan browser untuk melakukan operasi kompleks seperti dekode video, transkode, dan penggabungan langsung di sisi klien tanpa bergantung pada server backend.

Tautan Proyek: github.com/ffmpegwasm/ffmpeg.wasm

Arsitektur Tradisional vs Arsitektur FFmpeg.wasm

Arsitektur Tradisional (Backend Transcoding):
Pengguna → Unggah Video → Server FFmpeg → Output → Pengguna Unduh
Masalah: Konsumsi sumber daya CPU server tinggi, biaya bandwidth mahal, masalah privasi

Arsitektur FFmpeg.wasm:
Pengguna → FFmpeg.wasm di Browser → Output Blob → Pengguna Unduh
Kelebihan: Nol biaya server, jaminan privasi, dapat digunakan secara offline

Inti Teknologi: Apa itu WebAssembly?

WebAssembly (Wasm) adalah format biner tingkat rendah yang dirancang agar kode dari bahasa yang dikompilasi (seperti C, C++, Rust) dapat dijalankan di browser dengan kecepatan mendekati aplikasi asli (native).

Kode sumber FFmpeg ditulis dalam bahasa C. Toolchain Emscripten dapat mengompilasi kode C tersebut menjadi modul biner .wasm, yang bekerja bersama kode perekat (glue code) JavaScript (ffmpeg-core.js) untuk dijalankan di lingkungan browser.

Dua Mode Operasi FFmpeg.wasm

Mode Single-threaded (Utas Tunggal)

import { FFmpeg } from '@ffmpeg/ffmpeg';
import { toBlobURL } from '@ffmpeg/util';

const ffmpeg = new FFmpeg();
await ffmpeg.load({
  coreURL: await toBlobURL(
    'https://unpkg.com/@ffmpeg/[email protected]/dist/esm/ffmpeg-core.js',
    'text/javascript'
  ),
  wasmURL: await toBlobURL(
    'https://unpkg.com/@ffmpeg/[email protected]/dist/esm/ffmpeg-core.wasm',
    'application/wasm'
  ),
});
  • Tidak membutuhkan SharedArrayBuffer
  • Tidak membutuhkan Header HTTP khusus (COOP/COEP)
  • Semua operasi dilakukan dalam satu thread JS (Worker)
  • Cocok untuk deploy di kebanyakan situs statis (Cloudflare Pages, GitHub Pages, dll.)

Mode Multi-threaded (Banyak Utas)

await ffmpeg.load({
  coreURL: 'ffmpeg-core-mt.js',  // core versi multi-threaded
  wasmURL: 'ffmpeg-core-mt.wasm',
  workerURL: 'ffmpeg-core-mt.worker.js',
});
  • Menggunakan SharedArrayBuffer untuk berbagi memori di antara beberapa Web Worker
  • Memerlukan server untuk mengatur Header HTTP berikut:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
  • Peningkatan kecepatan yang signifikan (dapat memanfaatkan CPU multi-core)
  • Namun pengaturannya lebih kompleks dan beberapa CDN tidak mendukungnya

Sistem File Virtual (Emscripten FS)

FFmpeg.wasm tidak memiliki akses langsung ke disk lokal. Ia menggunakan Virtual File System (VFS) dari Emscripten untuk mensimulasikan operasi disk:

// Menulis ArrayBuffer ke VFS virtual
await ffmpeg.writeFile('input.ts', new Uint8Array(buffer));

// Menjalankan perintah FFmpeg (beroperasi di VFS virtual)
await ffmpeg.exec(['-i', 'input.ts', '-c', 'copy', 'output.mp4']);

// Membaca output
const data = await ffmpeg.readFile('output.mp4');

// Membersihkan memori (Penting!)
await ffmpeg.deleteFile('input.ts');
await ffmpeg.deleteFile('output.mp4');

Kunci: Data dalam VFS berada di dalam JavaScript Heap. Data harus dihapus secara manual setelah selesai digunakan, jika tidak maka akan membebani memori browser sampai halaman ditutup.

Batasan Memori dan Praktik Terbaik

Ini adalah batasan bawaan terbesar dari FFmpeg.wasm:

Item Batasan
Batas Atas JS Heap Sekitar 1-2 GB (Tergantung browser dan OS)
Model Memori Wasm Alamat 32-bit, batas atas modul tunggal 4 GB
Memori Tersedia Riil Biasanya 500 MB - 1.5 GB

Skenario Penggunaan yang Disarankan

  • ✅ Video di bawah 720p, durasi kurang dari 30 menit
  • ✅ Fokus utama pada concat (penggabungan fragmen), bukan transcoding ulang
  • ✅ Riset teknis dan pengujian tautan publik
  • ❌ Video panjang 4K/1080p (Memori tidak cukup)
  • ❌ Filter kompleks dan encoding ulang (Kecepatan terlalu lambat)

Praktik Terbaik Manajemen Memori

// 1. Unduh secara bertahap, hindari menampung semua ArrayBuffer sekaligus
const BATCH = 5;
for (let i = 0; i < segments.length; i += BATCH) {
  const batch = await downloadBatch(segments.slice(i, i + BATCH));
  // Segera tulis ke VFS, ArrayBuffer di sisi JS dapat didaur ulang
  for (const [idx, buf] of batch.entries()) {
    await ffmpeg.writeFile(`seg${i + idx}.ts`, new Uint8Array(buf));
  }
}

// 2. Segera bersihkan VFS setelah operasi selesai
await ffmpeg.deleteFile('output.mp4');

Perbandingan dengan API Backend

Aspek FFmpeg.wasm API Backend
Biaya Server Nol Tinggi (Padat CPU)
Privasi 100% (Pemrosesan Lokal) Harus mempercayai server
Kecepatan Proses Lambat (Wasm Utas Tunggal) Cepat (Multi-core + GPU)
Dukungan File Besar Dibatasi memori browser Hampir tanpa batas
Kompleksitas Deploy Sangat simpel (Aset Statis) Memerlukan pemeliharaan server
Skenario Terbaik Konversi skala kecil, alat riset Pemrosesan massal lingkungan produksi

Implementasi Nyata: Cara Kerja Situs Ini

Alat Riset HLS di situs ini menggunakan kombinasi berikut:

  • @ffmpeg/ffmpeg 0.12.x (Single-threaded, tidak butuh COOP/COEP)
  • @ffmpeg/core 0.12.x (Wasm Core yang sesuai)
  • Dimuat secara dinamis melalui unpkg CDN, pemuatan awal sekitar 15-30 detik (Modul Wasm sekitar 30MB)
  • Menjalankan ffmpeg -f concat -safe 0 -i concat.txt -c copy output.mp4 untuk menyelesaikan penggabungan TS

Bacaan Lebih Lanjut

Ingin menguji tautan M3U8 Anda sekarang?

🚀 Uji Pemutar M3U8 Online Sekarang