Exoplayer playing m3u8 files Android

2020-02-08 18:02发布

问题:

After trying multiple ways of playing m3u8 files using videoview and mediaplayer I decided to give up. Everytime i play the m3u8 file I only hear the voice.(please dont write urls from stack overflow answering my question. I' ve red them all ) Been asking around ,finally got to know that exoplayer maybe is the one I'm looking for. However exoplayer seems to be a newbie and I can'n find any proper tutorial. That been said Im myself a newbie and all talks about tracker and blabla seem just too complicated for me. I only want to be able to open all my m3u8 files from different urls in my app without passing them to vlc or any external intents.

For the record I use KitKat and above. So exoplayer should be implementable.

So what Im desperatly asking for is a simple tutorial in how I can play my m3u8 files using exoplayer or anyother way that shows the video and play the audio and NOT just one of them. Please dont link me to the exoplayer page on google dev. Ive been there too.

Thanks in advance :)

回答1:

On Android 4.1+, you can use this library https://github.com/brianwernick/ExoMedia/ . The example mentioned on the Read-me page should be sufficient to get you started. I have reproduced that code snippet with a few additions/modifications.

            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();
            }


回答2:

I Have created one demo app to play m3u8 media file

First add gradle dependencies to your file

compile 'com.google.android.exoplayer:exoplayer:r2.4.0'

Create a simple layout file with storage master.m3u8 path as input and SimpleExoPlayerView view to play downloaded files.

 <?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>

Create a simple ExoPlayer Activity to play Files.

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);


  }


}


回答3:

I have worked with m3u8 with following code

    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();
        }
    });


回答4:

This is the simplest way to stream m3u8 files using ExoPlayer Lib hope to help https://github.com/karim23/SimpleStreamPlayer/tree/master

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = getApplicationContext();
    setContentView(R.layout.activity_main);
    //change the live streaming URL with yours. 
    contentUri = "http://abclive.abcnews.com/i/abc_live4@136330/index_1200_av-b.m3u8?sd=10&b=1200&rebase=on";
    // contentType = DemoUtil.TYPE_HLS;
    final Intent intent = new Intent(context, VideoPlayerActivity.class).setData(Uri.parse(contentUri))
            .putExtra(VideoPlayerActivity.CONTENT_ID_EXTRA, -1)
            //Change the type according to the live streaming extension.
            .putExtra(VideoPlayerActivity.CONTENT_TYPE_EXTRA, DemoUtil.TYPE_HLS);
    liveStreamingTv =(TextView)findViewById(R.id.mainActivity_liveStreamingTv);
    liveStreamingTv.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            startActivity(intent);
        }
    });
}


回答5:

There are no tutorials on ExoPlayer right now. ExoPlayer is a the best alternative to MediaPlayer but is not very newbie friendly at the moment.

What you have to do is go to the github page and take a look at the DemoPlayer class in the demo app.

This app can open a lot of different formats including hls.