Adjust Dash stream volume with Android Exoplayer - android

I'm trying to set up a seekbar to control the level of an instance of exoplayer streaming dash.
The setup I am using is a modified version of the demo project and am having trouble figuring out which element I should be trying to affect with the seekbars output ie how to use MSG_SET_VOLUME properly etc etc
Any input would be massively appreciated.
The end result I am looking for is an application with two instances of exoplayer both streaming dash content with a fader(seekbar) controlling the mix of the two players (which once this is figured out i presume should be easy enough if the maths is correct)
Again any help would be massively appreciated I have had a bit of a time with Exoplayer so far being such a novice! thanks guys!

If I read the ExoPlayer source code correctly you have to keep references to the audioRenderers you use when preparing the ExoPlayer instance.
exoPlayer.prepare(audioRenderer);
To change volume you have to send the following message:
exoPlayer.sendMessage(audioRenderer, MediaCodecAudioTrackRenderer.MSG_SET_VOLUME, 0.1f);
First you pass the audioRenderer for which you want to change the volume. Secondly you define the message which you want to send to the renderer which is MSG_SET_VOLUME, since you want to affect audio.
Finally you pass the value you want to set the volume to. In this example I chose 0.1f but of course you can use any value which fits your needs.
You can effect two different playback volumes if you send messages to both MediaCodecAudioTrackRenderers which you used to prepare playback. So you could send two messages with for example value 0.4f for audioRenderer1 and 0.6f for audioRenderer2 to blend the playbacks into one another.
I did not try this myself, but I think it should work.
This is the snippet of the original ExoPlayer code which is responsible for handling the MSG_SET_VOLUME message:
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
if (messageType == MSG_SET_VOLUME) {
audioTrack.setVolume((Float) message);
} else {
super.handleMessage(messageType, message);
}
}

Related

How to control youtube video quality in exoplayer android?

I am working on Android ExoPlayer as mentioned in this Article- https://betterprogramming.pub/android-exoplayer-play-videos-in-your-app-like-youtube-486853913397
But I am unable to control the video quality (360p, 480p, etc). How to do that? I need the complete code.
For ABR streams, ExoPlayer will automatically switch to the best bit rate based on its assessment of current network conditions etc - e.g. if it is playing a high bit rate for a particular piece of content and determines that the network is busy and its buffer is not keeping up, it will switch to a lower bit rate for that content. More info here:
https://exoplayer.dev/track-selection.html
If you mean that you would like to be able to control the bit rate manually, then the track selector functionality will allow you do that.
You can see more info here (linked from the ExoPLayer GitHub): https://medium.com/google-exoplayer/exoplayer-2-x-track-selection-2b62ff712cc9
The default interface looks like:
You can select the quality version by creating your own ABR algorithm, e.g., yourOwnABR(), then call it in the function updateSelectedTrack() of file AdaptiveTrackSelection.java as follows.
public void updateSelectedTrack(
long playbackPositionUs,
long bufferedDurationUs,
long availableDurationUs,
List<? extends MediaChunk> queue,
MediaChunkIterator[] mediaChunkIterators) {
...
int newSelectedIndex = yourOwnABR();
...

Exoplayer Mediaplayer Android delay applying PlaybackParameters

I'm using Exoplayer to play a video in my application, what I want to do is change the speed of playback, for which Exoplayer provides a straightforward solution:
val playbackParameters = PlaybackParameters(whateverSpeedFloat)
exoPlayer.setPlaybackParameters(playbackParameters)
Now this works, but the problem I have is that the effect is not immediate, when you change the speed it takes a few frames for the actual speed to change. I guess it's because some of the frames are preloaded or buffered and the set playback parameters only affect the frames after this.
If I stop the video, and change speed from say 0.5x to 2x, then press play, it's very obvious that there is a delay in playback speed change. But, if I press stop, change the speed from 0.5x to 2x AND seek a different point in the video, and press play, it works great, there is no delay. I guess it reloads/buffers the new frames with the right playback parameters. I tried doing
exoPlayer.clearVideoDecoderOutputBufferRenderer()
after changing speeds to try and rebuffer the frames after setting the playback parameters but it doesn't seem to change anything.
Any ideas on how to fix this? Or other video player libraries that wouldn't have this problem?
UPDATE:
I still haven't found a solution, I took the problem to ExoPlayer and an issue was raised and "fixed"(https://github.com/google/ExoPlayer/issues/7982), however I'm still having the same problem, so atm I'll just get back to them and wait.
However, what was mentioned is that the delay is a know issue, and that right now there is no solution,
Correct. We looked at options to address the delay a while ago but couldn't find a clean/general/easy to implement approach (there is no API we can use to process the audio just before the mixer, so we have to do it upstream of the audio track buffer, which introduces latency).
Instead, they suggested initialising Exoplayer with a DefaultRenderersFactory with AudioTrackPlaybackParams set to true:
val defaultRenderersFactory =
DefaultRenderersFactory(this).setEnableAudioTrackPlaybackParams(true)
exoPlayer = SimpleExoPlayer.Builder(this, defaultRenderersFactory).build()
And this does in fact get rid of the delay (not 100% but I'd say around 80% which is good enough), but then the video speed gets all clunky and starts freezing and changing speeds every time it is paused/played or seeked to a different point.
I also tried modifying the buffering configuration #GensaGames suggested but even though I tested different configurations for a while, I never saw any change in the behaviour so discarded the solution and went to the exoPlayer repo.
I'll update this question when I finally have a working video speed changer.
I think you can decrease time of the buffering within configuration setup during ExpPlayer initializing. Below ex. on configuration, you can go throw documentation and check possible values.
/* Instantiate a DefaultLoadControl.Builder. */
DefaultLoadControl.Builder builder = new
DefaultLoadControl.Builder();
/* Maximum amount of media data to buffer (in milliseconds). */
final long loadControlMaxBufferMs = 60000;
/*Configure the DefaultLoadControl to use our setting for how many
Milliseconds of media data to buffer. */
builder.setBufferDurationsMs(
DefaultLoadcontrol.DEFAULT MIN BUFFER MS,
loadControlMaxBufferMs,
/* To reduce the startup time, also change the line below */
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
/* Build the actual DefaultLoadControl instance */
DefaultLoadControl loadControl = builder.createDefaultLoadControl();
/* Instantiate ExoPlayer with our configured DefaultLoadControl */
ExoPlayer player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
new DefaultTrackSelector(),
loadControl);
There is also good article about changing buffer time options.

switching from Media Player to Media Player force close

hi ive been working on my app and have found a hurdle in an activity i just cant seem to overcome. the activity is essentially a large novelty piano with 8 keys that play sounds there are 6 buttons along the side that change the picture of the notes and the notes themselves, this i accomplished :-) now i would like to add a background song to each different set of notes (instruments) only when i do the app crashes i have set the mediaplayer at the top (globally?) using MediaPlayer mp; MediaPlayer mp2; etc and im using this in my code to check if any music is playing, stop it, release it, and then play the piece i want,
if(mp!=null&&mp.isPlaying()){
mp.stop();
mp.release();
}
if(mp2!=null&&mp2.isPlaying()){
mp2.stop();
mp2.release();
}
if(mp3!=null&&mp3.isPlaying()){
mp3.stop();
mp3.release();
}
mp3 = MediaPlayer.create(MusicActivity.this, R.raw.snaps);
mp3.setLooping(true);
mp3.start();
this again works but going from one to another and then back crashes the app. is there something else i should be doing? or is just an out of memory error?
EDIT--
Thanks to ranjk89 for his help
changed to soundpools but they wont stop ranjk89 suggests referring to the stream id and not the sound id looking for a little more clarification if possible i have
farmback =0;
drumback =0;
at the top then its loaded in oncreate using
drumback = sp.load(this, R.raw.snaps,1);
farmback = sp.load(this, R.raw.oldmacdonaldbeta,1);
and then way down, in the same method i change the button icons, not the same method i change all my other sounds for my notes i call
sp.stop(drumback);
sp.play(farmback, 1, 1, 0, -1, 1);
in one and
sp.stop(farmback);
sp.play(drumback, 1, 1, 0, -1, 1);
in another but there are 6 different instruments in total that all need a different backing track which should stop when the instrument is changed and play the one associated to it so something like
if (sp !=null && sp.isplaying()){
sp.stop();
sp.play(dumback);
}
but obviously this is not possible any help appreciated
My Initial reaction is, you shouldn't be using multiple MediaPlayer at all in the first place.
I would suggest you to use SoundPool as you can load all the media(audio) initially, once they are all loaded you can play them at will. Plus you won't have multiple players which would downsize the complexity of your code.
But if you do want to use Media player,
See this. But be aware that once you release you will not be able to reuse that instance of MediaPlayer. Even if you are using multiple MediaPlayers, do not call release on them unless you are sure you don't want to use them any more. Use stop()/prepare() combination.
For application doing too much work on the Main Thread,
If you either use a SoundPool or only one MediaPlayer and still bump in to the same issue, Use AsyncTask. Android dev site has a very good tutorial on this

Android : multiple audio tracks in a VideoView?

I've got some .MP4 video files that must be read in a VideoView in an Android activity. These videos include several audio tracks, with each one corresponding to a user language (eg. : English, French, Japanese...).
I've got unexpected trouble finding any help or documentation to provide such a feature. I'm currently able to load the video and play it in a VideoView with a MediaController, but not to change audio tracks.
I'm not sure the Android SDK provides any easy way to do this, which leaves me quite clueless on how to solve my problem. I was thinking of extracting every audio track, loading the audio that I want into a MediaPlayer depending on the language, then make audio and video play together. But I fear that some sync issues could arise and prevent me from doing this.
If you have any clue, any advice to help me getting started with this problem, you're more than welcome.
No 3rd party library required:
mVideoView.setVideoURI(Uri.parse("")); // set video source
mVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
MediaPlayer.TrackInfo[] trackInfoArray = mp.getTrackInfo();
for (int i = 0; i < trackInfoArray.length; i++) {
// you can switch out the language comparison logic to whatever works for you
if (trackInfoArray[i].getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO
&& trackInfoArray[i].getLanguage().equals(Locale.getDefault().getISO3Language()) {
mp.selectTrack(i);
break;
}
}
return true;
}
});
As far as I can tell - audio tracks should be encoded in the 3-letter ISO 639-2 in order to be recognized correctly.
Haven't tested myself yet, but it seems that Vitamio library has support for multiple audio tracks (among other interesting features). It is API-compatible with VideoView class from Android.
Probably you would have to use Vitamio VideoView.setAudioTrack() to set audio track (for example based on locale). See Vitamio API docs for details.
Now you can Play Multiple audio track through ExoPlayer.
Here is the details,
https://exoplayer.dev/track-selection.html
Exo Player Track Selection
VideoView class can't support your require.U must parse to get audio stream data(you want) to play with AudioTrack class on java layer.

Getting audio volume during playback

I have some audio data (raw AAC) inside a byte array for playback. During playback, I need to get its volume/amplitude to draw (something like an audio wave when playing).
What I'm thinking now is to get the volume/amplitude of the current audio every 200 milliseconds and use that for drawing (using a canvas), but I'm not sure how to do that.
.
.
.
.
** 2011/07/13 add following **
Sorry just been delayed on other project until now.
What I tried is run the following codes in a thread, and playing my AAC audio.
a loop
{
// int v=audio.getStreamVolume(AudioManager.MODE_NORMAL);
// int v=audio.getStreamVolume(AudioManager.STREAM_MUSIC);
int v=audio.getStreamVolume(AudioManager.STREAM_DTMF);
// Tried 3 settings above
Log.i(HiCardConstants.TAG, "Volume - "+v);
try{Thread.sleep(200);}
catch(InterruptedException ie){}
}
But only get a fixed value, not dynamic volume...
And I also found a class named Visualizer, but unfortunately, my target platform is Android 2.2 ... :-(
Any suggestions are welcome :-)
After days and nights, I found that an Android app project called ringdroid
can solve my problem.
It helps me to get an audio gain value array, so that I can use to to draw my sound wave.
BTW, as my experience, some .AMR or .MP3 can't be parsed correctly, due to too low bitrate...

Categories

Resources