faster-whisper: Transkripsi Audio 4x Lebih Cepat dengan Memori Setengahnya

# faster-whisper: Transkripsi Audio 4x Lebih Cepat dengan Memori Setengahnya Halo temen-temen, kalau kalian pernah pakai Whisper dari OpenAI buat transkripsi audio, kalian pasti tahu dua hal: hasilny...

By Ruby Abdullah · · tutorial
faster-whisperwhisperspeech-to-textctranslate2transcription

faster-whisper: Transkripsi Audio 4x Lebih Cepat dengan Memori Setengahnya

Halo temen-temen, kalau kalian pernah pakai Whisper dari OpenAI buat transkripsi audio, kalian pasti tahu dua hal: hasilnya bagus banget, dan jalannya lambat banget. Nah di tutorial kali ini aku mau kenalin faster-whisper, implementasi ulang Whisper yang memberi hasil sama persis tapi berjalan sekitar empat kali lebih cepat dengan pemakaian memori jauh lebih kecil.

Ini bukan model baru. Bobotnya sama. Yang berbeda adalah mesin yang menjalankannya. faster-whisper memakai CTranslate2, engine inference khusus model Transformer yang dioptimasi habis-habisan, lengkap dengan dukungan kuantisasi INT8 dan float16. Jadi kalian dapat kualitas Whisper dengan biaya komputasi yang jauh lebih masuk akal.

Di tutorial ini kita bahas kenapa Whisper asli lambat, instalasi, transkripsi pertama, pilihan ukuran model dan tipe komputasi, deteksi bahasa dan timestamp per kata, VAD untuk membuang bagian hening, transkripsi batch dan file panjang, diarization sederhana, sampai deployment sebagai API. Ayo mulai.

Introduction

Kenapa Whisper Asli Lambat

Implementasi resmi Whisper ditulis dengan PyTorch dalam gaya penelitian, bukan gaya produksi. Setiap langkah decoding menjalankan operasi PyTorch dinamis dengan overhead Python yang tidak kecil. Tidak ada fusion kernel yang agresif, cache attention-nya sederhana, dan kuantisasi tidak didukung secara native.

faster-whisper mengambil bobot yang sama lalu menjalankannya di CTranslate2, yang melakukan sejumlah optimasi: fusion operasi, layout memori yang efisien, kernel yang dioptimasi untuk CPU maupun GPU, dan kuantisasi INT8 yang matang. Hasil praktisnya, di GPU yang sama kalian biasanya melihat percepatan tiga sampai lima kali dengan pemakaian VRAM sekitar setengahnya, dan di CPU percepatannya bahkan sering lebih terasa.

Yang penting dipahami: karena bobotnya identik, kualitas transkripsi kalian tidak berubah. Ini bukan trade-off kualitas demi kecepatan, ini murni implementasi yang lebih efisien.

Instalasi

python -m venv venv

source venv/bin/activate # Linux / Mac

venv\Scripts\activate # Windows

pip install faster-whisper

Kalian juga butuh ffmpeg terpasang di sistem untuk membaca berbagai format audio dan video.

# Ubuntu / Debian

sudo apt install ffmpeg

macOS

brew install ffmpeg

Untuk memakai GPU NVIDIA, pastikan cuBLAS dan cuDNN tersedia. Kalau kalian pakai PyTorch versi CUDA, biasanya library itu sudah ikut terinstal dan faster-whisper bisa langsung menemukannya. Kalau muncul error soal libcudnn, cara paling gampang adalah:

pip install nvidia-cublas-cu12 nvidia-cudnn-cu12

Transkripsi Pertama

from fasterwhisper import WhisperModel

Muat model, otomatis diunduh saat pertama kali

model = WhisperModel("large-v3", device="cuda", computetype="float16")

segments, info = model.transcribe("rapat.mp3", beamsize=5)

print(f"bahasa terdeteksi: {info.language} (probabilitas {info.languageprobability:.2f})")

print(f"durasi audio: {info.duration:.1f} detik")

for seg in segments:

print(f"[{seg.start:.2f}s -> {seg.end:.2f}s] {seg.text}")

Ada satu hal krusial yang harus kalian tahu di sini: segments itu generator, bukan list. Transkripsi baru benar-benar berjalan saat kalian mengiterasinya. Ini desain yang bagus karena kalian bisa mulai menampilkan hasil sebelum seluruh file selesai, tapi juga sering membingungkan pemula yang heran kenapa model.transcribe() selesai dalam sekejap.

Kalau kalian butuh seluruh hasil sekaligus:

segments = list(segments)

tekslengkap = " ".join(s.text for s in segments)

print(tekslengkap)

Memilih Ukuran Model

Whisper tersedia dalam beberapa ukuran, dan pilihan ini adalah keputusan terpenting kalian.

tiny dan base sangat cepat dan ringan, cocok untuk deteksi kata kunci sederhana atau bahasa Inggris yang jernih. Untuk bahasa Indonesia, akurasinya sering mengecewakan. small adalah titik masuk yang wajar untuk banyak aplikasi, terutama kalau audionya bersih. medium memberi kualitas yang lumayan bagus untuk bahasa Indonesia dengan biaya menengah. large-v3 adalah yang terbaik dari sisi akurasi, terutama untuk bahasa non-Inggris, aksen kental, dan audio berisik. Untuk pekerjaan serius berbahasa Indonesia, aku hampir selalu memakai ini. distil-large-v3 adalah versi hasil distilasi yang berjalan sekitar dua kali lebih cepat dari large-v3 dengan akurasi yang sangat dekat untuk bahasa Inggris. Perlu dicatat, model distilasi ini dioptimasi untuk bahasa Inggris, jadi untuk bahasa Indonesia sebaiknya tetap pakai large-v3.

Compute Type: Tombol Kecepatan Terbesar

Ini parameter yang paling sering diabaikan padahal dampaknya besar.

# GPU modern (Ampere ke atas)

model = WhisperModel("large-v3", device="cuda", computetype="float16")

GPU dengan VRAM terbatas

model = WhisperModel("large-v3", device="cuda", computetype="int8float16")

CPU, pilihan terbaik untuk kebanyakan kasus

model = WhisperModel("large-v3", device="cpu", computetype="int8", cputhreads=8)

Otomatis pilih yang terbaik untuk perangkat

model = WhisperModel("large-v3", device="auto", computetype="auto")

Panduan praktisnya begini. Di GPU, float16 adalah default yang bagus. Kalau VRAM kalian tipis, int8float16 menghemat memori signifikan dengan penurunan kualitas yang biasanya tidak terasa. Di CPU, int8 hampir selalu pilihan terbaik, dan bedanya dengan float32 bisa mencapai tiga kali lipat kecepatan.

Untuk CPU, atur cputhreads sesuai jumlah inti fisik kalian, bukan jumlah thread logis. Menaikkan angka ini melebihi inti fisik biasanya tidak membantu dan kadang malah memperlambat.

Timestamp per Kata

Untuk membuat subtitle yang presisi atau untuk menyorot kata saat audio diputar, kalian butuh timestamp level kata.

segments, info = model.transcribe(

"podcast.mp3",

wordtimestamps=True,

beamsize=5,

)

for seg in segments:

for kata in seg.words:

print(f"{kata.start:.2f}-{kata.end:.2f} {kata.word} (p={kata.probability:.2f})")

Perhatikan kata.probability. Nilai ini sangat berguna untuk quality control. Kalau kalian membangun pipeline transkripsi otomatis, kalian bisa menandai segmen dengan probabilitas rendah untuk direview manusia, alih-alih mereview semuanya.

segmenragu = [s for s in segments if s.avglogprob < -0.5 or s.nospeechprob > 0.6]

print(f"{len(segmenragu)} segmen perlu direview manual")

VAD: Membuang Bagian Hening

Voice Activity Detection mendeteksi bagian mana dari audio yang benar-benar berisi suara manusia. Ini fitur yang sangat aku rekomendasikan untuk hampir semua kasus.

segments, info = model.transcribe(

"wawancarapanjang.mp3",

vadfilter=True,

vadparameters=dict(

minsilencedurationms=500,

speechpadms=200,

),

)

Ada dua manfaat besar. Pertama, kecepatan. Kalau rekaman rapat kalian dua jam tapi hanya 45 menit yang ada suaranya, kalian menghemat lebih dari separuh waktu proses. Kedua, dan ini lebih penting, VAD mencegah halusinasi. Whisper punya kebiasaan buruk mengarang teks saat diberi audio hening atau berisik tanpa suara, sering menghasilkan kalimat seperti "Terima kasih telah menonton" yang berasal dari data latihnya. VAD memotong bagian itu sebelum sampai ke model.

Menangani Halusinasi

Selain VAD, ada beberapa parameter yang membantu.

segments, info = model.transcribe(

"audioberisik.mp3",

vadfilter=True,

conditiononprevioustext=False, # cegah error menjalar

temperature=0.0, # deterministik

compressionratiothreshold=2.4, # tolak output yang terlalu repetitif

nospeechthreshold=0.6,

logprobthreshold=-1.0,

)

conditiononprevioustext=False itu penting untuk audio sulit. Secara default Whisper memakai teks sebelumnya sebagai konteks, yang bagus untuk kelancaran tapi berbahaya kalau satu segmen salah, karena kesalahannya bisa menjalar dan membuat model masuk ke loop pengulangan.

Menentukan Bahasa dan Prompt Awal

Kalau kalian sudah tahu bahasanya, sebutkan. Ini menghemat waktu deteksi dan mencegah salah deteksi di awal file yang berisik.

segments, info = model.transcribe(

"rapat.mp3",

language="id",

initialprompt="Ini rekaman rapat tim engineering membahas deployment, Kubernetes, dan microservices.",

)

initialprompt sangat berguna untuk istilah khusus. Kalau rapat kalian penuh nama produk, singkatan perusahaan, atau istilah teknis, sebutkan di prompt awal. Whisper akan lebih besar kemungkinannya menuliskannya dengan benar. Ini trik sederhana yang dampaknya besar di domain teknis dan medis.

Transkripsi Batch

Untuk memproses banyak file, versi modern faster-whisper menyediakan pipeline batch yang jauh lebih cepat di GPU.

from fasterwhisper import WhisperModel, BatchedInferencePipeline

model = WhisperModel("large-v3", device="cuda", computetype="float16")

batched = BatchedInferencePipeline(model=model)

segments, info = batched.transcribe("rekamanpanjang.mp3", batchsize=16)

for seg in segments:

print(f"[{seg.start:.2f} -> {seg.end:.2f}] {seg.text}")

Untuk file panjang di GPU, ini bisa memberi percepatan beberapa kali lipat lagi dibanding mode biasa. Sesuaikan batchsize dengan VRAM kalian, mulai dari 8 dan naikkan sambil memantau pemakaian memori.

Untuk memproses banyak file sekaligus di CPU, pola yang paling efisien adalah satu proses per file dengan jumlah thread dibatasi, bukan multithreading dalam satu proses.

from concurrent.futures import ProcessPoolExecutor

from fasterwhisper import WhisperModel

import glob

def transkripsi(path):

model = WhisperModel("small", device="cpu", computetype="int8", cputhreads=2)

segments, info = model.transcribe(path, vadfilter=True, language="id")

return path, " ".join(s.text for s in segments)

if name == "main":

files = glob.glob("audio/.mp3")

with ProcessPoolExecutor(maxworkers=4) as ex:

for path, teks in ex.map(transkripsi, files):

with open(path + ".txt", "w", encoding="utf-8") as f:

f.write(teks)

print("selesai:", path)

Membuat File Subtitle

Ini kebutuhan yang sangat umum, jadi aku kasih fungsi lengkapnya.

def formatwaktusrt(detik: float) -> str:

jam = int(detik // 3600)

menit = int((detik % 3600) // 60)

dtk = int(detik % 60)

ms = int((detik - int(detik)) 1000)

return f"{jam:02d}:{menit:02d}:{dtk:02d},{ms:03d}"

def tulissrt(segments, outputpath):

with open(outputpath, "w", encoding="utf-8") as f:

for i, seg in enumerate(segments, start=1):

f.write(f"{i}\n")

f.write(f"{formatwaktusrt(seg.start)} --> {formatwaktusrt(seg.end)}\n")

f.write(f"{seg.text.strip()}\n\n")

segments, info = model.transcribe("video.mp4", vadfilter=True, language="id")

tulissrt(segments, "video.srt")

print("subtitle tersimpan")

Perhatikan bahwa faster-whisper bisa langsung membaca file video karena dia memakai ffmpeg di belakang layar. Kalian tidak perlu mengekstrak audionya dulu.

Membungkus Jadi API

Untuk dipakai tim, biasanya kalian ingin membungkusnya jadi layanan HTTP.

from fastapi import FastAPI, UploadFile, File

from fasterwhisper import WhisperModel

import tempfile, os

app = FastAPI()

Muat model SEKALI saat startup, jangan per request

model = WhisperModel("large-v3", device="cuda", computetype="float16")

@app.post("/transkripsi")

async def transkripsi(file: UploadFile = File(...), bahasa: str = "id"):

with tempfile.NamedTemporaryFile(delete=False, suffix=".audio") as tmp:

tmp.write(await file.read())

path = tmp.name

try:

segments, info = model.transcribe(

path, language=bahasa, vadfilter=True, wordtimestamps=False

)

hasil = [

{"start": s.start, "end": s.end, "text": s.text.strip()}

for s in segments

]

return {

"bahasa": info.language,

"durasi": info.duration,

"segmen": hasil,

"teks": " ".join(s["text"] for s in hasil),

}

finally:

os.unlink(path)

Jalankan dengan uvicorn app:app --host 0.0.0.0 --port 8000.

Dua catatan produksi. Pertama, muat model sekali di level modul, jangan di dalam handler, karena memuat large-v3 memakan waktu dan memori. Kedua, kalau trafik kalian tinggi, letakkan antrian di depan (misalnya Celery atau Redis queue) supaya request tidak menumpuk di GPU dan menyebabkan out of memory.

Tips dan Best Practice

Selalu aktifkan vadfilter=True kecuali kalian punya alasan kuat untuk tidak. Manfaat kecepatan dan pencegahan halusinasinya hampir selalu sepadan.

Sebutkan language secara eksplisit kalau kalian tahu bahasanya. Deteksi otomatis hanya melihat 30 detik pertama, dan kalau bagian itu berisi musik atau hening, hasilnya bisa salah untuk seluruh file.

Pakai initialprompt untuk istilah domain. Ini cara termurah menaikkan akurasi nama produk dan singkatan.

Simpan avglogprob dan nospeechprob dari setiap segmen ke database kalian. Nanti waktu ada keluhan kualitas, kalian punya data untuk menelusurinya.

Untuk audio telepon atau rekaman lapangan berkualitas rendah, pertimbangkan preprocessing dengan filter noise reduction sebelum masuk ke Whisper. Kadang perbaikan di sisi audio lebih efektif daripada mengganti model.

Kalau kalian butuh tahu siapa yang berbicara, gabungkan dengan library diarization seperti pyannote.audio, lalu petakan hasil diarization ke timestamp segmen dari faster-whisper. Whisper sendiri tidak melakukan diarization.

Kesimpulan

faster-whisper adalah salah satu upgrade paling gampang yang bisa kalian lakukan kalau saat ini masih memakai Whisper asli. Ringkasannya:

Bobot modelnya identik dengan Whisper OpenAI, jadi kualitas transkripsi tidak berubah, yang berubah hanya efisiensi eksekusinya lewat CTranslate2.

compute
type adalah tombol kecepatan terbesar kalian: float16 untuk GPU, int8 untuk CPU, int8float16 untuk GPU dengan VRAM terbatas.

Hasil transcribe adalah generator, jadi transkripsi baru berjalan saat kalian mengiterasinya.

VAD filter menghemat waktu sekaligus mencegah halusinasi, dan sebaiknya jadi default kalian.

Timestamp per kata, initialprompt, dan skor kepercayaan per segmen membuka banyak kemungkinan untuk quality control dan produk yang lebih rapi.

Untuk produksi, muat model sekali, pakai batching di GPU atau multiprocessing di CPU, dan letakkan antrian di depan layanan kalian.

Coba ambil satu rekaman rapat lama kalian, transkripsi dengan large-v3 plus VAD, lalu bandingkan waktunya dengan Whisper asli. Selisihnya biasanya cukup besar untuk membuat kalian langsung pindah dan tidak menengok ke belakang. Selamat mencoba.

Artikel Terkait

Tutorial OpenAI Whisper: Speech-to-Text dan Audio Transcription

OpenAI Whisper - Tutorial Lengkap Speech-to-Text Daftar Isi Pendahuluan Prasyarat Memahami Ukuran Model Whisper [Tran...

PaddleOCR: Ekstraksi Teks dari Gambar dan Dokumen dengan Akurasi Tinggi

PaddleOCR: Ekstraksi Teks dari Gambar dan Dokumen dengan Akurasi Tinggi Halo temen-temen, kali ini kita bahas salah satu...

OpenVINO: Menjalankan Model AI dengan Cepat di CPU, iGPU, dan NPU Intel

OpenVINO: Menjalankan Model AI dengan Cepat di CPU, iGPU, dan NPU Intel Halo temen-temen, di tutorial kali ini aku mau n...

TensorRT-LLM: Memeras Throughput Maksimal dari GPU NVIDIA untuk Inference LLM

TensorRT-LLM: Memeras Throughput Maksimal dari GPU NVIDIA untuk Inference LLM Halo temen-temen, kali ini kita bahas sala...