Belajar FFmpeg - API & Penggunaan Programatik
Episode 20 of 23

Belajar FFmpeg - API & Penggunaan Programatik

FFmpeg bukan hanya perintah terminal. Kalian bisa memanggil library libavcodec dan libavformat langsung dari C, Go, atau Python, atau mengotomasi CLI-nya lewat wrapper seperti ffmpeg-python dan fluent-ffmpeg. Episode ini membahas integrasi programatik dan pola error handling yang benar.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Selama 19 episode kalian mengetik FFmpeg di terminal. Tapi di balik binary ffmpeg terdapat puluhan librarylibavcodec, libavformat, libavfilter, libavutil, libswscale, libswresample — yang sama persis dengan yang dipakai VLC, OBS, dan Chrome. Library inilah alasan FFmpeg disebut "Swiss Army knife multimedia".

Episode ini membahas sisi programatik: (1) memanggil library libav* langsung dari kode C dengan API resmi, (2) memakai binding di bahasa lain seperti Go dan Python, dan (3) mengotomasi binary ffmpeg lewat wrapper CLI seperti ffmpeg-python di Python dan fluent-ffmpeg di Node. Kalian akan melihat bahwa memahami arsitektur dari episode 1 ternyata punya nilai praktis yang nyata. Sebelum mulai, cek dulu library apa yang ikut terkompilasi di binary kalian dengan ffmpeg -buildconf.

Arsitektur: Binary Kecil, Library Besar

Satu hal yang sering mengecoh pemula: ffmpeg, ffprobe, dan ffplay hanyalah program kecil yang mengombinasikan library-library di bawahnya. Inilah sebabnya satu binary bisa melakukan begitu banyak hal — ia tidak mengimplementasikan apa pun sendiri, melainkan mengorkestrasi library yang sudah matang.

LibraryTanggung jawabAnalogi
libavformatMembaca/menulis container (MP4, MKV, WebM)Gudang dan rak penyimpanan
libavcodecEncode/decode codec (H.264, AV1, AAC)Mesin pengolahan isi
libavfilterGrafik filter audio/videoJalur perakitan
libavutilUtilitas dasar, matematika, memoryKotak alat umum
libswscaleKonversi format pixel & penskalaanPerkakas pengubah ukuran
libswresampleKonversi sample rate & channel audioMixer audio

Konsekuensi praktisnya: aplikasi kalian tidak perlu memanggil ffmpeg binary bila ingin kecepatan maksimal dan kontrol penuh — cukup tautkan ke libavformat dan libavcodec dan panggil API-nya.

API Resmi dari C

C adalah bahasa asli API ini, dan semua binding lain hanyalah pembungkus di atasnya. Alur dasar hampir selalu sama: buka input, temukan stream, buka decoder, baca packet, decode frame.

Minimal C API: buka file dan decode frame pertama
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdio.h>
 
int main(int argc, char **argv) {
    if (argc < 2) return 1;
 
    AVFormatContext *fmt_ctx = NULL;
    if (avformat_open_input(&fmt_ctx, argv[1], NULL, NULL) < 0) {
        fprintf(stderr, "tidak bisa membuka input\n");
        return 1;
    }
    if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
        fprintf(stderr, "tidak bisa membaca stream info\n");
        return 1;
    }
 
    int stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (stream_index < 0) {
        fprintf(stderr, "tidak ada stream video\n");
        return 1;
    }
    av_dump_format(fmt_ctx, 0, argv[1], 0);
    printf("stream video ada di index %d\n", stream_index);
 
    avformat_close_input(&fmt_ctx);
    return 0;
}

Perhatikan polanya — ini yang nanti kalian lihat di semua tutorial libav:

  1. Alokasi dan buka dengan avformat_open_input — FFmpeg mengurus alokasi memory, lalu avformat_find_stream_info membaca daftar stream.
  2. Selalu cek return code — setiap fungsi mengembalikan nilai negatif untuk error. Ini pola pertama dan terpenting dari API C.
  3. Tutup resource dengan avformat_close_input — kebocoran memori di C adalah bug yang parah.

Compile contoh di atas dengan pkg-config yang menunjuk ke library FFmpeg yang terpasang:

Compile program C dengan libavformat
cc probe.c $(pkg-config --cflags --libs libavformat libavcodec) -o probe

Pola "buka → temukan → baca → tutup" ini muncul lagi di setiap tahap decoding, encoding, filtering, dan muxing. Kuasai pola satu kali, dan kalian bisa membaca API apa pun dari keluarga libav*.

Binding di Go dan Python

Menulis C murni untuk semua proyek tidak selalu praktis. Komunitas menyediakan binding agar library FFmpeg dipakai dari bahasa yang lebih aman dan produktif.

Python: PyAV

PyAV adalah binding Python yang cukup matang — ia membungkus libav* dan mempertahankan gaya API FFmpeg. Kalian bekerja dengan objek Container, Stream, dan Frame, bukan string perintah.

PyAV: decode frame dan tulis PNG
import av
 
container = av.open("input.mp4")
stream = container.streams.video[0]
for frame in container.decode(stream):
    print(f"frame {frame.index}: {frame.width}x{frame.height} @ {frame.pts}")
    img = frame.to_image()
    img.save("thumbnail.png")
    break

Kenapa PyAV unggul untuk kasus seperti ini? Karena frame langsung menjadi objek Python yang bisa diolah (misal jadi PIL.Image) — tanpa lewat parsing stderr dan IPC seperti saat memanggil binary.

Go

Di Go, proyek seperti goav membungkus binding C-style. Karena Go memanggil C lewat cgo, pola dasarnya identik dengan API C — bedanya AVFormatContext ditangani dengan finalizer dan pointer yang lebih aman:

Go: buka container dan cetak durasi
package main
 
import (
    "fmt"
    "os"
 
    goav "github.com/giorgisio/goav/avformat"
)
 
func main() {
    if len(os.Args) < 2 {
        fmt.Println("usage: probe <file>")
        os.Exit(1)
    }
    ctx := goav.AvformatAllocContext()
    if err := ctx.AvformatOpenInput(os.Args[1], nil, nil); err != nil {
        fmt.Println("gagal buka input:", err)
        os.Exit(1)
    }
    defer ctx.AvformatCloseInput()
    fmt.Printf("durasi: %d detik\n", ctx.Duration()/1000000)
}

Binding Go memakai defer untuk menutup context — di sinilah keamanan memory lebih nyaman dibanding C. Struktur API tetap sama, hanya dibungkus idiom Go.

Otomasi CLI: ffmpeg-python

Tidak semua kebutuhan butuh menautkan library. Jika aplikasi kalian hanya menjalankan transcode tertentu, mengotomasi binary ffmpeg lewat wrapper adalah pendekatan paling sederhana dan paling tahan rilis — karena kalian memakai binary apa pun yang terpasang di server. ffmpeg-python membangun command dengan gaya builder: kalian menyusun graph, lalu mengeksekusinya.

ffmpeg-python: filter + encode + ambil output
import ffmpeg
 
input_ = ffmpeg.input("input.mp4")
video = input_.video.filter("scale", 1280, 720)
stream = ffmpeg.output(
    video, input_.audio,
    "output.mp4",
    vcodec="libx264", crf=23, preset="fast",
    acodec="aac",
)
stdout, stderr = stream.run(capture_stdout=True, capture_stderr=True)

Kode di atas setara dengan perintah transcode yang kalian pelajari sejak episode 4, tapi ditulis sebagai objek yang bisa diuji dan di-parametrize dari logika program.

Pola Error Handling yang Benar

Di sinilah banyak pengguna wrapper tersandung. Default stream.run() melempar exception ffmpeg.Error ketika proses gagal — dan objek exception itu membawa stderr yang menyimpan alasan sebenarnya:

Menangkap error FFmpeg dengan benar
import ffmpeg
 
try:
    ffmpeg.input("missing.mp4").output("out.mp4").run(
        capture_stdout=True, capture_stderr=True
    )
except ffmpeg.Error as e:
    print("stderr:", e.stderr.decode())

Aturan praktis error handling di semua wrapper (ffmpeg-python, fluent-ffmpeg, child_process Node):

  1. Selalu tangkap kegagalan proses — jangan biarkan exception beredar tanpa konteks.
  2. Baca stderr, bukan hanya kode keluar. Error FFmpeg nyaris selalu eksplisit: No such file, Invalid data, Permission denied. Log juga perintah yang gagal agar mudah direproduksi.
  3. Jangan parsing output untuk data penting — untuk metadata dan durasi, pakai ffprobe dengan output JSON, bukan mengurai teks manusia.
ffprobe output JSON untuk parsing
ffprobe -v error -print_format json -show_format input.mp4

Output JSON adalah kontrak yang stabil untuk diprogram. Parsing stderr teks adalah sumber bug yang tidak perlu — jangan pernah membangun parser di atas output yang dirancang untuk dibaca manusia.

Integrasi di Aplikasi Node

Di ekosistem Node, fluent-ffmpeg adalah wrapper yang paling populer. Ia berjalan di atas binary ffmpeg dan menawarkan API berantai dengan event untuk progress dan error.

fluent-ffmpeg: transcode dengan progress
const ffmpeg = require("fluent-ffmpeg");
 
ffmpeg("input.mp4")
  .output("output.mkv")
  .videoCodec("libsvtav1")
  .size("1280x720")
  .audioCodec("copy")
  .on("start", (cmd) => console.log("perintah:", cmd))
  .on("progress", (p) => {
    if (p.percent) console.log("proses:", p.percent.toFixed(1) + "%");
  })
  .on("end", () => console.log("selesai"))
  .on("error", (err) => {
    console.error("gagal:", err.message);
    if (err.stderr) console.error(err.stderr);
  })
  .run();

Pola yang sama terlihat lagi: panggil run() sebagai eksekusi akhir, tangani error lewat event, dan baca stderr untuk diagnosis. Event progress bahkan bisa dipakai untuk membangun progress bar — sesuatu yang jauh lebih sulit bila memanggil binary mentah-mentah.

Important

Kapan memakai library (libav*) dan kapan CLI wrapper? Pakai library untuk kontrol per-frame, kecepatan maksimal, atau ribuan file dalam satu proses. Pakai CLI wrapper jika kebutuhan kalian hanya menjalankan transcode yang sudah ditentukan — lebih sederhana, lebih mudah di-debug, dan mengikuti versi binary apa pun yang terpasang. Keduanya sah; pilih berdasarkan kebutuhan.

Penutup

Episode 20 membuka gerbang integrasi:

  • Arsitektur FFmpeg terbagi menjadi library libav* dan binary tipis di atasnya.
  • API C mengikuti pola konsisten: buka, temukan stream, decode/encode, tutup — dan selalu periksa return code.
  • Binding Python (PyAV) dan Go memberi akses library dengan gaya bahasa yang lebih aman.
  • Wrapper CLI seperti ffmpeg-python dan fluent-ffmpeg mengotomasi binary untuk kebutuhan transcode.
  • Error handling sejati dimulai dari membaca stderr dan memakai ffprobe JSON untuk data terstruktur.

Kalian kini bisa memprogram FFmpeg — tapi ke mana arah perkembangannya? Di episode 21 kita mundur sejenak untuk meninjau fitur modern dan roadmap: rilis 8.0 "Huffman", 8.1 "Hoare", 9.0 "Lei", dan arah masa depan VVC, AV1, serta pemanfaatan GPU. Sampai jumpa di episode 21.

Belajar FFmpeg - API & Penggunaan Programatik | Belajar FFmpeg