Bạn biết tôi qua Upwork? Nếu bạn biết tôi qua Upwork và muốn sử dụng dịch vụ, vui lòng liên hệ qua Upwork. Tin nhắn từ khách Upwork gửi ngoài Upwork sẽ không được trả lời.
Ghi chú bản địa hóa🎬 Phụ đề & Caption

Thẻ ngôn ngữ phụ đề trong MP4 và MKV: vie, vi và zh-Hans

Track phụ đề MP4 cần mã ISO 639-2 như vie (không phải vi); MKV hỗ trợ BCP 47 đầy đủ như zh-Hans qua mkvmerge. Hướng dẫn cú pháp ffmpeg và mkvmerge kèm bảng tra mã.

Dao Huy (Lucas)8 phút đọc8 mục
Thẻ ngôn ngữ phụ đề trong MP4 và MKV: vie, vi và zh-Hans

💡 Trong MP4, ffmpeg yêu cầu mã ISO 639-2 ba chữ cái cho metadata ngôn ngữ phụ đề: dùng -metadata:s:s:0 language=vie cho tiếng Việt, không phải vi. Trong MKV, mkvmerge ghi cả phần tử ISO 639-2 cũ lẫn LanguageIETF theo BCP 47 từ một lần đặt cờ duy nhất, cho phép dùng zh-Hans cho tiếng Trung giản thể, điều mà mã ba chữ cái zho một mình không thể biểu đạt.

Ý chính

  • Trường -metadata:s:s:N language= của ffmpeg nhận mã ISO 639-2 ba chữ cái: vie (tiếng Việt), eng (tiếng Anh), fra (tiếng Pháp), zho (tiếng Trung bất kỳ).
  • Dùng mã BCP 47 hai chữ cái (vi) trong ffmpeg không nhất quán trên mọi player; luôn dùng mã ISO 639-2 ba chữ cái cho MP4.
  • MKV lưu hai trường ngôn ngữ song song: Language cũ (ISO 639-2) và LanguageIETF mới (BCP 47); mkvmerge ghi cả hai từ một giá trị --language duy nhất.
  • Với tiếng Trung, subtag BCP 47 (zh-Hans / zh-Hant) là cách duy nhất phân biệt Giản thể và Phồn thể trong track phụ đề.
  • Xác minh mọi thẻ sau khi mux: ffprobe -v error -select_streams s -show_entries stream=index,codec_name:stream_tags=language,title -of default=noprint_wrappers=1 output.mp4

Thẻ ngôn ngữ phụ đề quan trọng như thế nào, và nên dùng mã nào?

Thẻ ngôn ngữ trên track phụ đề cho trình phát media, streaming manifest và công cụ truy cập biết track nào cần tải tự động. Gán sai mã hoặc để und (undefined) thì player có thể bỏ qua hoàn toàn, hoặc tải sai ngôn ngữ cho người xem đã cài ngôn ngữ hệ thống là tiếng Việt hay tiếng Trung giản thể.

Tôi từng có client bị Plex bỏ qua track phụ đề tiếng Việt vì muxer ghi vi vào một trường MP4 cần mã ISO 639-2 ba chữ cái vie. File vẫn chạy ổn trong VLC vì VLC chấp nhận mã linh hoạt hơn, nhưng QC trên nền tảng của client lại báo lỗi. Phát hiện sớm chỉ mất vài phút để sửa; phát hiện khi giao hàng là tốn kém.

Hai chuẩn điều chỉnh thẻ ngôn ngữ trong media container:

Ngôn ngữMã BCP 47Mã ISO 639-2Ghi chú
Tiếng ViệtvivieDùng vie trong ffmpeg MP4
Tiếng Anheneng
Tiếng Phápfrfra
Tiếng Trung giản thểzh-Hanszhozho một mình là không rõ
Tiếng Trung phồn thểzh-HantzhoISO 639-2 giống tiếng Trung giản thể
Tiếng Nhậtjajpn
Tiếng Hànkokor
Tiếng Tây Ban Nhaesspa

ISO 639-2 dùng mã ba chữ cái và từng là chuẩn cho media container. BCP 47 thêm subtag tùy chọn cho chữ viết (Hans, Hant) và vùng lãnh thổ. Điểm bất cập quan trọng: zho bao gồm mọi biến thể tiếng Trung trong ISO 639-2, nên container chỉ dùng ISO 639-2 không phân biệt được Giản thể và Phồn thể.

Gán thẻ ngôn ngữ đúng trong MP4 bằng ffmpeg

MP4 lưu metadata phụ đề trong language box ở cấp track. ffmpeg ánh xạ trường này sang ISO 639-2. Đây là lệnh tôi dùng để gán thẻ đúng cho track phụ đề tiếng Việt khi mux vào MP4:

ffmpeg -i video.mp4 -i vi.srt \
  -map 0 -map 1 \
  -c:v copy -c:a copy \
  -c:s mov_text \
  -metadata:s:s:0 language=vie \
  -metadata:s:s:0 title="Vietnamese" \
  -disposition:s:0 default \
  output.mp4

Các tham số liên quan đến thẻ ngôn ngữ:

  • -metadata:s:s:0 language=vie: bộ chỉ định s:s:0 có nghĩa loại stream subtitle, index 0. Giá trị phải là mã ISO 639-2 ba chữ cái, không phải mã BCP 47 hai chữ cái.
  • -metadata:s:s:0 title="Vietnamese": nhãn hiển thị trong menu player, độc lập với mã ngôn ngữ.
  • -disposition:s:0 default: đánh dấu track này là mặc định cho player tự bật một track phụ đề.

Với hai track phụ đề, track thứ hai dùng -metadata:s:s:1 language=eng và -disposition:s:1 0 để xóa cờ default. Index sau s:s: là chỉ số stream phụ đề tính từ 0. Toàn bộ quy trình codec và mux xem thêm bài nhúng track phụ đề mềm vào MP4 và MKV.

File MKV xử lý thẻ BCP 47 và zh-Hans như thế nào?

Matroska (MKV) giới thiệu thêm một trường ngôn ngữ thứ hai trong spec v4: Language cũ (ISO 639-2) và LanguageIETF mới (BCP 47), cả hai đều có trên mỗi track. mkvmerge ghi cả hai từ một giá trị --language duy nhất, tự động tách phần ISO 639-2 cho trường cũ:

# Thêm SRT tiếng Việt vào MKV
mkvmerge -o output.mkv \
  video.mkv \
  --language 0:vi \
  --track-name "0:Vietnamese" \
  vi.srt

# Thêm phụ đề tiếng Trung giản thể với subtag chữ viết
mkvmerge -o output.mkv \
  video.mkv \
  --language 0:zh-Hans \
  --track-name "0:Chinese (Simplified)" \
  zh-hans.srt

# Cả Giản thể và Phồn thể thành hai track riêng có thể chọn
mkvmerge -o output.mkv \
  video.mkv \
  --language 0:zh-Hans --track-name "0:Chinese (Simplified)" zh-hans.srt \
  --language 0:zh-Hant --track-name "0:Chinese (Traditional)" zh-hant.srt
  • --language 0:zh-Hans: mkvmerge ghi zho vào Language cũ và zh-Hans vào LanguageIETF. Các player đọc được LanguageIETF (VLC 3.0+, mpv, Infuse) hiển thị "Chinese (Simplified)" là tùy chọn có tên riêng.
  • 0: trong --language 0:vi là chỉ số track trong FILE INPUT TIẾP THEO được liệt kê, không phải số stream tuyệt đối trong output.

Subtag chữ viết quan trọng nhất khi file có cả hai track tiếng Trung. Nếu không có subtag BCP 47 riêng trong LanguageIETF, menu player hiển thị hai mục đều nhãn "Chinese" và người xem không phân biệt được. Với output MP4 cần hai track tiếng Trung phân biệt rõ ràng, MKV + mkvmerge là container đáng tin cậy hơn.

Làm sao xác minh thẻ ngôn ngữ bằng ffprobe?

Tôi chạy lệnh ffprobe này ngay sau mỗi lần mux để xác nhận thẻ đúng trước khi file rời máy:

ffprobe -v error \
  -select_streams s \
  -show_entries stream=index,codec_name:stream_tags=language,title \
  -of default=noprint_wrappers=1 \
  output.mp4

Output mong đợi cho track tiếng Việt gán đúng:

index=2
codec_name=mov_text
TAG:language=vie
TAG:title=Vietnamese

Những gì cần kiểm tra:

  • TAG:language=und: mã ISO 639-2 không được nhận; kiểm tra lại cách đánh vần ba chữ cái theo bảng trên.
  • Dòng TAG:language không xuất hiện: index trong -metadata:s:s:N bị sai; đếm stream phụ đề từ 0.
  • codec_name không phải mov_text trong output MP4: codec phụ đề sai; hầu hết player sẽ âm thầm bỏ qua track đó.

Với file MKV, dùng mkvinfo output.mkv (có trong MKVToolNix) thay thế - nó in cả Language và LanguageIETF rõ ràng cho từng track, giúp xác nhận subtag BCP 47 đã được ghi đúng.

Khi nào nên thuê dịch thuật phụ đề, khi nào tự làm?

Việc gán thẻ và mux ở trên hoàn toàn trong tầm tay của bất kỳ ai có ffmpeg hoặc MKVToolNix. Khi đã có file phụ đề, công việc kỹ thuật chỉ mất vài phút.

Điều không thể tự động hóa là bản thân việc dịch. Vai trò của tôi trong một lần giao hàng phụ đề là đọc thoại nguồn bằng tiếng Anh, tìm cách diễn đạt tiếng Việt phù hợp với thời gian và tốc độ đọc, rồi kiểm tra từng cue theo style guide của nền tảng. Bước mux với thẻ ngôn ngữ đúng là năm phút cuối của dự án, không phải giá trị xứng đáng được trả tiền.

Nếu bạn đã có file SRT đúng ngôn ngữ và cần gán thẻ và mux chính xác, các lệnh trên xử lý được. Nếu cần file phụ đề được dịch, định thời gian và kiểm tra bởi người bản ngữ, đó là việc tôi làm trên trang dịch thuật phụ đề.

Câu hỏi thường gặp

Mã ngôn ngữ đúng cho tiếng Việt trong ffmpeg là gì?

Dùng vie, mã ISO 639-2 ba chữ cái cho tiếng Việt. Tránh dùng vi (dạng BCP 47) cho trường -metadata:s:s:N language= của ffmpeg. Một số bản ffmpeg tự chuyển đổi vi sang vie, nhưng hành vi này không nhất quán trên mọi phiên bản. Đặt rõ vie và thẻ sẽ dùng được trên VLC, Plex, Apple TV, Infuse và công cụ QC của nền tảng streaming.

Có thể dùng thẻ BCP 47 như zh-Hans trong MP4 không?

Trường -metadata:s:s:N language= chuẩn của ffmpeg chỉ nhận mã ISO 639-2 ba chữ cái, không phải subtag BCP 47 đầy đủ như zh-Hans. Container MP4 không có slot chuẩn cho subtag chữ viết theo cách MKV có qua LanguageIETF. Với track phụ đề cần phân biệt Giản thể và Phồn thể thành hai tùy chọn có tên riêng, MKV với mkvmerge là lựa chọn container đáng tin cậy hơn.

Mã ngôn ngữ trong container có ảnh hưởng đến index hóa SEO không?

Không trực tiếp. Với web delivery, thuộc tính srclang của phần tử HTML <track> dùng BCP 47 (ví dụ srclang="vi"), và trình duyệt lẫn công cụ tìm kiếm dùng thuộc tính đó cho truy cập và index hóa. Thẻ ngôn ngữ ở cấp container là cho player cục bộ, QC nền tảng streaming và phần mềm thư viện media.

Điều gì xảy ra nếu giao hàng file có thẻ ngôn ngữ sai lên nền tảng streaming?

Các công cụ QC tự động tại nền tảng như Netflix hoặc Amazon kiểm tra metadata track phụ đề theo spec giao hàng mong đợi. Mã ISO 639-2 sai hoặc thiếu trên track phụ đề thường tạo ra flag trong báo cáo QC, có thể chặn ingest hoặc yêu cầu sửa và giao lại asset. Phát hiện sớm chỉ mất vài phút để sửa; phát hiện khi QC phát hành là chậm trễ tốn kém.

Làm sao tìm mã ISO 639-2 cho ngôn ngữ không có trong bảng này?

Nguồn tra cứu chính thức là danh sách mã ISO 639-2 của Thư viện Quốc hội Mỹ (loc.gov/standards/iso639-2/). Nó liệt kê cả dạng terminological (ffmpeg dùng) và dạng bibliographic cho mỗi ngôn ngữ. Với mã cơ sở và subtag BCP 47, Sổ đăng ký Subtag Ngôn ngữ IANA (iana.org) là nguồn chính thức.

Nguồn

Dao Huy (Lucas)
Dao Huy (Lucas)
Tốt nghiệp Trường Đại học Ngoại ngữ, Đại học Đà Nẵng. Ký cam kết chính xác trên mọi bản dịch có xác nhận (USCIS, IRCC).

Bài viết bởi Đào Huy (Lucas), biên dịch viên và chuyên viên bản địa hóa tiếng Việt (Anh, Trung, Pháp sang Việt). See translation services →

Báo giáWhatsApp