在Android上播放m3u8文件的Exoplayer
在尝试了使用videoview和mediaplayer播放m3u8文件的多种方式后,我决定放弃。每次我播放m3u8文件时,我只听到声音。(请不要从堆栈溢出中写入URL来回答我的问题。我已将它们全部刷新) 一直在四处打听,终于了解到,exoplayer可能就是我要找的人。然而,exoplayer似乎是个新手,我找不到任何合适的教程。有人说我自己是个新手,所有关于tracker和blabla的讨论对我来说都太复杂了。我只想能够在我的应用程序中打开来自不同URL的所有m3u8文件,而无需将它们传递给vlc或任何外部意图 作为记录,我使用KitKat和更高版本。所以exoplayer应该是可实现的 因此,我急切地想要的是一个简单的教程,介绍如何使用exoplayer播放m3u8文件,或者以任何其他方式显示视频和播放音频,而不是仅使用其中一种。请不要将我链接到谷歌开发上的exoplayer页面。我也去过那里在Android上播放m3u8文件的Exoplayer,android,android-mediaplayer,m3u8,exoplayer,Android,Android Mediaplayer,M3u8,Exoplayer,在尝试了使用videoview和mediaplayer播放m3u8文件的多种方式后,我决定放弃。每次我播放m3u8文件时,我只听到声音。(请不要从堆栈溢出中写入URL来回答我的问题。我已将它们全部刷新) 一直在四处打听,终于了解到,exoplayer可能就是我要找的人。然而,exoplayer似乎是个新手,我找不到任何合适的教程。有人说我自己是个新手,所有关于tracker和blabla的讨论对我来说都太复杂了。我只想能够在我的应用程序中打开来自不同URL的所有m3u8文件,而无需将它们传递给v
提前感谢:)目前没有关于
ExoPlayer
的教程ExoPlayer
是MediaPlayer
的最佳选择,但目前对新手不太友好
您需要做的是转到github页面,查看demo
应用程序中的DemoPlayer
类
此应用程序可以打开许多不同的格式,包括
hls
这是使用ExoPlayer Lib流式传输m3u8文件的最简单方法,希望对您有所帮助
在Android 4.1+上,您可以使用此库。自述页面上提到的示例应该足以让您开始学习。我通过一些添加/修改复制了该代码片段
private void setupVideoView() {
EMVideoView emVideoView = (EMVideoView)findViewById(R.id.video_play_activity_video_view);
emVideoView.setOnPreparedListener(this);
//Enter your m3u8 URL below
emVideoView.setVideoURI(Uri.parse("http://SOMESERVER/playlist.m3u8"));
}
@Override
public void onPrepared(MediaPlayer mp) {
//Starts the video playback as soon as it is ready
emVideoView.start();
}
@Override
public void onPause() {
super.onPause();
//Pause Video Playback
emVideoView.pause();
}
我已经创建了一个演示应用程序来播放m3u8媒体文件 首先将渐变依赖项添加到文件中
compile 'com.google.android.exoplayer:exoplayer:r2.4.0'
创建一个简单的布局文件,将storage master.m3u8路径作为输入,并使用SimpleExoPlayerView视图播放下载的文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout mlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<android.support.design.widget.TextInputEditText
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:id="@+id/mediaPath"
android:layout_height="56dp" />
<android.support.v7.widget.AppCompatButton
android:id="@+id/play"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_below="@+id/mediaPath"
android:background="@color/colorAccent"
android:layout_width="match_parent"
android:text="Play"
android:layout_height="56dp" />
<com.google.android.exoplayer2.ui.SimpleExoPlayerView
android:layout_below="@+id/play"
android:id="@+id/video_view"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
创建一个简单的ExoPlayer活动来播放文件
public class ExoPlayer extends AppCompatActivity{
Context mContext;
SimpleExoPlayerView playerView;
EditText editText;
private ComponentListener componentListener;
private DataSource.Factory mediaDataSourceFactory;
private Handler mainHandler;
private DefaultTrackSelector trackSelector;
SimpleExoPlayer player;
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exoplayer);
mContext =this;
editText = (EditText) findViewById(R.id.mediaPath);
Button btnPlay = (Button) findViewById(R.id.play);
playerView = (SimpleExoPlayerView)findViewById(R.id.video_view);
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
componentListener = new ComponentListener();
trackSelector = new DefaultTrackSelector();
btnPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(editText.getText()!=null && editText.getText().length()>0){
initializePlayer(editText.getText().toString());
}
}
});
}
private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
return ((AnalyticsApplication) getApplication())
.buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
private void initializePlayer(String path) {
player = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);
player.addListener(componentListener);
// String path = file:///storage/emulated/0/SugarBox/master.m3u8";
Uri uri = Uri.parse(path);
MediaSource mediaSource = buildMediaSource(uri);
player.prepare(mediaSource, true, false);
playerView.setPlayer(player);
}
private MediaSource buildMediaSource(Uri uri) {
return new HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, null);
}
private void releasePlayer() {
if (player != null) {
player.removeListener(componentListener);
player.release();
player = null;
}
}
@Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
if(editText.getText()!=null && editText.getText().length()>0){
initializePlayer(editText.getText().toString());
}
}
}
@Override
public void onResume() {
super.onResume();
if ((Util.SDK_INT <= 23 || player == null)) {
if(editText.getText()!=null && editText.getText().length()>0){
initializePlayer(editText.getText().toString());
}
}
}
@Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
@Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
private class ComponentListener implements com.google.android.exoplayer2.ExoPlayer.EventListener{
@Override
public void onPlayerStateChanged(boolean playWhenReady,
int playbackState) {
String stateString;
switch (playbackState) {
case com.google.android.exoplayer2.ExoPlayer.STATE_IDLE:
stateString = "ExoPlayer.STATE_IDLE -";
break;
case com.google.android.exoplayer2.ExoPlayer.STATE_BUFFERING:
stateString = "ExoPlayer.STATE_BUFFERING -";
break;
case com.google.android.exoplayer2.ExoPlayer.STATE_READY:
stateString = "ExoPlayer.STATE_READY -";
break;
case com.google.android.exoplayer2.ExoPlayer.STATE_ENDED:
stateString = "ExoPlayer.STATE_ENDED -";
break;
default:
stateString = "UNKNOWN_STATE -";
break;
}
Log.d("ExopLayer", "changed state to " + stateString
+ " playWhenReady: " + playWhenReady);
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {}
@Override
public void onTracksChanged(TrackGroupArray trackGroups,
TrackSelectionArray trackSelections) {}
@Override
public void onLoadingChanged(boolean isLoading) {}
@Override
public void onPlayerError(ExoPlaybackException error) {}
@Override
public void onPositionDiscontinuity() {}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
}
private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray) throws UnsupportedDrmException {
if (Util.SDK_INT < 18) {
return null;
}
HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl,
buildHttpDataSourceFactory(false));
if (keyRequestPropertiesArray != null) {
for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) {
drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i],
keyRequestPropertiesArray[i + 1]);
}
}
return new DefaultDrmSessionManager<>(uuid,
FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, null);
}
private HttpDataSource.Factory buildHttpDataSourceFactory(boolean useBandwidthMeter) {
return ((AnalyticsApplication) getApplication())
.buildHttpDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
}
公共类ExoPlayer扩展AppCompative活动{
语境;
SimpleExoPlayerView-playerView;
编辑文本编辑文本;
私有组件监听器组件监听器;
私有数据源工厂mediaDataSourceFactory;
私人经理人;
私有DefaultTrackSelector;
SimpleExoPlayer;
专用静态最终DefaultBandwidthMeter带宽\ U米=新的DefaultBandwidthMeter();
@凌驾
创建时受保护的void(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u exoplayer);
mContext=这个;
editText=(editText)findViewById(R.id.mediaPath);
按钮btnPlay=(按钮)findViewById(R.id.play);
playerView=(SimpleExoPlayerView)findViewById(R.id.video\u视图);
mediaDataSourceFactory=buildDataSourceFactory(true);
mainHandler=新处理程序();
componentListener=新的componentListener();
trackSelector=新的DefaultTrackSelector();
btnPlay.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图){
if(editText.getText()!=null&&editText.getText().length()>0){
初始化图层(editText.getText().toString());
}
}
});
}
私有数据源.FactoryBuildDataSourceFactory(布尔使用带宽计){
返回((AnalyticsApplication)getApplication())
.buildDataSourceFactory(使用带宽计?带宽计:空);
}
私有void初始化层(字符串路径){
player=ExoPlayerFactory.newSimpleInstance(mContext,trackSelector);
player.addListener(componentListener);
//字符串路径=file:///storage/emulated/0/SugarBox/master.m3u8";
Uri=Uri.parse(路径);
MediaSource=buildMediaSource(uri);
player.prepare(mediaSource,true,false);
playerView.setPlayer(player);
}
私有媒体源buildMediaSource(Uri){
返回新的HlsMediaSource(uri、mediaDataSourceFactory、mainHandler、null);
}
私有无效释放玩家(){
如果(玩家!=null){
player.removeListener(componentListener);
player.release();
player=null;
}
}
@凌驾
public void onStart(){
super.onStart();
如果(Util.SDK_INT>23){
if(editText.getText()!=null&&editText.getText().length()>0){
初始化图层(editText.getText().toString());
}
}
}
@凌驾
恢复时公开作废(){
super.onResume();
如果((Util.SDK_INT 0){
初始化图层(editText.getText().toString());
}
}
}
@凌驾
公共无效暂停(){
super.onPause();
如果(Util.SDK_INT 23){
释放玩家();
}
}
私有类ComponentListener实现com.google.android.exoplayer2.ExoPlayer.EventListener{
@凌驾
PlayerStateChanged上的公共无效(布尔PlayerWhenReady,
int播放后台状态){
字符串stateString;
交换机(播放后台状态){
case com.google.android.exoplayer2.ExoPlayer.STATE_IDLE:
stateString=“ExoPlayer.STATE_IDLE-”;
打破
case com.google.android.exoplayer2.ExoPlayer.STATE_缓冲:
stateString=“ExoPlayer.STATE_BUFFERING-”;
打破
case com.google.android.exoplayer2.ExoPlayer.STATE_就绪:
stateString=“ExoPlayer.STATE_READY-”;
打破
case com.google.android.exoplayer2.ExoPlayer.STATE_结束:
stateString=“ExoPlayer.STATE_end-”;
打破
违约:
stateString=“未知_状态-”;
打破
}
Log.d(“ExopLayer”,“将状态更改为”+stateString
+“playWhenReady:”+playWhenReady);
}
@越过
public class ExoPlayer extends AppCompatActivity{
Context mContext;
SimpleExoPlayerView playerView;
EditText editText;
private ComponentListener componentListener;
private DataSource.Factory mediaDataSourceFactory;
private Handler mainHandler;
private DefaultTrackSelector trackSelector;
SimpleExoPlayer player;
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exoplayer);
mContext =this;
editText = (EditText) findViewById(R.id.mediaPath);
Button btnPlay = (Button) findViewById(R.id.play);
playerView = (SimpleExoPlayerView)findViewById(R.id.video_view);
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
componentListener = new ComponentListener();
trackSelector = new DefaultTrackSelector();
btnPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(editText.getText()!=null && editText.getText().length()>0){
initializePlayer(editText.getText().toString());
}
}
});
}
private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
return ((AnalyticsApplication) getApplication())
.buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
private void initializePlayer(String path) {
player = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);
player.addListener(componentListener);
// String path = file:///storage/emulated/0/SugarBox/master.m3u8";
Uri uri = Uri.parse(path);
MediaSource mediaSource = buildMediaSource(uri);
player.prepare(mediaSource, true, false);
playerView.setPlayer(player);
}
private MediaSource buildMediaSource(Uri uri) {
return new HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, null);
}
private void releasePlayer() {
if (player != null) {
player.removeListener(componentListener);
player.release();
player = null;
}
}
@Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
if(editText.getText()!=null && editText.getText().length()>0){
initializePlayer(editText.getText().toString());
}
}
}
@Override
public void onResume() {
super.onResume();
if ((Util.SDK_INT <= 23 || player == null)) {
if(editText.getText()!=null && editText.getText().length()>0){
initializePlayer(editText.getText().toString());
}
}
}
@Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
@Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
private class ComponentListener implements com.google.android.exoplayer2.ExoPlayer.EventListener{
@Override
public void onPlayerStateChanged(boolean playWhenReady,
int playbackState) {
String stateString;
switch (playbackState) {
case com.google.android.exoplayer2.ExoPlayer.STATE_IDLE:
stateString = "ExoPlayer.STATE_IDLE -";
break;
case com.google.android.exoplayer2.ExoPlayer.STATE_BUFFERING:
stateString = "ExoPlayer.STATE_BUFFERING -";
break;
case com.google.android.exoplayer2.ExoPlayer.STATE_READY:
stateString = "ExoPlayer.STATE_READY -";
break;
case com.google.android.exoplayer2.ExoPlayer.STATE_ENDED:
stateString = "ExoPlayer.STATE_ENDED -";
break;
default:
stateString = "UNKNOWN_STATE -";
break;
}
Log.d("ExopLayer", "changed state to " + stateString
+ " playWhenReady: " + playWhenReady);
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {}
@Override
public void onTracksChanged(TrackGroupArray trackGroups,
TrackSelectionArray trackSelections) {}
@Override
public void onLoadingChanged(boolean isLoading) {}
@Override
public void onPlayerError(ExoPlaybackException error) {}
@Override
public void onPositionDiscontinuity() {}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
}
private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray) throws UnsupportedDrmException {
if (Util.SDK_INT < 18) {
return null;
}
HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl,
buildHttpDataSourceFactory(false));
if (keyRequestPropertiesArray != null) {
for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) {
drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i],
keyRequestPropertiesArray[i + 1]);
}
}
return new DefaultDrmSessionManager<>(uuid,
FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, null);
}
private HttpDataSource.Factory buildHttpDataSourceFactory(boolean useBandwidthMeter) {
return ((AnalyticsApplication) getApplication())
.buildHttpDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
}
videoView = findViewById(R.id.videoViewXml);
final ProgressDialog progressDialog = new ProgressDialog(VideoActivity.this);
progressDialog.setMessage("Please Wait");
progressDialog.setCancelable(false);
progressDialog.show();
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
videoView.setMediaController(mediaController);
videoView.setVideoURI(Uri.parse(VIDEO_PATH));
videoView.start();
videoView.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
progressDialog.dismiss();
}
});
private fun buildMediaSource(uri: Uri): MediaSource {
val userAgent = "exoplayer-codelab"
return if (uri.lastPathSegment!!.contains("mp3") || uri.lastPathSegment!!.contains("mp4")) {
ExtractorMediaSource.Factory(DefaultHttpDataSourceFactory(userAgent))
.createMediaSource(uri)
} else {
HlsMediaSource.Factory(DefaultHttpDataSourceFactory(userAgent))
.createMediaSource(uri)
}
}
val mediaSource = buildMediaSource(Uri.parse(stories[counter].mediaUrl))
simpleExoPlayer.prepare(mediaSource, false, false)