最近投屏接到客诉说苹果哔哩哔哩客户端投直播会显示播放失败。
我测试发现安卓端哔哩哔哩是正常的,某投屏软件也能正常播放,我对此感到困惑。通过tcpdump
分析,发现它的ijk播放器在访问链接时改变了User Agent。
然后我就开始测试了:
1 2 3 4 5 6 7 8
| 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"); headers.put("User-Agent", "stagefright"); headers.put("User-Agent", "a"); headers.put("User-Agent", "Androi"); headers.put("User-Agent", "stagefrigh");
|
经测试发现含有Android或者stagefright都会导致访问403,其他都正常。
而安卓默认的User Agent就包含了Android和stagefright。
1 2 3 4 5 6 7 8 9 10 11 12
| 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播放器
1
| mIjkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "user_agent", "Bilibili Freedoooooom/MarkII");
|
1 2
| 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版本的问题。
参考链接:
哔哩哔哩视频403Forbidden原因
浅度剖析B站的新 -352 风控策略 - A Salty Blog