mmo.vn
AI & sáng tạo nội dung5 phút đọc

Case study: Tự viết app đóng watermark hàng loạt cho video bằng Python và FFmpeg

App desktop đóng logo cho cả thư mục video bằng FFmpeg: tự tính cỡ logo theo từng video, chọn vị trí theo video dọc hay ngang, logo đổi góc để khó cắt bỏ, chạy nền có thanh tiến độ. Kèm code và lệnh mẫu.

Thumbnail case study app đóng watermark hàng loạt cho video

Kênh nào đăng video đều đặn rồi cũng gặp chuyện video bị người khác tải về và đăng lại. Đóng logo thủ công trong phần mềm dựng cho từng video thì mất thời gian, nhất là khi có vài chục clip mỗi tuần. Case study này trình bày một app desktop nhỏ viết bằng Python: chọn một thư mục video, chọn logo, bấm một nút, app đóng watermark cho cả thư mục bằng FFmpeg, tự chỉnh kích thước logo theo từng video, kể cả video dọc và ngang lẫn lộn.

Tóm tắt case study

Đầu raBản sao của từng video đã có logo, giữ nguyên file gốc
Công cụPython, PySide6 (giao diện), FFmpeg và ffprobe (xử lý video), một AI hỗ trợ viết code
Đầu vàoMột thư mục video và một file logo PNG nền trong suốt
Hợp vớiKênh đăng nhiều video ngắn, đội media phải đóng logo cho nhiều clip mỗi tuần
Không hợp vớiVideo cần hiệu ứng logo động phức tạp, hoặc chỉ vài video mỗi tháng

Tóm tắt nhanh

FFmpeg đã làm được việc đóng watermark từ lâu, nhưng gõ lệnh cho từng file thì không ai muốn. App chỉ làm ba việc: đo kích thước từng video, tính cỡ logo cho cân, rồi chạy FFmpeg cho cả thư mục ở chế độ nền. AI hỗ trợ viết code giúp người không chuyên vẫn dựng được app này, nhưng cần hiểu đủ về lệnh FFmpeg để kiểm tra kết quả.

Bước 1: Đo kích thước từng video

Một logo rộng 200 pixel trông vừa vặn trên video dọc 1080×1920, nhưng sẽ quá to trên video 720p và quá bé trên video 4K. Vì vậy app không dùng một cỡ logo cố định mà đo từng video trước bằng ffprobe:

ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 input.mp4
# kết quả, ví dụ: 1080,1920

Từ chiều rộng và chiều cao, app biết video dọc hay ngang và tính cỡ logo theo tỷ lệ, ví dụ logo rộng bằng 18% cạnh ngắn của video.

Bước 2: Lệnh FFmpeg đóng logo

Với cỡ logo đã tính, app gọi FFmpeg với bộ lọc overlay. Đoạn code tạo lệnh:

import subprocess

def add_watermark(src, logo, dst, logo_w, margin, opacity=0.85):
    vf = (
        f"[1:v]scale={logo_w}:-1,format=rgba,colorchannelmixer=aa={opacity}[wm];"
        f"[0:v][wm]overlay=main_w-overlay_w-{margin}:{margin}"
    )
    cmd = [
        "ffmpeg", "-y", "-i", src, "-i", logo,
        "-filter_complex", vf,
        "-c:v", "libx264", "-crf", "20", "-preset", "veryfast",
        "-c:a", "copy",
        dst,
    ]
    subprocess.run(cmd, check=True)
  • scale={logo_w}:-1 đổi cỡ logo theo chiều rộng đã tính, giữ nguyên tỷ lệ.
  • colorchannelmixer=aa=0.85 làm logo hơi trong suốt, đủ nhận ra mà không che nội dung.
  • overlay=main_w-overlay_w-{margin}:{margin} đặt logo ở góc trên bên phải, cách mép một khoảng margin.
  • -c:a copy giữ nguyên âm thanh, không mã hoá lại, vừa nhanh vừa không giảm chất lượng tiếng.

Bước 3: Chọn vị trí theo loại video

Góc dưới bên phải là vị trí quen thuộc trên video ngang, nhưng trên video dọc của TikTok, Reels, Shorts thì góc đó bị các nút thả tim, bình luận, chia sẻ che mất. App chọn vị trí tự động:

Loại videoVị trí logoLý do
Ngang (16:9)Góc dưới bên phảiVị trí người xem đã quen, không che phụ đề ở giữa
Dọc (9:16)Phía trên, cách mép trên khoảng 12% chiều caoTránh thanh nút bên phải và phần chữ mô tả ở dưới
Vuông (1:1)Góc trên bên phảiÍt bị che trên hầu hết nền tảng

Bước 4: Logo di chuyển để khó cắt bỏ

Logo đứng yên ở một góc rất dễ bị cắt khung hoặc làm mờ. Một cách đơn giản để khó gỡ hơn: cho logo đổi góc sau mỗi khoảng thời gian. Bộ lọc overlay tính lại vị trí ở từng khung hình, nên có thể dùng biểu thức theo thời gian t:

overlay=x='if(lt(mod(t,20),10), 40, main_w-overlay_w-40)':y=40
# 10 giây đầu của mỗi chu kỳ 20 giây: logo ở góc trái; 10 giây sau: góc phải

Cách này không chặn được hoàn toàn việc đăng lại, nhưng làm việc gỡ logo tốn công hơn nhiều so với một cú cắt khung.

Bước 5: Chạy cả thư mục mà giao diện không bị đứng

  • Chạy nền. Mỗi video là một tác vụ trong QThreadPool. Giới hạn chạy cùng lúc 2 đến 3 video, vì mã hoá video ngốn nhiều CPU.
  • Thanh tiến độ thật. Thêm -progress pipe:1 vào lệnh FFmpeg, app đọc thời điểm đã xử lý và chia cho thời lượng video để hiện phần trăm.
  • Không ghi đè file gốc. Kết quả lưu vào thư mục con, tên file thêm hậu tố, ví dụ _wm.mp4. Video đã có bản _wm thì bỏ qua khi chạy lại.
  • Dùng card đồ hoạ nếu có. Máy có card NVIDIA có thể đổi libx264 thành h264_nvenc để mã hoá nhanh hơn, đổi lại file thường lớn hơn ở cùng chất lượng.

Điểm cộng

  • Cả thư mục video có logo chỉ với một lần bấm.
  • Logo tự đúng cỡ và đúng vị trí cho video dọc, ngang, vuông.
  • FFmpeg miễn phí, chạy hoàn toàn trên máy, không phải tải video lên dịch vụ nào.
  • Giữ nguyên âm thanh và file gốc.

Điểm trừ

  • Video phải mã hoá lại, nên mỗi file mất thời gian và có thể giảm chất lượng nhẹ nếu đặt CRF quá cao.
  • Cần cài FFmpeg và Python, người chưa quen sẽ mất thời gian lúc đầu.
  • Watermark chỉ làm việc đăng lại khó hơn, không ngăn được hoàn toàn.
  • Logo PNG không có nền trong suốt sẽ hiện thành một khối vuông, cần chuẩn bị file logo đúng chuẩn.

Lưu ý

Chỉ đóng watermark lên video bạn sở hữu hoặc có quyền sử dụng. Đóng logo của mình lên video của người khác không biến video đó thành của bạn, và có thể vi phạm bản quyền cũng như chính sách của các nền tảng.

Kết luận

Nếu bạn đăng nhiều video ngắn mỗi tuần, một app đóng watermark hàng loạt là món đầu tư nhỏ nhưng tiết kiệm thời gian rõ rệt. Phần đáng làm kỹ không phải lệnh FFmpeg mà là các quy tắc xung quanh: cỡ logo theo từng video, vị trí theo loại khung hình, và không bao giờ ghi đè file gốc.

Nguồn: FFmpeg: tài liệu bộ lọc overlay.