Delay in start of play music in SimpleExoPlayer android - android

I am building Music App in which I have uploaded music on firebase. I am using SimpleExoPlayer and PlayerView to run the music. The problem is when I click on the music, the music start after 10 seconds or more. I search it but did not find any solution
ExoPLayer library:
implementation "com.google.android.exoplayer:exoplayer:2.14.1"
public void initPlayer(MusicModel dataModel) {
if (playerLayout.getVisibility() == View.GONE && !isFullScreenOn) {
playerLayout.setVisibility(View.VISIBLE);
}
assignPlayerLayout(dataModel);
assignFullScreenPlayerLayout(dataModel);
try {
playerView.setControllerShowTimeoutMs(0);
playerView.setCameraDistance(10);
playerView.setShowFastForwardButton(false);
playerView.setShowRewindButton(false);
playerView.setShowNextButton(false);
playerView.setShowPreviousButton(false);
playerView.setShutterBackgroundColor(R.color.white);
simpleExoPlayer = new SimpleExoPlayer.Builder(MainActivity.this).build();
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MOVIE)
.build();
simpleExoPlayer.setAudioAttributes(audioAttributes, true);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(MainActivity.this,
Util.getUserAgent(MainActivity.this, getResources().getString(R.string.app_name)));
MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(getString(dataModel.getAudioFile())));
playerView.setPlayer(simpleExoPlayer);
simpleExoPlayer.seekTo(0);
// Tell it to play the sound
simpleExoPlayer.prepare(mediaSource);
simpleExoPlayer.setPlayWhenReady(true);
isPlaying = true;
}catch (Exception e){
Log.e("except",e.toString());
}
}
Please give me a solution
Blockquote
, I shall be very thankful to you.

Related

Exoplayer can't play only audio for HLS

I have link only audio https://storage.googleapis.com/as-piepme/1465/livestream/1465.fef238cdc9d9eb0b958d4eb23080e28b/index.m3u8 but Exoplayer can't play above link,
it return "source error". But both IOS and Chrome run fine. My code:
SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build();
player.setMediaItem(MediaItem.fromUri(Uri.parse(linkPlay)));
player.prepare();
player.setPlayWhenReady(true);
Update my solution:
MediaItem mediaItem = new MediaItem.Builder()
.setUri(Uri.parse("https://storage.googleapis.com/as-piepme/1465/livestream/1465.fef238cdc9d9eb0b958d4eb23080e28b/index.m3u8"))
.build();
DefaultHlsExtractorFactory defaultHlsExtractorFactory = new DefaultHlsExtractorFactory(DefaultTsPayloadReaderFactory.FLAG_IGNORE_H264_STREAM, false);
MediaSource mediaSource = new HlsMediaSource.Factory(new DefaultHlsDataSourceFactory(new DefaultDataSourceFactory(context)))
.setExtractorFactory(defaultHlsExtractorFactory)
.setAllowChunklessPreparation(true)
.createMediaSource(mediaItem);
player.setMediaSource(mediaSource);
You need to use a Media source.
Try this sample code.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory();
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(hlsUri));
// Create a player instance.
SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build();
// Set the media source to be played.
player.setMediaSource(hlsMediaSource);
// Prepare the player.
player.prepare();
For more details check the documentation.
Update
Use this one.
DefaultTrackSelector trackSelector = new DefaultTrackSelector(this, new AdaptiveTrackSelection.Factory());
DefaultTrackSelector.Parameters trackSelectorParameters = trackSelector.buildUponParameters().setMaxAudioChannelCount(0).build();
trackSelector.setParameters(trackSelectorParameters);
RenderersFactory renderersFactory = new DefaultRenderersFactory(this);
SimpleExoPlayer audioPlayer = = new SimpleExoPlayer.Builder(this, renderersFactory).setTrackSelector(trackSelector).build();
HttpDataSource.Factory factory = new DefaultHttpDataSourceFactory("Online Audio Player", DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true);
audioPlayer.setMediaSource(new ProgressiveMediaSource.Factory(factory).createMediaSource(MediaItem.fromUri("https://storage.googleapis.com/as-piepme/1465/livestream/1465.fef238cdc9d9eb0b958d4eb23080e28b/index.m3u8")));
audioPlayer.prepare();
audioPlayer.setPlayWhenReady(true);

How to re-add a mediasource after the exoplayer has been prepared?

I'm creating a playlist video player in exoplayer in android studio. I'm adding the first video extracted from a server and it is being played by the exoplayer perfectly. But when I add the second part, the exoplayer does not play that video. I want to add the second video after the exoplayer has been prepared. I want to know how to do that. Please Help me.
My MainActivity.java:
public class MainActivity extends AppCompatActivity
{
SimpleExoPlayer video_player;
PlayerView player_screen;
DefaultTrackSelector track_selector;
DefaultBandwidthMeter band_width_meter = new DefaultBandwidthMeter();
ArrayList<MediaSource> mediaSources_contents = new ArrayList<>();
ConcatenatingMediaSource concatenating_mediaSource_contents;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
player_screen = (PlayerView) findViewById(R.id.player_screen);
player_screen.requestFocus();
TrackSelection.Factory video_track_selection_factory = new AdaptiveTrackSelection.Factory(band_width_meter);
track_selector = new DefaultTrackSelector(video_track_selection_factory);
video_player = ExoPlayerFactory.newSimpleInstance(this, track_selector);
player_screen.setPlayer(video_player);
video_player.setPlayWhenReady(true);
Uri url1 = Uri.parse("THE - URL - OF - FIRST - VIDEO");
DataSource.Factory data_source_factory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "Application Name"), band_width_meter);
MediaSource source1 = new ExtractorMediaSource.Factory(data_source_factory).createMediaSource(url1);
mediaSources_contents.add(source1);
concatenating_mediaSource_contents = new ConcatenatingMediaSource(mediaSources_contents.toArray(new MediaSource[mediaSources_contents.size()]));
video_player.prepare(concatenating_mediaSource_contents);
// The lines below this point adds the second video to the media source. But it is not being played by the exoplayer.
Uri url2 = Uri.parse("THE - URL - OF - SECOND - VIDEO");
MediaSource source2 = new ExtractorMediaSource.Factory(data_source_factory).createMediaSource(url2);
mediaSources_contents.add(source2);
}
}
At Prepared Time
Initialize ConcatenatingMediaSource
ConcatenatingMediaSource mediaSource = new ConcatenatingMediaSource();
MediaSource firstSource = new ProgressiveMediaSource.Factory(new FileDataSourceFactory()).createMediaSource(Uri.parse(uri.get(0)));
MediaSource secondSource= new ProgressiveMediaSource.Factory(new FileDataSourceFactory()).createMediaSource(Uri.parse(uri.get(1)));
mediaSource.addMediaSources(firstSource);
mediaSource.addMediaSources(secondSource);
player.prepare(mediaSource, true, false);
After Prepare Add mediasource
MediaSource thirdSource= new ProgressiveMediaSource.Factory(new FileDataSourceFactory()).createMediaSource(Uri.parse(uri.get(3)));
mediaSource.addMediaSources(thirdSource);// mediaSource is refrance of ConcatenatingMediaSource
Try add this concatenating_mediaSource_contents.addMediaSource(source2); instead mediaSources_contents.add(source2);and for first media source also (not necessary, for better readability)

Exoplayer unable to play DASH video android

I'm trying to play DASH video with the help of Uri obtained from exoplayer demo app https://github.com/google/ExoPlayer/blob/release-v2/demos/main/src/main/assets/media.exolist.json
When I change my network from WIFI to mobile data , video quality doesn't change instead it starts buffering.
My code
private void initializePlayer() {
if (player == null) {
player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
new DefaultTrackSelector(), new DefaultLoadControl());
exoPlayerView.setPlayer(player);
player.setPlayWhenReady(playWhenReady);
player.seekTo(currentWindow, playbackPosition);
}
Uri uri = Uri.parse("http://www.youtube.com/api/manifest/dash/id/3aa39fa2cc27967f/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=A2716F75795F5D2AF0E88962FFCD10DB79384F29.84308FF04844498CE6FBCE4731507882B8307798&key=ik0");
MediaSource mediaSource = buildMediaSource(uri);
player.prepare(mediaSource, true, false);
player.addListener(new PlayerEventListener());
player.setRepeatMode(Player.REPEAT_MODE_ALL);
//exoPlayerView.setUseController(false);
}
private MediaSource buildMediaSource(Uri uri) {
DataSource.Factory manifestDataSourceFactory = new DefaultHttpDataSourceFactory("ua");
DashChunkSource.Factory dashChunkSourceFactory = new DefaultDashChunkSource.Factory(new DefaultHttpDataSourceFactory("ua", BANDWIDTH_METER));
return new DashMediaSource.Factory(dashChunkSourceFactory, manifestDataSourceFactory).createMediaSource(uri);
}
gradle
compile 'com.google.android.exoplayer:exoplayer-core:2.7.0'
compile 'com.google.android.exoplayer:exoplayer-dash:2.7.0'
compile 'com.google.android.exoplayer:exoplayer-ui:2.7.0'
Is there Anything I missed ?
It was a silly mistake
instead of new DefaultTrackSelector()
I used
TrackSelection.Factory adaptiveTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
new DefaultTrackSelector(adaptiveTrackSelectionFactory)

Leaking activity context when implementing exoplayer in a separate class

I use the exoplayer 3 times in my application so I thought it would be better to implement it in its own class and just use it 3 times.
In doing this I introduced a memory leak so it is leaking the activity and causing the app to crash.
I am not really sure why this would be happening because I haven't closed the activity. I guess it is because there is some change in the activity or the view.
If you could tell me what is wrong with my implementation to cause a memory leak it would be greatly appreciated.
This is my exoplayer control class:
public class ExoPlayerControls {
Context context;
SimpleExoPlayerView simpleExoplayerView;
SimpleExoPlayer player;
boolean preview;
public ExoPlayerControls(Context context, SimpleExoPlayerView simpleExoplayerView, SimpleExoPlayer player, Boolean preview) {
this.context = context;
this.simpleExoplayerView = simpleExoplayerView;
this.player = player;
this.preview = preview;
}
public boolean setUPExoPlayer (String alarmMediaLocation){
try {
if (player != null){
player.setPlayWhenReady(false);
//URI location of audio
Uri mediaURI = Uri.parse(alarmMediaLocation);
// Data source Factory
DefaultHttpDataSourceFactory datasourceFactory = new DefaultHttpDataSourceFactory("alarm video");
// Extractor Factory
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// Media source
MediaSource mediasource = new ExtractorMediaSource(mediaURI, datasourceFactory, extractorsFactory, null, null);
// Prepare the exoplayer
player.prepare(mediasource);
player.setPlayWhenReady(false);
} else {
// Create a bandwith meter
BandwidthMeter bandwidthmeter = new DefaultBandwidthMeter();
// Create a track selector
TrackSelector trackselector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory(bandwidthmeter));
// Create the player
player = ExoPlayerFactory.newSimpleInstance(context, trackselector);
//URI location of audio
Uri mediaURI = Uri.parse(alarmMediaLocation);
// Data source Factory
DefaultHttpDataSourceFactory datasourceFactory = new DefaultHttpDataSourceFactory("alarm video");
// Extractor Factory
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// Media source
MediaSource mediasource = new ExtractorMediaSource(mediaURI, datasourceFactory, extractorsFactory, null, null);
// Bind the player to the view.
simpleExoplayerView.setPlayer(player);
// Prepare the exoplayer
player.prepare(mediasource);
player.setPlayWhenReady(false);
}
} catch (Error e){
Toast.makeText(context, "Exoplayer error" + e, Toast.LENGTH_SHORT).show();
}
return true;
}
public void playAlarmMedia(String alarmMediaLocation){
try {
boolean exoPlayerSet = setUPExoPlayer(alarmMediaLocation);
if (exoPlayerSet){
// Tell exoplayer to start playing immediately
player.setPlayWhenReady(true);
}
} catch (Error e){
Toast.makeText(context, "Exoplayer error" + e, Toast.LENGTH_SHORT).show();
}
}
}
And I implement it in my activity like this:
// Initialise exoplayer controls
exoPlayerControls = new ExoPlayerControls(this, simpleExoplayerView, player, preview);
String alarmMediaLocation = downloadedAlarmToPlay.getAlarmMediaLocation();
exoPlayerControls.setUPExoPlayer(alarmMediaLocation);
The exoplayer class has three nested static classes/interfaces ExoplayerComponent, Factory and Listener. In general any Static objects will hold reference to an activity. Could the memory leak be caused by orientation changes? Because the activity will be unable to destroy itself. So older instances of the activity will be retained in memory causing a memory leak. A way to get over this is to use getAppplicationContext() instead of the Activity context (this). The application context is a singleton object. So every time Activity gets created due to screen rotation, no new instances of context are being created.

How to get local video Uri for ExoPlayer 2.x

I have a dog.mp4 video file in res/raw folder, which I want to play with ExoPlayer. I'm trying to figure out how to get video Uri for this line of code from ExoPlayer developers guide (https://google.github.io/ExoPlayer/guide.html):
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
dataSourceFactory, extractorsFactory, null, null);
To get it, I use this line:
Uri mp4VideoUri = Uri.parse("android.resources://"+getPackageName()+"/"+R.raw.dog);
Also tried this syntax: android.resource://[package]/[res type]/[res name]
But SimpleExoPlayerView stays black and I get following error:
com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to android.resources://lt.wilkas.deleteexoplayer/2131099648
What am I doing wrong?
Don't move your videos from raw to any another folder
Use this code to play video:
PlayerView playerView = findViewById(R.id.player_view);
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(this);
// Bind the player to the view.
playerView.setPlayer(player);
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "yourApplicationName"));
// This is the MediaSource representing the media to be played.
MediaSource firstSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(RawResourceDataSource.buildRawResourceUri(R.raw.dog));
// Prepare the player with the source.
player.prepare(firstSource);
According to ExoPlayer 2.12 its even easier to use MediaItem.
To create it we need Uri that could be generated from RawResourceDataSource.buildRawResourceUri.
And that's it. Just set this MediaItem do prepare() and play when ready:
SimpleExoPlayer.Builder(view.context).build().apply {
val uri = RawResourceDataSource.buildRawResourceUri(R.raw.video)
setMediaItem(MediaItem.fromUri(uri))
prepare()
playWhenReady = true
}
I've found out that res/raw folder cant be used to store local videos for ExoPlayer. They should be placed in assets folder.
res/raw folder can be used to access local video file for ExoPlayer via it's URI. Here's the solution that will not give the Malformed URL exception and it works for me. You have to use RawResourceDataSource.buildRawResourceUri(R.raw.video) method of the RawResourceDataSource class. Keep in mind that i used the 2.8.0 version of ExoPlayer.
public class MainActivity extends AppCompatActivity {
PlayerView playerView;
SimpleExoPlayer simpleExoPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playerView=findViewById(R.id.playerView);
}
#Override
protected void onStart() {
simpleExoPlayer= ExoPlayerFactory.newSimpleInstance(this,new DefaultTrackSelector());
DefaultDataSourceFactory defaultDataSourceFactory=new DefaultDataSourceFactory(this, Util.getUserAgent(this,"yourApplicationName"));
simpleExoPlayer.setPlayWhenReady(true);
ExtractorMediaSource extractorMediaSource=new ExtractorMediaSource.Factory(defaultDataSourceFactory).createMediaSource(RawResourceDataSource.buildRawResourceUri(R.raw.video));
simpleExoPlayer.prepare(extractorMediaSource);
playerView.setPlayer(simpleExoPlayer);
super.onStart();
}
#Override
protected void onStop() {
playerView.setPlayer(null);
simpleExoPlayer.release();
simpleExoPlayer=null;
super.onStop();
}
}
here is the sample to load video/audio file from res/raw with ExoPlayer :
val player = ExoPlayerFactory.newSimpleInstance(context,DefaultTrackSelector())
val rawDataSource = RawResourceDataSource(context)
rawDataSource.open(DataSpec(RawResourceDataSource.buildRawResourceUri(R.raw.brown)))
val mediaSource = ExtractorMediaSource.Factory(DataSource.Factory { rawDataSource })
.createMediaSource(rawDataSource.uri)
player.playWhenReady = true
player.prepare(mediaSource)
sample copied from
This code works for me.
fun buildMediaSourceRaw() : MediaSource{
val dataSourceFactory = DefaultDataSourceFactory(context, "exoPlayer")
val uri = RawResourceDataSource.buildRawResourceUri(R.raw.my_video)
return ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri)
}
Then
player?.prepare(buildMediaSourceRaw())

Categories

Resources