Seamless Lip-Syncing: How to Fix the "Pasted-On" Mouth Look
In my experience, the real engineering challenge isn't the generative model itself; it's the post-processing pipeline required to make a generated patch actually belong to a real human face. If you want high-fidelity results, you can't just do a simple pixel replacement. You need a multi-stage blending stack.
First, you have to address the resolution mismatch. Generative crops are often soft or blurry compared to the source video. I've found that running the patched frame through a face restoration GAN like GFPGAN is essential to bring the mouth detail up to the same sharpness as the surrounding skin.
_, _, restored_img = self.gfpgan.enhance(
ff, has_aligned=False, only_center_face=True, paste_back=True
)Using only_center_face=True is a smart way to save compute—you don't want to waste GPU cycles enhancing background faces that don't matter.
But even with a sharp mouth, a rectangular paste is a death sentence. You need a soft, organic mask. This is where face-parsing networks come in. Instead of a box, you use the parser to identify the exact pixels belonging to the lips and mouth area, creating a mask that follows the actual anatomy.
# select the mouth / lip classes from the face parser
mm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0]
mouth_mask = np.zeros_like(restored_img)
tmp_mask = self.face_enhancement.faceparser.process(restored_img[y1:y2, x1:x2], mm)[0]
tmp_mask_resized = cv2.resize(tmp_mask, (x2 - x1, y2 - y1))[:, :, np.newaxis] / 255.
mouth_mask[y1:y2, x1:x2] = tmp_mask_resizedThe final boss, however, is the frequency mismatch. Even with a perfect mask, a standard alpha blend often leaves a visible edge because the skin textures at different scales don't line up. The most robust way to handle this is through a Laplacian pyramid blend. By decomposing the images into frequency bands, you can blend the low frequencies over a wide area and the high frequencies over a very narrow one. It effectively "hides" the seam across all scales.
def laplacian_pyramidIs the extra compute worth the cost? If you're looking for professional-grade output where the user doesn't realize they're looking at AI, absolutely. It's the difference between a "tech demo" and a finished product.