ExoPlayer - play 10 files one after another - android

I have 10 video i need to play, once one is done, the next one starts to play.
I'm using Google's ExoPlayer, I use the example in the DEMO # GitHub.
I can play 1 video but if i try to play the next one, it wont start.
If i try to reInit the player, and the start playing again, it crashes.
private void loadvideo() {
Uri uri = Uri.parse(VIDEO_LIBRARY_URL + currentVideo + ".mp4");
sampleSource = new FrameworkSampleSource(this, uri, null, 2);
// 1. Instantiate the player.
// 2. Construct renderers.
videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
// 3. Inject the renderers through prepare.
player.prepare(videoRenderer, audioRenderer);
// 4. Pass the surface to the video renderer.
surface = surfaceView.getHolder().getSurface();
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
// 5. Start playback.
player.setPlayWhenReady(true);
player.addListener(new ExoPlayer.Listener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.d(TAG, "onPlayerStateChanged + " + playbackState);
if (playbackState == ExoPlayer.STATE_ENDED) {
currentVideo++;
loadNextVideo();
}
}
#Override
public void onPlayWhenReadyCommitted() {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
});
}
What am i doing wrong?
How can i play videos continuity?
Thanks.

You can reuse the ExoPlayer up until the point that you call release(), and then it should no longer be used.
To change the media that it is currently playing, you essentially need to perform the following steps:
// ...enable autoplay...
player.stop();
player.seekTo(0L);
player.prepare(renderers);
Creating the renderers is a little bit more involved, but that's the flow you should follow and the player should be able to play back to back videos.

I'm using Exoplayer change mp4 video success. I use the example in the DEMO.
1.DEMO project in DemoPlayer.java:
private final RendererBuilder rendererBuilder;
//remove final,then modify that:
private RendererBuilder rendererBuilder;
//and add the set method:
public void setRendererBuilder(RendererBuilder rendererBuilder){
this.rendererBuilder = rendererBuilder;
}
//finally,add stop method
public void stop(){
player.stop();
}
2.DEMO project in PlayerActivity.java:
add method:
private void changeVideo(){
player.stop();
player.seekTo(0L);
//you must change your contentUri before invoke getRendererBuilder();
player.setRendererBuilder(getRendererBuilder());
player.prepare();
playerNeedsPrepare = false;
}
remember change param contentUri before invoke changeVideo method.

Use ConcatenatingMediaSource to play files in sequence.
For example, for playing 2 media Uris (firstVideoUri and secondVideoUri), use this code:
MediaSource firstSource =
new ExtractorMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource =
new ExtractorMediaSource.Factory(...).createMediaSource(secondVideoUri);
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(firstSourceTwice, secondSource);
And then use concatenatedSource to play media files sequentially.

OK, Answering my own question.
on the example, google init the ExoPlayer at OnResume().
i had to re-init for every video like that:
player = ExoPlayer.Factory.newInstance(2, 1000, 5000);
if someone has a better idea, please let me know.

There is another solution, you could refer to ConcatenatingMediaSource to achieve auto play next media.
In Demo App example :
1. Launch ExoPlayer
2. Select Playlists
3. Choose Cats->Dogs

Related

Exoplayer2 hls - choose quality [duplicate]

I am currently developing a live and movie player application. I chose ExoPlayer version 2 to play the movie and I do not know much about it. I want to let the user choose the quality of a movie on the player screen, for example, 720p or 1080p or etc.
But I do not know how to get a list of existing qualities and show them to the user.
and the below code is my implementation of SimpleExoPlayer :
private void initPlayer(String path){
Handler handler = new Handler();
// 1. Create a default TrackSelector
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
SimpleExoPlayerView playerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
playerView.setPlayer(player);
playerView.setKeepScreenOn(true);
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new HlsMediaSource(Uri.parse(path),
dataSourceFactory,handler, null);
// Prepare the player with the source.
player.addListener(this);
player.prepare(videoSource);
playerView.requestFocus();
player.setPlayWhenReady(true); // to play video when ready. Use false to pause a video
}
// ExoPlayer Listener Methods :
#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 onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case ExoPlayer.STATE_BUFFERING:
//You can use progress dialog to show user that video is preparing or buffering so please wait
progressBar.setVisibility(View.VISIBLE);
break;
case ExoPlayer.STATE_IDLE:
//idle state
break;
case ExoPlayer.STATE_READY:
// dismiss your dialog here because our video is ready to play now
progressBar.setVisibility(GONE);
//Toast.makeText(getApplicationContext(),String.valueOf(player.getCurrentTrackSelections().get(0).getSelectedFormat().bitrate),Toast.LENGTH_SHORT).show();
break;
case ExoPlayer.STATE_ENDED:
// do your processing after ending of video
break;
}
}
#Override
public void onPlayerError(ExoPlaybackException error) {
// show user that something went wrong. it can be a dialog
}
#Override
public void onPositionDiscontinuity() {
}
please help to solve this issue.
thanks a lot.
Everything you'd like to achieve is viewable in the ExoPlayer2 demo app. More specifically the PlayerActivity class.
You can also check out this good article on the topic.
The core points you'll want to look into are around track selection (via the TrackSelector) as well as the TrackSelectionHelper. I'll include the important code samples below which will hopefully be enough to get you going. But ultimately just following something similar in the demo app will get you where you need to be.
You'll hold onto the track selector you init the player with and use that for just about everything.
Below is just a block of code to ideally cover the gist of what you're trying to do since the demo does appear to over-complicate things a hair. Also I haven't run the code, but it's close enough.
// These two could be fields OR passed around
int videoRendererIndex;
TrackGroupArray trackGroups;
// This is the body of the logic for see if there are even video tracks
// It also does some field setting
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
for (int i = 0; i < mappedTrackInfo.length; i++) {
TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i);
if (trackGroups.length != 0) {
switch (player.getRendererType(i)) {
case C.TRACK_TYPE_VIDEO:
videoRendererIndex = i;
return true;
}
}
}
// This next part is actually about getting the list. It doesn't include
// some additional logic they put in for adaptive tracks (DASH/HLS/SS),
// but you can look at the sample for that (TrackSelectionHelper#buildView())
// Below you'd be building up items in a list. This just does
// views directly, but you could just have a list of track names (with indexes)
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
TrackGroup group = trackGroups.get(groupIndex);
for (int trackIndex = 0; trackIndex < group.length; trackIndex++) {
if (trackIndex == 0) {
// Beginning of a new set, the demo app adds a divider
}
CheckedTextView trackView = ...; // The TextView to show in the list
// The below points to a util which extracts the quality from the TrackGroup
trackView.setText(DemoUtil.buildTrackName(group.getFormat(trackIndex)));
}
// Assuming you tagged the view with the groupIndex and trackIndex, you
// can build your override with that info.
Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag();
int groupIndex = tag.first;
int trackIndex = tag.second;
// This is the override you'd use for something that isn't adaptive.
override = new SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex);
// Otherwise they call their helper for adaptives, which roughly does:
int[] tracks = getTracksAdding(override, trackIndex);
TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY : adaptiveTrackSelectionFactory;
override = new SelectionOverride(factory, groupIndex, tracks);
// Then we actually set our override on the selector to switch the quality/track
selector.setSelectionOverride(rendererIndex, trackGroups, override);
As I mentioned above, this is a slight oversimplification of the process, but the core part is that you're messing around with the TrackSelector, SelectionOverride, and Track/TrackGroups to get this to work.
You could conceivably copy the demo code verbatim and it should work, but I'd highly recommend taking the time to understand what each piece is doing and tailor your solution to your use case.
If I had more time I'd get it to compile and run. But if you can get my sample going then feel free to edit my post.
Hope that helps :)
I avoid the way as above posted. My way is using the DefaultTrackSelector as follows:
trackSelector.setParameters(trackSelector.getParameters()
.withMaxVideoBitrate(bitrate)
.withMaxVideoSize(width, height));
I've tested with HLS videos and it seems to perform in the right way. I get the bitrate, width and height reading from the HlsManifest.
You can copy the sample codes form this link.
ExoPlayer Video Quality Control.
Note : Do not forget to add the exoplayer dependencies in the built.gradle file
implementation 'com.google.android.exoplayer:exoplayer-core:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'

Android Media Player Streaming not working

I have created one streaming audio application which is working on some Android devices but except moto g (6.0.1)API.
Exception: IOException OR MEDIA_ERROR_SYSTEM "error : (1, -2147483648)"
Code:
URL url = new URL("streaming extracted url");
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
String urlStr = uri.toASCIIString();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(urlStr);
player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
}
});
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.reset();
}
});
player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
});
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
Can anyone please help me whats going wrong in this? Do I missing something?
I have had a similar and inexplicable issue. I am using a simple MediaPlayer to stream audio from a site. This works perfectly on a Samsung Galaxy S4 (Android 5.0.1), but on Pixel (Android 8.1.0) the audio won't play.
I am loading the URL on a play button click, showing a progress spinner until the MediaPlayer onPrepared listener is triggered. When prepared, I'm hiding the progress bar, and starting playback.
On Pixel, the normal loading / streaming time elapses (so I guess the file is being prepared!) onPrepared is triggered, no errors are shown, but the audio is never played!
Our server uses a self signed certificate which I thought might have been the issue, but even accessing the file over http it won't play on Pixel. I have also confirmed it's not a codec issue, as moving the file to Google Drive and playing with a direct link in my app the file plays back fine.
I am not sure if it's a server based issue, but all other files (images etc) are served and display fine (using Glide), and the file is served and can be viewed in Chrome via the same URL fed into the MediaPlayer!
I have just now moved to ExoPlayer, and it's playing fine on both devices .. so I guess this is the way forward!
Add dependency
compile 'com.google.android.exoplayer:exoplayer-core:2.6.1'
When play button is clicked, I'm loading Audio if not already loaded, otherwise starting playback
if (player == null) {
loadAudio();
} else {
player.setPlayWhenReady(true);
}
And my loadAudio()
private void loadAudio() {
String userAgent = Util.getUserAgent(getActivity(), "SimpleExoPlayer");
Uri uri = Uri.parse(audioUrl);
DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
true);
// This is the MediaSource representing the media to be played.
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
TrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector);
player.addListener(this);
player.prepare(mediaSource);
player.setPlayWhenReady(true);
}
... and the ExoPlayer listeners for state, so I can swap play / pause buttons in UI on completion etc
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_BUFFERING:
audioProgress.setVisibility(View.VISIBLE);
break;
case Player.STATE_ENDED:
handler.removeCallbacks(UpdateAudioTime);
buttonControllerPlay.setVisibility(View.VISIBLE);
buttonControllerPause.setVisibility(View.GONE);
seekBar.setProgress(0);
break;
case Player.STATE_IDLE:
break;
case Player.STATE_READY:
audioProgress.setVisibility(View.GONE);
finalTime = player.getDuration();
startTime = player.getCurrentPosition();
seekBar.setMax((int) finalTime);
seekBar.setProgress((int) startTime);
handler.postDelayed(UpdateAudioTime, 100);
break;
default:
break;
}
}
Remember to release the player on stop / destroy
Hopefully can help someone out there who is scratching their head as much as I was!
I've used the following code to stream audio on a Moto G5 (Android 7.0) and it is working fine:
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
mediaPlayer.setAudioAttributes(audioAttributes)
This might explain the issue:
Application developers should use audio attributes when creating or
updating applications for Android 5.0. However, applications are not
required to take advantage of attributes; they can handle legacy
stream types only or remain unaware of attributes (i.e. a generic
media player that doesn't know anything about the content it's
playing).
In such cases, the framework maintains backwards compatibility with
older devices and Android releases by automatically translating legacy
audio stream types to audio attributes. However, the framework does
not enforce or guarantee this mapping across devices, manufacturers,
or Android releases.
Source: https://source.android.com/devices/audio/attributes

How to play video one by one in TextureView in android?

I want to play the video one by one from my sdcard using Texture view in android. I am using tetureview bcoz , I want to rotate the video at 90 degree.. so I can play the rotated video on device by implementing SurfaceTextureListener interface.
This is the code:
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
root = Environment.getExternalStorageDirectory();
ArrayList extList = new ArrayList<String>();
extList.add("mp4");
extList.add("3gp");
extList.add("ts");
extList.add("webm");
extList.add("mkv");
Intent intent = getIntent();
Bundle b = intent.getExtras();
vFiles = b.getStringArrayList("vFiles");
System.out.println("VFiles: " + vFiles);
iterator = vFiles.iterator();
videoPath = root + "/Video/";
if (iterator.hasNext()) {
System.out.println("Inside iterator: .......................................");
String video = videoPath + iterator.next();
mMediaPlayer = new MediaPlayer();
//mMediaPlayer.setDataSource(afd.getFileDescriptor(),
// afd.getStartOffset(), afd.getLength());
mMediaPlayer.setDataSource(video);
System.out.println("After Datasource: " + video);
mMediaPlayer.setSurface(sur);
// mMediaPlayer.setLooping(true);
mMediaPlayer.prepareAsync();
// mMediaPlayer.setOnBufferingUpdateListener((OnBufferingUpdateListener) this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnCompletionListener(this);
// Play video when the media source is ready for playback.
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
// mediaPlayer.setLooping(true);
mediaPlayer.start();
}
});
}
}
But By this code, Only one video is playing , after another video is not playing.. and I want when one video is finished then second video in the list should be play and so on..
I searched a lot about this on net... But no luck...
Can any one help me regarding this ?
onSurfaceTextureAvailable method doesn't get triggered when the MediaPlayer object has completed playback, it gets triggered when the Surface texture is ready to be used.
You need to implement MediaPlayer.OnCompletionListener, the onCompletion method gets triggered once the playback is completed.
Start the playback of the next video in the list once the playback of the first video is completed.

multiple videos play one after the another

can anyone teach me how to make videos play one after the other
I need the full code
I have 4 videos
Video1, Video2, Video3, Video4
I want Video1 to play first then followed Video2, then followed by Video3, then followed by Video4
String path="android.resource://" + getPackageName() +"/" + R.raw.Video1;
videoView1.setVideoURI(Uri.parse(path));
videoView1.start();
Short & Simple
Let's say you have four videos in array list
ArrayList<String> urlList = new ArrayList<>();
Create one counter variable to manage current video playing.
int video_counter = 0;
Now following code make your work easy to play dynamic range of video to play in loop (like one after another).
VideoView vv_video = findViewById(R.id.vv_video);
vv_video.setVideoURI(Uri.parse(urlList.get(counter_video_loop)));
vv_video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
vv_video.start();
}
});
vv_video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if ((video_counter + 1) <= urlList.size()) {
video_counter++;
vv_video.setVideoURI(Uri.parse(urlList.get(video_counter + 1)));
vv_video.start();
}
}
});
Assume you have a Videoview, you could for example put the paths to the videos into an array, and detect the end of playback like this:
videoView.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//start next video here
//for example, set video path to next array item
}
});
Maybe you should create a new VideoView to play next video at OnCompletionListener, and remove the old VideoView ,add the new VideoView.
It works for me.
use exoPlayer for concatenate multi video

Seamless video Loop with VideoView

I have the following code to take a video as a raw resource, start the video and loop it but I need the video to loop seamlessly as of now when it comes to an end of the clip and starts the clip again the transition between causes a flicker for a split second, which I really can't have for my app.
public class Example extends Activity {
VideoView vv;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
vv = (VideoView)findViewById(R.id.VideoView01);
//Video Loop
vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
vv.start(); //need to make transition seamless.
}
});
Uri uri = Uri.parse("android.resource://com.example/"
+ R.raw.video);
vv.setVideoURI(uri);
vv.requestFocus();
vv.start();
}
}
The clip is only 22 seconds long but was created to be seamless so it is possible to work without the delay.
Try this it will work 100%
VideoView videoView;<---write this in outside of method or else declare it as final variable.
videoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setLooping(true);
}
});
In Kotlin simply use
videoView.setOnPreparedListener { it.isLooping = true }
Not sure if this helps years later, but I used
vv.start();
vv.setOnCompletionListener ( new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
vv.start();
}
});
and it has a seamless loop
The pause is for the underlying MediaPlayer to refresh its buffers. How long that will take will depend on a number of factors, many of which are outside your control (e.g., speed of CPU, speed of on-board flash storage).
One you can control is to get your video out of the resource and into the filesystem. Resources are stored in the APK, which is a ZIP file, so extracting the video this way probably takes extra time.
You may need to switch away from VideoView and use a SurfaceView with two MediaPlayers, alternating between them -- one is playing while the next is preparing, so when the playing one ends you can switch to the new player. I have not tried this, and so I do not know what the ramifications might be. However, I know that this technique is frequently used for audio playback to transition from one clip to another.
Little late, but any reason that you can't use the following?
MediaPlayer.setLooping(true);
If you are using Kotlin
videoView.setOnPreparedListener(object : MediaPlayer.OnPreparedListener {
override fun onPrepared(mp: MediaPlayer?) {
//Start Playback
videoView.start()
//Loop Video
mp!!.isLooping = true;
Log.i(TAG, "Video Started");
}
});
Using Arrow Expression short form
videoView.setOnPreparedListener { mp ->
//Start Playback
videoView.start()
//Loop Video
mp!!.isLooping = true;
Log.i(TAG, "Video Started");
};
Answer to this is to remove the audio from the video and convert that to a .ogg file which can be looped seamlessly and then use the video without audio to loop round and this works.
Here is answer friends, you must use vv.resume in setOnCompletionListener class
[https://stackoverflow.com/a/27606389/3414469][1]

Categories

Resources