[Android]使用MediaPlayer播放m3u8地址遇到的问题

377 查看

已经失效了, 请自行解析m3u8文件获得真实视频地址进行播放.

请参考 http://www.denghaojie.cn/android-youku-url-m3u8-mp4-479.html

在这坑里掉了几天,终于爬出来了。

起因是youku的拼接地址方式失效了,经过抓包分析iOS版本的播放地址,发现其使用的m3u8地址为以下:

http://pl.youku.com/playlist/m3u8?vid={id}&type=mp4
http://pl.youku.com/playlist/m3u8?vid={id}&type=hd2
http://pl.youku.com/playlist/m3u8?vid={id}&type=flv

对应不同的清晰度。

发现地址以后iOS的播放就没啥问题了,安卓这边,地址填到原先的播放代码里面,在设备上测试也通过。播放相关代码大致如下:

MediaPlayer mediaplayer = new MediaPlayer();
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaplayer.setOnBufferingUpdateListener(this);
mediaplayer.setOnCompletionListener(this);
mediaplayer.setOnPreparedListener(this);
mediaplayer.setOnErrorListener(this);
mediaplayer.setOnVideoSizeChangedListener( this );
mediaplayer.setDataSource(url);
mediaplayer.prepare();

但是做兼容性测试的时候发现有大约一半的设备不能播放,症状是在OnPreparedListener接口的OnPrepared的回调被调用时,无法获得视频的高宽以及长度信息。

@Override
public void onPrepared(MediaPlayer mp) { // prepareAsync结束后调用
    int videoWidth = mp.getVideoWidth();
    int videoHeight = mp.getVideoHeight();
    if (videoHeight != 0 && videoWidth != 0) {
        play();//播放视频
        resizePlayWindow();// 重新计算播放窗口大小
        mVideoListener.onPrepareEnd(videoWidth, videoHeight);
    }
}

此处获得的videoWidth 以及videoHeight均为0。

同样,OnVideoSizeChangedListener接口的onVideoSizeChanged 回调返回的高宽也都未0。

反编译其他类似应用后,发现问题出在OnPrepared方法。正常工作的应用处理如下:

@Override
public void onPrepared(MediaPlayer mp) { // prepareAsync结束后调用
    int videoWidth = mp.getVideoWidth();
    int videoHeight = mp.getVideoHeight();
    if (videoHeight != 0 && videoWidth != 0) {
        play();//
        resizePlayWindow();// 重新计算播放窗口大小
        mVideoListener.onPrepareEnd(videoWidth, videoHeight);
    } else {
        mMediaPlayer.start();
    }
}

即在无法获得信息的情况下仍然start MediaPlayer。这样处理后会再次触发OnVideoSizeChangedListener接口的onVideoSizeChanged接口,并且在这个回调时能正确的返回视频信息。修改onVideoSizeChanged实现如下:

@Override
public void onVideoSizeChanged( MediaPlayer mediaPlayer, int width, int height ) {
    //此时width与height包含正确的视频高宽。
    if(width > 0 && height > 0) {
        play();//获得视频高宽后播放。
        resizePlayWindow();// 重新计算播放窗口大小
        // 初始化完成,更新ui
        mVideoListener.onPrepareEnd(width, height);
    }
}

修改后在所有设备上均能正常播放m3u8视频。


以上方式都过期了.

目前采取以下方式来获得youku的播放地址:

  1. 后台开启一个webview去载入youku的页面
  2. 分析它的页面代码来获得真实的播放源

m3u8文件使用之前的方式也不能完美播放, 目前使用以下方式播放:

由于m3u8格式本身是一个视频列表文件, 对于非直播的视频源, 可以下载并解析此文件来获得其中的视频地址,并使用MediaPlayer等控件进行播放.