5 attempts, 2 SIGKILLs, 1 non-existent flag: how I got a 4-second avatar to speak Spanish
This is the story of a four-second video that took an entire evening, five attempts, two out-of-memory kills, one flag that never existed, and a parameter combo that felt like a magic spell. The mission: make my AI avatar say a sentence in Spanish β with the lips actually synced.
The mission
I had an avatar video of myself. I generated the audio with edge-tts (Spanish voice, "La IA no espera. Tu negocio tampoco." β "AI doesn't wait. Neither does your business."). All I needed was to map the audio onto the face with Wav2Lip. Simple, right?
Attempt 1 β the library moved on without me
librosa.filters.mel(...) β TypeError: unexpected keyword argument
Wav2Lip was written for librosa 0.8. My environment had 0.11, where mel() requires keyword arguments. One-line patch in audio.py, re-run.
Attempt 2 β SIGKILL (the quiet killer)
No Python traceback. No error message. Just Killed β the signature of the OOM killer on a server with ~8 GB already occupied by other services. Wav2Lip was loading the whole face video into memory.
Attempt 3 β the flag that never existed
I shrank the video to 960Γ540 and confidently added --batch_size 8. The CLI replied: unknown argument. The real flag is --wav2lip_batch_size β I'd read the docs from memory and hallucinated the name. (Yes β I, the person writing a story about a bug, introduced a hallucinated flag.)
Attempt 4 β the second SIGKILL
Correct flag, both batch sizes set: --wav2lip_batch_size 8 --face_batch_size 8. The process made it furtherβ¦ then died the same silent death. At this point I understood: it wasn't the video resolution, it wasn't the flags β it was peak memory during inference.
Attempt 5 β the magic combo
The winning incantation:
OMP_NUM_THREADS=4 python inference.py \
--checkpoint_path wav2lip_gan.pth \
--face miguel-face-small.mp4 \
--audio avatar-es.mp3 \
--wav2lip_batch_size 4 \
--resize_factor 2 \
--outfile miguel-avatar-es.mp4
-
--resize_factor 2: halves the processing resolution (and memory) while keeping the output watchable -
--wav2lip_batch_size 4: small enough to fit, big enough to be worth it -
OMP_NUM_THREADS=4: keeps the rest of the box alive
104 frames. 4.2 seconds. Exit code 0. The lips moved with the Spanish audio, frame by frame.
The plot twist
I was so proud I tried a "high-definition" re-run with --resize_factor 1. The OOM killer came back and murdered it in seconds. The lesson landed twice: I wasn't fixing resolution, I was fighting RAM β and the "lower quality" version was the production version all along.
What made the software more resilient (me)
-
The OOM kill is a feature of your environment, not a bug of your code β
free -hbefore you start, batch sizes after. -
Read the CLI help, don't trust your memory of it β
--helptakes ten seconds and saves an attempt. -
The ugly-but-working config is a legitimate final state β
resize_factor 2+ batch 4 was "worse" on paper and the only thing that survived.
The takeaway
A four-second video that took five attempts taught me more about memory management than a month of tutorials. And the avatar? He's out there, speaking Spanish, perfectly in sync.
π¬ The actual output: a 4.2s clip, 480Γ270, 365,943 bytes β the smallest, scrappiest, most hard-won video I've made.
bugsmash
This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry.
Top comments (0)