Android开发新手,若有错误请指出,谢谢~
视频播放
bilibili的核心功能不用说,即播放视频 + 弹幕功能,本章主要讲述如何在Android中播放B站视频(争取下一章中加入弹幕功能)。首先,Android中播放视频使用Bilibili官方开源的ijkMediaPlayer,Android自带的MediaPlayer支持格式有限,无法满足Bilibili视频源的格式。ijkPlayer的github中展示了许多编译、修改的内容,对于仅需要使用的可以暂时不看。
获取视频地址
视频主要分为2类,直播和点播,这两类的接口是不一样的。其中点播又有专辑、番剧等包含集数等概念的内容,需要播放不同内容。这里我们只讨论一个地址的那种,即单个视频。
- 直播地址
- 点播地址
直播地址URL如下,可以通过live/Index获取直播页的内容,其中最重要的内容为每一个直播Item的room_id,其他也有很多接口获取房间号内容,如直播详情、直播列表等,这里使用直播首页作为示例。
http://live.bilibili.com/AppIndex/home?_device=android&_hwid=51e96f5f2f54d5f9&_ulv=10000&access_key=563d6046f06289cbdcb472601ce5a761&appkey=c1b107428d337928&build=410000&platform=android&scale=xxhdpi&sign=fbdcfe141853f7e2c84c4d401f6a8758
{
owner: {
face: "http://i0.hdslb.com/bfs/face/ac9785955b2d95391495869e7d64b8dc7d9499d4.jpg",
mid: 867152,
name: "Tsubomixy"
},
cover: {
src: "http://i0.hdslb.com/group1/M00/B6/AA/oYYBAFbmgraAF4DkAADqc2Inrws485.jpg",
height: 180,
width: 320
},
title: "疯狂掉分少年",
room_id: 81414,
online: 157
}
每一个直播间的Item如上述Json,每一个视频直播都对应一个直播间Id,与Web端相同,通过调用接口获取视频直播地址。具体playurl接口获取直播视频地址如下,返回数据为xml格式,
http://live.bilibili.com/api/playurl?player=1&quality=0&cid=room_id
房间号23058为B站官方音乐直播间,房间号稳定,可供大家测试。将http://live.bilibili.com/api/playurl?player=1&quality=0&cid=23058 粘到浏览器中即可,这种xml格式浏览器无法直接解析因此可能看不到内容,需要查看源代码,即可查看到如下图的内容:
![直播地址xml](https://github.com/HakuLess/ImageLib/blob/master/blog/live_xml.png?raw=true =744x209)
url为默认使用线路,b1、b2、b3指的是备用线路1、2、3。至此,我们获取到了B站直播的播放地址。接下来就可以使用ijkplayer使用该地址进行播放视频。
点播地址URL与直播地址相似,同样有cid的概念。首先需要通过其他接口获取视频直播地址的cid,然后通过如下接口获取点播视频的地址:
String sign_this = string2MD5("appkey=" + appkey + "&cid=" + cid + secretkey);
String url = "http://interface.bilibili.com/playurl?appkey=" + appkey + "&cid=" + cid + "&sign=" + sign_this;
视频点播与直播不一样需要使用secretkey进行md5加密,这部分详细内容可以查看第0步的内容。这里使用cid为3885454为例,其获取地址URL为 http://interface.bilibili.com/playurl?appkey=f3bb208b3d081dc8&cid=3885454&sign=3aa2879fb591b4e297ed3e69156c821e 。
<video>
<result>suee</result>
<timelength>206000</timelength>
<format>
<![CDATA[ flv ]]>
</format>
<accept_format>
<![CDATA[ mp4,hdmp4,flv ]]>
</accept_format>
<accept_quality>
<![CDATA[ 3,2,1 ]]>
</accept_quality>
<from>
<![CDATA[ local ]]>
</from>
<seek_param>
<![CDATA[ start ]]>
</seek_param>
<seek_type>
<![CDATA[ offset ]]>
</seek_type>
<src>0</src>
<durl>
<order>1</order>
<length>206000</length>
<size>39674116</size>
<url>
<![CDATA[
http://cn-zjhz5-dx.acgvideo.com/vg11/0/28/3885454-1.flv?expires=1458561300&ssig=SalA4VKqDvz49duWpIJ1Tg&oi=1961670062&appkey=f3bb208b3d081dc8&or=3026306826&rate=0
]]>
</url>
<backup_url>
<url>
<![CDATA[
http://cn-zjwz3-dx.acgvideo.com/vg16/7/18/3885454-1.flv?expires=1458561300&ssig=OmgeF1kfdbUgTkGTBMO2xw&oi=1961670062&appkey=f3bb208b3d081dc8&or=3026306826&rate=0
]]>
</url>
<url>
<![CDATA[
http://cn-zjsx10-dx.acgvideo.com/vg2/f/a0/3885454-1.flv?expires=1458561300&ssig=MTYHl-CUFarh8LpXnMXjEg&oi=1961670062&appkey=f3bb208b3d081dc8&or=3026306826&rate=0
]]>
</url>
</backup_url>
</durl>
</video>```
其中三个URL分别为默认线路、备用线路1和备用线路2。至此,获取单个视频点播的视频地址~ 下面就可以使用播放器进行视频播放了~!
##### 播放视频
播放视频的方式不止一种,这里只提供使用ijkplayer播放视频的方式,需要的同学可以看[ijkplayer github](https://github.com/Bilibili/ijkplayer)。对于我们只使用不修改的同学,可以直接在gradle中配置即可。
required
allprojects {
repositories {
jcenter()
}
}
dependencies {
# required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.4.5.1'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.4.5.1'
# Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.4.5.1'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.4.5.1'
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.4.5.1'
# ExoPlayer as IMediaPlayer: optional, experimental
compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.4.5.1'
}
对于大部分情况只需要配置required项即可,之后就可以在项目中直接使用ijkMediaPlayer,使用方式与普通的MediaPlayer相似,具体代码如下:
private void playVideo(String uri) {
try {
ijkMediaPlayer.setDataSource(this, Uri.parse(uri));
ijkMediaPlayer.setDisplay(holder);
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
ijkMediaPlayer.setDisplay(holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
ijkMediaPlayer.prepareAsync();
ijkMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
完整项目代码可以在[我的github](https://github.com/HakuLess)中查看。项目截图与bilibili官方对比图如下:
![直播首页截图](https://github.com/HakuLess/ImageLib/blob/master/blog/compare_live_index.png?raw=true =578x499)
![直播页面_官方](https://raw.githubusercontent.com/HakuLess/ImageLib/master/blog/compare_live_play_bili.jpeg?raw=true =285x577)
![直播页面_自定义](https://github.com/HakuLess/ImageLib/blob/master/blog/compare_live_play_hbili.jpeg?raw=true?raw=true =285x577)
有待开发的功能还有很多,如弹幕、评论、视频下载等,大家敬请期待~
##### ThanksTo
* [bilibili视频解析](http://www.iippcc.com/bilibili/)
* [爱bilibili](http://www.ibilibili.com/)
* [B站视频地址获取](https://www.blackglory.me/bilibili-video-source-get/)
* [B站API](http://www.fuckbilibili.com/biliapi.html)
* [哔哩哔哩JJ](http://www.bilibilijj.com/)