我们使用webrtc的时候遇到过带宽占用太高的问题。查看别人的博客也发现他们的项目一般都是支持一个服务器5到6人的语音。这是成本太高的问题。
其实webrtc自己是可以设置这些的。
仔细阅读webrtc的源码,我设置如下的参数,使得带宽减少了一半多。一个5M服务器可以支持近30人。
private static final boolean _preferIsac = true; private static final int _audioStartBitrate = 0;
调用下面的两个函数:
private static String preferCodec(
String sdpDescription, String codec, boolean isAudio) {
String[] lines = sdpDescription.split("\r\n");
int mLineIndex = -1;
String codecRtpMap = null;
// a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
String regex = "^a=rtpmap:(\\d+) " + codec + "(/\\d+)+[\r]?$";
Pattern codecPattern = Pattern.compile(regex);
String mediaDescription = "m=video ";
if (isAudio) {
mediaDescription = "m=audio ";
}
for (int i = 0; (i < lines.length)
&& (mLineIndex == -1 || codecRtpMap == null); i++) {
if (lines[i].startsWith(mediaDescription)) {
mLineIndex = i;
continue;
}
Matcher codecMatcher = codecPattern.matcher(lines[i]);
if (codecMatcher.matches()) {
codecRtpMap = codecMatcher.group(1);
}
}
if (mLineIndex == -1) {
Log.w(TAG, "No " + mediaDescription + " line, so can't prefer " + codec);
return sdpDescription;
}
if (codecRtpMap == null) {
Log.w(TAG, "No rtpmap for " + codec);
return sdpDescription;
}
Log.d(TAG, "Found " + codec + " rtpmap " + codecRtpMap + ", prefer at "
+ lines[mLineIndex]);
String[] origMLineParts = lines[mLineIndex].split(" ");
if (origMLineParts.length > 3) {
StringBuilder newMLine = new StringBuilder();
int origPartIndex = 0;
// Format is: m=<media> <port> <proto> <fmt> ...
newMLine.append(origMLineParts[origPartIndex++]).append(" ");
newMLine.append(origMLineParts[origPartIndex++]).append(" ");
newMLine.append(origMLineParts[origPartIndex++]).append(" ");
newMLine.append(codecRtpMap);
for (; origPartIndex < origMLineParts.length; origPartIndex++) {
if (!origMLineParts[origPartIndex].equals(codecRtpMap)) {
newMLine.append(" ").append(origMLineParts[origPartIndex]);
}
}
lines[mLineIndex] = newMLine.toString();
Log.d(TAG, "Change media description: " + lines[mLineIndex]);
} else {
Log.e(TAG, "Wrong SDP media description format: " + lines[mLineIndex]);
}
StringBuilder newSdpDescription = new StringBuilder();
for (String line : lines) {
newSdpDescription.append(line).append("\r\n");
}
return newSdpDescription.toString();
}
private static String setStartBitrate(String codec, boolean isVideoCodec,
String sdpDescription, int bitrateKbps) {
String[] lines = sdpDescription.split("\r\n");
int rtpmapLineIndex = -1;
boolean sdpFormatUpdated = false;
String codecRtpMap = null;
// Search for codec rtpmap in format
// a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
String regex = "^a=rtpmap:(\\d+) " + codec + "(/\\d+)+[\r]?$";
Pattern codecPattern = Pattern.compile(regex);
for (int i = 0; i < lines.length; i++) {
Matcher codecMatcher = codecPattern.matcher(lines[i]);
if (codecMatcher.matches()) {
codecRtpMap = codecMatcher.group(1);
rtpmapLineIndex = i;
break;
}
}
if (codecRtpMap == null) {
Log.w(TAG, "No rtpmap for " + codec + " codec");
return sdpDescription;
}
Log.d(TAG, "Found " + codec + " rtpmap " + codecRtpMap
+ " at " + lines[rtpmapLineIndex]);
// Check if a=fmtp string already exist in remote SDP for this codec and
// update it with new bitrate parameter.
regex = "^a=fmtp:" + codecRtpMap + " \\w+=\\d+.*[\r]?$";
codecPattern = Pattern.compile(regex);
for (int i = 0; i < lines.length; i++) {
Matcher codecMatcher = codecPattern.matcher(lines[i]);
if (codecMatcher.matches()) {
Log.d(TAG, "Found " + codec + " " + lines[i]);
if (isVideoCodec) {
lines[i] += "; " + VIDEO_CODEC_PARAM_START_BITRATE
+ "=" + bitrateKbps;
} else {
lines[i] += "; " + AUDIO_CODEC_PARAM_BITRATE
+ "=" + (bitrateKbps * 1000);
}
Log.d(TAG, "Update remote SDP line: " + lines[i]);
sdpFormatUpdated = true;
break;
}
}
StringBuilder newSdpDescription = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
newSdpDescription.append(lines[i]).append("\r\n");
// Append new a=fmtp line if no such line exist for a codec.
if (!sdpFormatUpdated && i == rtpmapLineIndex) {
String bitrateSet;
if (isVideoCodec) {
bitrateSet = "a=fmtp:" + codecRtpMap + " "
+ VIDEO_CODEC_PARAM_START_BITRATE + "=" + bitrateKbps;
} else {
bitrateSet = "a=fmtp:" + codecRtpMap + " "
+ AUDIO_CODEC_PARAM_BITRATE + "=" + (bitrateKbps * 1000);
}
Log.d(TAG, "Add remote SDP line: " + bitrateSet);
newSdpDescription.append(bitrateSet).append("\r\n");
}
}
return newSdpDescription.toString();
}
这两个函数的使用方法可以在webrtc的源码中获得,webrtc-master-webrtc\examples\androidapp\src\org\appspot\apprtc\PeerConnectionClient.java
大家也可以尝试其他的方法。或许能够得到更喜人的方案。我们的结果是ICE连接占用23KB左右,声音相关35KB。
如果有更好的方案请邮件发我:
fatestaymq2@foxmail.com