Voice AI im lặng sau tường lửa chưa chắc là lỗi của model
Giao diện báo đã kết nối, agent đã vào phòng mà không ai nghe thấy gì; kiểm tra lần lượt candidate, cặp kết nối và phản ứng của agent sẽ cho bạn biết nên gọi đội mạng hay mở lại code.

Tóm tắt nhanh
- Trang web tải được chỉ chứng minh HTTPS đi qua; đường UDP cho âm thanh có thể bị chặn riêng.
- STUN cho biết địa chỉ công khai, ICE kiểm tra cặp nào thật sự thông, TURN chuyển tiếp khi không còn lựa chọn khác.
- Luôn chuẩn bị TURN/TLS trên cổng 443 làm đường dự phòng, nhưng vẫn xin mở UDP để có chất lượng tốt nhất.
Thử hình dung sáng go-live của một voice agent cho tổng đài. Bản demo chạy tốt trên laptop của bạn và trên điện thoại 4G của người quản lý dự án. Trong mạng công ty khách, giao diện báo đã kết nối, agent đã vào phòng, và không ai nghe thấy gì.
Phản xạ tự nhiên là nghi model hoặc mở lại prompt. Đừng vội. Khi trang web tải được mà tiếng thì không, câu hỏi đầu tiên phải là: gói âm thanh có đường đi hay không?
Lúc này, gửi một ticket rồi ngồi chờ không giúp được gì. Nếu bạn ngồi cạnh đội IT của khách, chỉ ra đúng đường bị chặn và xin đúng cổng, buổi go-live có thể cứu được ngay trong sáng hôm đó.
Trang web thông, tiếng nói chưa chắc thông
Hãy tách cuộc gọi thành hai dòng. Dòng đầu là trang web, đi qua HTTPS: giao diện hiện lên nghĩa là dòng này thông. Dòng thứ hai là âm thanh, và nó không nhất thiết đi cùng đường.
Danh sách cổng trong tài liệu tự triển khai của LiveKit cho thấy rõ sự tách biệt ấy: 443 phục vụ HTTPS và TURN/TLS, còn WebRTC cần thêm 3478/UDP, dải 50000-60000/UDP và 7881 cho đường TCP.
Thử hình dung một tường lửa chỉ cho 443 đi qua, trong khi hệ thống của bạn chưa bật TURN/TLS. Giao diện vẫn xanh vì HTTPS không gặp vấn đề gì, còn gói tiếng thì không có lối ra.
Ba nhân vật: ICE, STUN và TURN
MDN mô tả ICE là khung giúp trình duyệt kết nối với peer: vượt tường lửa, lấy địa chỉ khi thiết bị không có IP công khai, chuyển tiếp dữ liệu khi cần. Hãy coi ICE như người đi tìm đường. Nó gom mọi địa chỉ có thể dùng, gọi là candidate, rồi thử xem cặp nào đi được.
Candidate có ba loại chính. host mang địa chỉ thật của máy. srflx là địa chỉ mà NAT cấp khi gói tin đi qua nó tới máy chủ, và STUN chính là giao thức giúp bạn khám phá địa chỉ công khai cùng các hạn chế của router. relay là địa chỉ lấy từ máy chủ TURN, dùng để chuyển tiếp media giữa hai peer.
Có địa chỉ công khai vẫn chưa đủ. Gặp symmetric NAT, TURN vượt qua bằng cách chuyển tiếp mọi dữ liệu qua máy chủ. Cái giá là chi phí thêm, nên cả MDN lẫn RFC 8656 đều khuyên chỉ dùng TURN khi không tìm được đường nào khác.
Khi gặp mạng doanh nghiệp, nên nghi UDP bị chặn trước, rồi mới xét đến NAT. Phép thử dưới đây trả lời câu hỏi đó trong vài phút.
Đọc mạng của khách qua vài dòng log
Quay lại sáng go-live. Mở DevTools trên một máy thật trong mạng của khách, rồi thử từng đường riêng lẻ. Thay tên máy chủ và thông tin đăng nhập bằng của hệ thống bạn.
function probe(url, creds = {}) {
const pc = new RTCPeerConnection({ iceServers: [{ urls: url, ...creds }] });
pc.createDataChannel('probe'); // needed to trigger candidate gathering
pc.onicecandidate = (e) => {
if (e.candidate) console.log(url, e.candidate.type);
};
pc.createOffer().then((offer) => pc.setLocalDescription(offer));
}
const creds = { username: 'TEMP_USER', credential: 'TEMP_PASS' };
probe('stun:media.example.com:3478');
probe('turn:media.example.com:3478?transport=udp', creds);
probe('turns:media.example.com:443?transport=tcp', creds);
Giả sử kết quả trả về như sau:
stun:media.example.com:3478 host
turn:media.example.com:3478?transport=udp host
turns:media.example.com:443?transport=tcp host
turns:media.example.com:443?transport=tcp relay
Đọc từng dòng. host luôn có nên chưa nói lên điều gì. Đường STUN không trả về srflx, TURN qua UDP không trả về relay: hai đường đi bằng UDP đều im. Chỉ TURN/TLS trên cổng 443 trả lời, nên kết luận hợp lý là UDP đi ra đang bị chặn, còn 443 vẫn mở.
Nếu cả dòng 443 cũng chỉ có host, hãy rà cấu hình TURN phía bạn trước, rồi gọi IT của khách kèm log.
Nhưng candidate chỉ là địa chỉ có thể dùng để nhận dữ liệu, chưa phải đường đã thông. RFC 8445 nói mục đích của ICE là tìm ra cặp địa chỉ nào hoạt động được, và mỗi lần kiểm tra là một giao dịch STUN trên một cặp cụ thể.
Vì thế, hãy gọi một cuộc thật rồi tìm trong log của client và máy chủ xem ICE có cặp nào thành công không. Nếu không có cặp nào, tiếng chưa có đường đi và việc vẫn thuộc về mạng: gọi IT của khách kèm log, và nhờ người phụ trách máy chủ media phía bạn xem cùng.
Tầng cuối nằm ngoài mạng. Nếu đã có cặp thành công mà tai không nghe gì, đừng gọi IT vội. Hãy nói một câu vào micro rồi xem log của agent: nó có ghi nhận lời bạn không, có sinh câu trả lời không?
Agent không nhận được gì thì hãy nghi chiều đi: micro, quyền trình duyệt. Agent đã trả lời mà loa vẫn im thì nghi chiều về: trình duyệt chặn autoplay, hoặc phần phát tiếng trong pipeline của agent.
Xin IT mở đúng thứ gì?
Câu “mở tường lửa giúp” không cho đội IT thứ gì để duyệt. Một danh sách cổng cụ thể thì có. Tài liệu triển khai của LiveKit là một ví dụ tốt để học cách đọc; nếu dùng hệ thống khác, hãy tra lại cổng của nhà cung cấp đó.
| Đường đi | Cổng theo LiveKit | Việc cần làm với IT |
|---|---|---|
| UDP | 3478/UDP, 50000-60000/UDP | Luôn xin mở: đây là đường cho chất lượng tốt nhất |
| WebRTC qua TCP | 7881 | Xin mở thêm, nhưng không thay cho UDP |
| TURN/TLS | 443 | Xác nhận máy người dùng đi ra được, để dự phòng khi UDP không khả thi |
LiveKit dùng TURN/TLS trên TCP 443 khi UDP không khả thi, nhưng vẫn khuyến nghị mở các cổng UDP để có chất lượng âm thanh và video tốt nhất.
Nếu phía bạn đã triển khai TURN/TLS và probe trên 443 trả về relay, hãy nói với IT đúng như vậy: hôm nay có đường dự phòng qua 443, còn UDP là thứ bạn xin để hội thoại mượt hơn. Nếu chưa triển khai, cổng 443 mở cũng chưa cứu được cuộc gọi, và việc đầu tiên nằm ở phía bạn.
Ở khách hàng tiếp theo, hãy làm gì từ đầu?
Đừng đợi đến ngày go-live. Ngay từ tuần đầu, xin một máy đúng cấu hình người dùng cuối, cắm đúng mạng họ dùng, không phải Wi-Fi khách, rồi chạy probe và lưu kết quả vào tài liệu dự án.
Sau đó gọi một cuộc thật và ghi lại ICE có cặp nào thành công không, agent có nghe và trả lời không. Gửi IT bảng cổng kèm log làm bằng chứng. Khi họ đã xử lý, thử lại với iceTransportPolicy: 'relay' trong cấu hình RTCPeerConnection để chắc đường dự phòng hoạt động thật, không chỉ tồn tại trên giấy.
Những lỗi khiến bạn mất cả buổi sáng
Một cái bẫy quen thuộc là chỉ cấu hình STUN và kiểm thử từ nhà. Theo web.dev, phần lớn cuộc gọi WebRTC kết nối được chỉ với STUN, nên mạng ở nhà dễ cho mọi thứ lên xanh. Hướng dẫn của WebRTC.org lại nói thẳng rằng socket trực tiếp giữa các client thường không khả thi, và cách giải quyết phổ biến là dùng TURN.
Bẫy kế tiếp là có TURN nhưng chỉ chạy trên UDP. Gặp tường lửa chặn UDP, TURN đó cũng bị chặn theo; đó là lý do cần có TURN/TLS trên TCP 443. Ngược lại, ép mọi cuộc gọi qua relay cho chắc ăn thì lại tự gánh thêm chi phí ở những mạng vốn không cần, điều RFC 8656 khuyên tránh.
Cũng đừng dừng ở candidate. Thấy srflx hay relay rồi kết luận mạng ổn là chưa đủ, vì chỉ kiểm tra trên từng cặp mới trả lời được câu hỏi đó. Và đừng đổ cho mạng khi chưa xem log của agent, để rồi bắt đội IT của khách đi tìm một sự cố có thể không nằm ở chỗ họ.
Kể kỹ năng này trong CV thế nào?
Kỹ năng này đáng đưa vào CV, miễn là cụ thể. Khi đọc mô tả công việc voice AI, hãy để ý các từ WebRTC, TURN, NAT traversal. Khi kể về dự án, đừng viết “có kinh nghiệm WebRTC”: hãy kể mạng bị chặn gì, bạn chứng minh bằng log nào và đã xin mở cổng gì.
Bài tập: tự chặn UDP trên máy của bạn
Dựng một ứng dụng WebRTC nhỏ, hoặc dùng bản demo của nhà cung cấp, rồi đặt luật firewall trên chính máy bạn để chặn UDP đi ra, chừa DNS. Gọi thử khi chưa có TURN/TLS, ghi lại loại candidate từ probe và cuộc gọi có tiếng hay không, rồi bật TURN/TLS trên 443 và gọi lại.
Sau một buổi tối như vậy, cuộc gọi im lặng không còn là chuyện bí ẩn, vì bạn đã tự tay gây ra nó một lần. Lần tới, khi cả phòng họp quay sang nhìn bạn, bạn đã biết phải mở log nào trước.
Bài này có hữu ích không?
Cảm ơn bạn đã góp ý!
8 nguồn
- Introduction to WebRTC protocols - Web APIs | MDN
- RFC 8445: Interactive Connectivity Establishment (ICE)
- RFC 8656: Traversal Using Relays around NAT (TURN)
- RTCIceCandidate: type property | MDN
- WebRTC infrastructure (web.dev)
- Configuring firewalls | LiveKit docs
- Virtual machines | LiveKit docs
- TURN server | WebRTC