💡 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=viecho tiếng Việt, không phảivi. Trong MKV, mkvmerge ghi cả phần tử ISO 639-2 cũ lẫnLanguageIETFtheo BCP 47 từ một lần đặt cờ duy nhất, cho phép dùngzh-Hanscho tiếng Trung giản thể, điều mà mã ba chữ cáizhomộ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:
Languagecũ (ISO 639-2) vàLanguageIETFmới (BCP 47); mkvmerge ghi cả hai từ một giá trị--languageduy 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 47 | Mã ISO 639-2 | Ghi chú |
|---|---|---|---|
| Tiếng Việt | vi | vie | Dùng vie trong ffmpeg MP4 |
| Tiếng Anh | en | eng | |
| Tiếng Pháp | fr | fra | |
| Tiếng Trung giản thể | zh-Hans | zho | zho một mình là không rõ |
| Tiếng Trung phồn thể | zh-Hant | zho | ISO 639-2 giống tiếng Trung giản thể |
| Tiếng Nhật | ja | jpn | |
| Tiếng Hàn | ko | kor | |
| Tiếng Tây Ban Nha | es | spa |
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ỉ địnhs:s:0có 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 ghizhovàoLanguagecũ vàzh-HansvàoLanguageIETF. Các player đọc đượcLanguageIETF(VLC 3.0+, mpv, Infuse) hiển thị "Chinese (Simplified)" là tùy chọn có tên riêng.0:trong--language 0:vilà 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:languagekhông xuất hiện: index trong-metadata:s:s:Nbị sai; đếm stream phụ đề từ 0. codec_namekhông phảimov_texttrong 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
- FFmpeg documentation: tùy chọn -metadata và stream specifiers - tài liệu chính thức cho cú pháp
-metadata:s:s:N language=. Kiểm tra tháng 11/2026. - MKVToolNix mkvmerge documentation: tùy chọn --language - ghi nhận hỗ trợ BCP 47 và ghi cặp phần tử
Language/LanguageIETF. Kiểm tra tháng 11/2026. - Library of Congress: Danh sách mã ISO 639-2 - tra cứu chính thức mã ba chữ cái bao gồm
vie,eng,fra,zho. Kiểm tra tháng 11/2026. - IETF RFC 5646: BCP 47 language tags - định nghĩa cú pháp BCP 47 bao gồm subtag chữ viết như
zh-Hansvàzh-Hant. Kiểm tra tháng 11/2026.

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 →
