什么是DTX功能
Opus编解码器中的DTX(Discontinuous Transmission,不连续传输)功能是一种优化技术,旨在通过动态调整数据传输以节省带宽和功耗。
工作原理
- 语音活动检测(VAD)
DTX通过VAD实时检测输入音频中是否有语音活动。当检测到静音或背景噪声时,停止发送有效音频数据包。
- 舒适噪声生成(CNG)
在静音期间,发送端会生成极低比特率的“舒适噪声”参数(而非传输完整音频包),接收端据此合成与环境匹配的背景噪声,避免用户因完全静音误以为通话中断。
核心优势
- 带宽节省
静音时段仅发送少量CNG数据(如每400毫秒一个包),显著降低平均带宽占用(尤其在语音通话中,静音约占50%时间)。
- 降低功耗
减少数据包传输和处理频率,延长移动设备电池续航。
- 无缝体验
CNG维持自然通话氛围,避免静音突兀感。
实现方式
在Answer中找到描述opus的行
a=fmtp:111 minptime=10;useinbandfec=1
在后面追加内容: usedtx=1
a=fmtp:111 minptime=10;useinbandfec=1;usedtx=1
然后将修改后的answer送到浏览器中
效果
代码
可以直接从gittee获取源代码,也可以直接使用下面的代码,代码的测试环境要在设备连接wifi下才能正常建立连接。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>webrtc连接</title>
</head>
<body>
<video id="localStream" style="width: 320px; height: 240px;" autoplay muted></video>
<video id="remoteStream" style="width: 320px; height: 240px;" autoplay controls > </video>
<button id="deviceBtn">打开设备</button>
<button id="startBtn">建立连接</button>
<script>
let localStream = null;
let localVideo = document.getElementById("localStream");
let remoteVideo = document.getElementById("remoteStream")
let deviceBtn = document.getElementById("deviceBtn");
let startBtn = document.getElementById("startBtn");
let pc_pub = new RTCPeerConnection();
let pc_sub = new RTCPeerConnection();
deviceBtn.addEventListener("click", () => {
navigator.mediaDevices.getUserMedia({audio: true }).then((mediastream) => {
localStream = mediastream;
localVideo.srcObject = mediastream;
})
})
function stopPlay () {
if (remoteVideo.srcObject) {
remoteVideo.srcObject = null;
}
}
startBtn.addEventListener("click", () => {
pc_pub.addTrack(localStream.getAudioTracks()[0], localStream);
pc_pub.createOffer().then((offer) => {
pc_pub.setLocalDescription(offer).then(() => {
pc_sub.setRemoteDescription(offer).then(() => {
pc_sub.createAnswer().then((answer) => {
pc_sub.setLocalDescription(answer).then(() => {
answer.sdp = answer.sdp.replace(/(a=fmtp:\d+.*?\buseinbandfec=1\b)(?![^;\n]*\busedtx=1\b)/gi,'$1;usedtx=1');
pc_pub.setRemoteDescription(answer).then(() => {
})
})
})
})
})
})
})
pc_pub.addEventListener('icecandidate', (event) => {
if (event.candidate) {
pc_sub.addIceCandidate(event.candidate);
}
})
pc_sub.addEventListener('icecandidate', (event) => {
if (event.candidate) {
pc_pub.addIceCandidate(event.candidate);
}
})
pc_sub.addEventListener('track', (event) => {
remoteVideo.srcObject = event.streams[0];
})
</script>
</body>
其他
如果你也是专注前端多媒体或者对前端多媒体感兴趣,可以关注