ExoPlayer - play two audio tracks simultaneously - android

Using ExoPlayer i'm trying to play two audio tracks simultaneously.
My idea was to create two MediaSource, and to "combine" between them using MergingMediaSource.
This is what I have done:
Uri uriAudio1 = Uri.parse(AUDIO_URL_1);
Uri uriAudio2 = Uri.parse(AUDIO_URL_2);
MediaSource audioSource1 = new ExtractorMediaSource(uriAudio1, dataSourceFactory, extractorsFactory, mainHandler, null);
MediaSource audioSource2 = new ExtractorMediaSource(uriAudio2, dataSourceFactory, extractorsFactory, mainHandler, null);
MergingMediaSource mergedAudioSource = new MergingMediaSource(audioSource1, audioSource2);
mPlayer.prepare(mergedAudioSource);
How ever instead of hearing both audio tracks in parallel, i hear only the first audioSource1.
Any ideas? Thanks!

Try to set channel count like this
val trackSelector = DefaultTrackSelector()
trackSelector.setParameters(
trackSelector.buildUponParameters()
.setMaxVideoSizeSd()
.setMaxAudioChannelCount(2)
)

It seems that this functionality isn't currently supported, according to issue #2200.

I ran into the same problem, solved it by using two different instances of Exoplayer, one for each audio asset, and playing them at the same time.

You can use ConcatenatingMediaSource :
List<MediaSource> mediaSources = new ArrayList<>();
for (Track track : tracks) {
MediaSource mediaSource = ...//use your uri media source from tack.getPath
mediaSources.add(mediaSource);
}
mediaPlayer.prepare(new ConcatenatingMediaSource(mediaSources.toArray(new MediaSource[mediaSources.size()])));

Related

Exoplayer keeps playing the audio even when video is stopped after

I am using exoplayer and I noticed when I play a video in one activity and then switch to another by pressing on a button the video itself stops playing in order to switch to the new activity, but the audio keeps playing. If I return to the old activity and play the video again the audio is still going + I hear the audio from playing the video again and hear the audio two times now simulteanously at different times of the song.
String url = model.getVideo();
try {
BandwidthMeter bandwidthMeter= new DefaultBandwidthMeter();
TrackSelector trackSelector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory( bandwidthMeter));
holder.exoPlayer= ExoPlayerFactory.newSimpleInstance( LiFit.getContext(),trackSelector );
Uri videouri = Uri.parse(model.getVideo());
DefaultHttpDataSourceFactory dataSourceFactory = new DefaultHttpDataSourceFactory("exoplayer_video");
ExtractorsFactory extractorsFactory= new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videouri,dataSourceFactory,extractorsFactory,null,null);
holder.videoView.setPlayer(holder.exoPlayer);
holder.exoPlayer.prepare(mediaSource);
//holder.exoPlayer.setPlayWhenReady(true);
} catch (Exception e) {
//Nichts
}
This is the code I am using does somebody know a solution for this problem ?
exoplayer has a method setPlayWhenReady which can be used to play/pause the media, and a release method when the player is no longer needed.
You can use these methods when switching to another activity.

Adding multiple Audio Hlsmedia source using Dynamicmediasource In Exoplayer without pause currently playing Player.

I want to make Dynamic Audio Playlist using Exoplayer.I used DynamicMediaSource as well as ConcateMediaSource it will work fine but if my player is currently playing and i will try to add mediasource then current player can be go on pause state and newly added mediasource will be playing.Initially i will create media source for only one audio and make player.playWhenReady true for only first time.then add another source in list and create audio source for my playlist.
So is it possible to add mediasouce without pause player? And playlist can be play in added manner?
below code is for create media souce for first audio:-
fun createAudioSource(data: MusicDetailResponse.AudioX, audioAllItem: MusicDetailResponse.Audio, position: Int) {
player = ExoPlayerFactory.newSimpleInstance(context, DefaultTrackSelector())
val userAgent = Util.getUserAgent(context, context.getString(R.string.label_user_agent))
val dataSourceFactory = DefaultHttpDataSourceFactory(
userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
1800000,
true)
val hlsMediaSource = HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(data.audio))
player!!.prepare(hlsMediaSource)
player!!.playWhenReady = true
}
fun addAudioList(item: MusicDetailResponse.AudioX) {
tempAudioList.add(item)
createHlsMediaSource(tempAudioList)
}
private fun createHlsMediaSource(tempAudioList: ArrayList<MusicDetailResponse.AudioX>) {
for (i in 1 until tempAudioList.size) {
val userAgent = Util.getUserAgent(context, context.getString(R.string.label_user_agent))
val dataSourceFactory = DefaultHttpDataSourceFactory(
userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
1800000,
true)
val hlsMediaSource = HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(tempAudioList[i].audio))
cMediaSource!!.addMediaSource(hlsMediaSource)
}
player?.prepare(cMediaSource, false, false)
}
Renamed all occurrences of DynamicConcatenatingMediaSource to ConcatenatingMediaSource.
Ever wanted to support media playlists in your Android app, where users can add and remove playlist items arbitrarily during playback? Now you can!
From ExoPlayer 2.8.0 onward we’ve updated the ConcatenatingMediaSource with dynamic playlist functionality. On the surface the new media source has a very simple and straightforward interface:
addMediaSource(mediaSource) appends a new media source at the end of the playlist.
addMediaSource(index, mediaSource) inserts a new media source at the specified index in the playlist.
addMediaSources(Collection) bulk appends a whole set of new media sources at the end of the playlist.
addMediaSources(index, Collection) bulk inserts a set of new media sources at the specified index in the playlist.
removeMediaSource(index) removes the media source at the given index.
moveMediaSource(fromIndex, toIndex) moves an existing media source within the playlist. This is useful as you do not have to create a new MediaSource object. And you can also move around the currently playing item without disrupting playback.
getMediaSource(index) allows you to access the media source at the given index.
getSize() returns the current playlist length.

How to implement seekTo() when using HLS with the ExoPlayer

I am trying to implement a basic radio player that can pause the live stream, rewind it and then fast forward it again.
I think that this functionality should be natively supported from version 2.1 of the ExoPlayer.
However, the rewind and fast-forward controls are grayed out when streaming even though they work when playing local content.
Here is how I am creating the player:
private void initExoPlayer(){
Handler mHandler = new Handler();
String userAgent = "userAgent";
Uri uri = Uri.parse(urlSourceOfStream);
dataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
1800000,
true);
mediaSource = new ExtractorMediaSource(uri,dataSourceFactory, Mp3Extractor.FACTORY,
mHandler, null);
bandwidthMeter = new DefaultBandwidthMeter();
trackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(trackSelectionFactory);
loadControl = new DefaultLoadControl();
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
exoPlayer.prepare(mediaSource);
((SimpleExoPlayerView) findViewById(R.id.exoPlayer)).setPlayer(exoPlayer);
}
The player can pause successfully, and it seems to be caching the content as I can resume the player after it has been paused for minutes. This also indicates that there should be some cache that can allow me to rewind the content.
I've also tried using the OkHttpDataSourceFactory :
OkHttpClient client = new OkHttpClient.Builder().cache(new Cache(getFilesDir() , 1000)).build();
OkHttpDataSourceFactory okHttpDataSourceFactory = new OkHttpDataSourceFactory(client, userAgent, null);
Trying to rewind the player like this makes the player play from the live stream position and does not rewind the content:
exoPlayer.seekTo(Math.max(exoPlayer.getCurrentPosition() - 1000, 0));
My question in a nutshell: How can I rewind and fast-forward an HLS with the ExoPlayer?
Thanks in advance.
It looks like there is a bug, https://github.com/google/ExoPlayer/issues/87 discussing this, and it's been closed. But I'm not sure if its reached the v2 release, and rather it might be in the dev release, here

Android: ExoPlayer: create MediaSource from DefaultHttpDataSource

I use ExoPlayer for playback of videos from url in my app and need to set an authorization header for each video. DefaultHttpDataSource can be used for that. For example,
DefaultHttpDataSource source = new DefaultHttpDataSource(Util.getUserAgent(mContext, "appAgent"), null);
source.setRequestProperty("Authorization", authToken);
MediaSource is needed to prepare the player. The question is how to create a MediaSource based on DefaultHttpDataSource?
Both of the constructors of ExtractorMediaSource require DataSource.Factory, not DataSource.
This returns a Datasource.Factory object:
return new DefaultDataSourceFactory(this, null, new DefaultHttpDataSourceFactory(Util.getUserAgent(mContext, "appAgent"), null));

Creating a simple instance of ExoPlayer

I am currently looking to develop an application that utilises Dash through the ExoPlayer in Android.
To begin with I am going through the demo project however am having trouble with even creating a simple working instance of ExoPlayer that can stream mp3 or similar.
Would really appreciate any help anyone can give relating to getting a very simple exoplayer instance working from which i can adapt and build upon or if anyone has any leads for more references or guides which I can follow as there seems to be very little documentation available.
Thanks very much for all and any help!
First of all instantiate your ExoPlayer with this line:
exoPlayer = ExoPlayer.Factory.newInstance(RENDERER_COUNT, minBufferMs, minRebufferMs);
If you want to play audio only you can use these values:
RENDERER_COUNT = 1 //since you want to render simple audio
minBufferMs = 1000
minRebufferMs = 5000
Both buffer values can be tweaked according to your requirements
Now you have to create a DataSource. When you want to stream mp3 you can use the DefaultUriDataSource. You have to pass the Context and a UserAgent. To keep it simple play a local file and pass null as userAgent:
DataSource dataSource = new DefaultUriDataSource(context, null);
Then create the sampleSource:
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
uri, dataSource, new Mp3Extractor(), RENDERER_COUNT, requestedBufferSize);
uri points to your file, as an Extractor you can use a simple default Mp3Extractor if you want to play mp3. requestedBufferSize can be tweaked again according to your requirements. Use 5000 for example.
Now you can create your audio track renderer using the sample source as follows:
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
Finally call prepare on your exoPlayer instance:
exoPlayer.prepare(audioRenderer);
To start playback call:
exoPlayer.setPlayWhenReady(true);
Here is how you would do it using the new ExoPlayer 2 API, and the SimpleExoPlayer.
First create the player:
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, bandwidthMeter);
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl);
player.addListener(...); // To receive events from the player
Then create your MediaSource. For MP3 you can use ExtractorMediaSource:
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
Uri uri = Uri.parse(mp3UriString);
Handler mainHandler = new Handler(Looper.getMainLooper());
MediaSource mediaSource = new ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory, mainHandler, mediaSourceListener); // Listener defined elsewhere
Then prepare and play when ready:
player.prepare(mediaSource);
player.setPlayWhenReady(true);
For DASH you would use DashMediaSource instead of ExtractorMediaSource.
Today while working on a project, I found that this.myExoPlayer = ExoPlayerFactory.newSimpleInstance(getActivity()); and some others are now deprecated and Android studio suggested to use new way. So I did a quick Google for it but everywhere I found the old way. So I looked into the SimpleExoPlayer.java file, read some methods. So this is how you initialize simpleExoPlayer:
Activity activity = getActivity(); // if you are in a fragment
// Or, activity = YourActivity.this; if you are in an Activity
SimpleExoPlayer simpleExoPlayer = new SimpleExoPlayer.Builder(activity).build();
I hope this is helpful.

Categories

Resources