最近投屏接到客诉说苹果哔哩哔哩客户端投直播会显示播放失败。
我测试发现安卓端哔哩哔哩是正常的,某投屏软件也能正常播放,我对此感到困惑。通过tcpdump
分析,发现它的ijk播放器在访问链接时改变了User Agent。
然后我就开始测试了:
arduino
headers.put("User-Agent", "Mozilla/5.0.BiliTV/1.7.2"); //正常
headers.put("User-Agent", "Bilibili Freedoooooom/MarkII");//正常
headers.put("User-Agent", "Linux Androi");//正常
headers.put("User-Agent", "Android");//403 forbidden
headers.put("User-Agent", "stagefright");//403 forbidden
headers.put("User-Agent", "a");//正常
headers.put("User-Agent", "Androi");//正常
headers.put("User-Agent", "stagefrigh");//正常
经测试发现含有Android或者stagefright都会导致访问403,其他都正常。
而安卓默认的User Agent就包含了Android和stagefright。
arduino
AString MakeUserAgent() {
AString ua;
ua.append("stagefright/1.2 (Linux;Android ");
#if (PROPERTY_VALUE_MAX < 8)
#error "PROPERTY_VALUE_MAX must be at least 8"
#endif
char value[PROPERTY_VALUE_MAX];
property_get("ro.build.version.release", value, "Unknown");
ua.append(value);
ua.append(")");
return ua;
}
解决
既然知道了问题原因,那么解决起来就很简单了,当判断是哔哩哔哩的直播链接时,改变播放器的user agent。
ijk播放器
arduino
mIjkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "user_agent", "Bilibili Freedoooooom/MarkII");
MediaPlayer播放器
kotlin
headers.put("User-Agent", "Bilibili Freedoooooom/MarkII");
mPlayer.setDataSource(this, Uri.parse(videoUrl), headers);
注意,由于谷歌的bug,安卓5.0和5.1不支持该设置
MediaPlayer ignores User-Agent header [37018604] - Issue Tracker
.../MediaHTTP.cpp · Gerrit Code Review
其他
当然也可以通过本地代理来解决,拦截播放请求就可以随意改变user agent了,这也可以解决安卓5.0以下MediaPlayer不支持某些tls版本的问题。
参考链接: