Reputation: 5761
I'm using MediaPlayer
to stream a radio over HTTP. On Lollipop my stream takes about a minute to start which is unacceptable. It takes about 20 seconds on Kitkat, which is already a pain but now became unusable.
There is a well known problem with this component related to buffering: the amount of bytes to buffer is harcoded and can't be changed.
My code is really standard
player.reset();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(streamUrl);
player.prepareAsync();
And on prepared I do
player.start();
I've heard about alternatives as GStreamer
but I couldn't make it work on Windows.
I wonder if anyone has a working solution to stream radio over HTTP with a decent start delay.
EDIT
I tested ExoPlayer but the lower start time I get is 15 seconds. The player is stuck on "preparing" state (not buffering, that's later so far I see).
EDIT
The format of the stream is AAC
EDIT
I tested https://code.google.com/p/aacdecoder-android/ but the only problem this library has is the lack of support to stream pause. It's a requirement of my application to support pause on online stream.
Upvotes: 10
Views: 17015
Reputation: 9
This is for mp3 media player only we can use this code
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent)
{
double ratio = percent / 100.0;
int bufferingLevel = (int)(mp.getDuration() * ratio);
seekBar.setSecondaryProgress(bufferingLevel);
}
});
Upvotes: 0
Reputation: 15476
If your use case is compatible with GPL/LGPL licenses, then VLC should be exactly what you need. VLC is able to stream from your URL on a 3G network with only ~1 sec delay.
Step 1: Download VLC source code and compile per the instruction
Step 2:
The most important class is org.videolan.vlc.audio.AudioServiceController
, which was called from org.videolan.vlc.gui.MRLPanelFragement.processUri() --> org.videolan.vlc.util.Util.openStream(Context, String) --> AudioServiceController.load(String, boolean)
. You can remove all the unnecessary code other than AudioServiceController
and its support classes to slim down the size
Upvotes: 10
Reputation: 2541
If you are willing to spend some $ on a library , I recommend Bass It has a full set of API calls that you can integrate and also a solid documentation. There is a shareware version that you can test.
If you are not willing to spend $. I highly recommend VLC @Kai mentioned, also in the future you can expand your application to stream video with it. I worked with the API before to perform a live stream for my aquarium. @Kai provided you with the necessary links.
Check out this link for more info.
Upvotes: 0
Reputation: 907
i'll post how i do it and hoe it gives a difference. it's not a realtime sound item ( it's a mp3 from an online api, but it's about 4-6mb) so it could vary, but takes less than 3-5 seconds to load on my genimotion VM.
i know it's almost the same as your code. maybe if you could share the url or a similar one giving the same problems i could test it in my app.
runThread(url);//ran on the oncreate.
private void runThread(final String url) {
new Thread() {
public void run() {
mediaPlayer = new MediaPlayer();//mediaplayer is a global variable.
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try{
mediaPlayer.setDataSource(url);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
//audio did finish.
}
});
mediaPlayer.prepare(); // might take long! (for buffering, etc)
duration = mediaPlayer.getDuration();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//here you should start playing it.
}
});
}
});
}
catch(Exception e)
{
}
}
}.start();
}
tested on a nexus 4 with jelly bean, similar time responses.
Upvotes: 0
Reputation: 874
There are 2 kinds of delay in streaming a. is the Buffering delay which is the startup delay and b. is the broadcast delay.
In the case of media player, the stream is taking 1 minute to buffer. So we first need to see how the time taken to fill the buffer can be reduced. I am not sure if that is possible in the Media player code of Android to configure the buffer size.
However if we try to use AAC decoder library for android (https://code.google.com/p/aacdecoder-android/downloads/detail?name=aacdecoder- android-0.8.zip) then we have the provision to fill the input buffer.
Pl. refer to the code snippet below, you can fill your input buffer capacity, based on your requirement and then you can start the playback. Since we have control on the input buffer capacity we can try to reduce time delay to start the playback. Pl. check if this can help you.
/**
* Sets the audio buffer (AudioTrack) capacity.
* The capacity can be expressed in time of audio playing of such buffer.
* For example 1 second buffer capacity is 88100 samples for 44kHz stereo.
* By setting this the audio will start playing after the audio buffer
is first filled.
*
* NOTE: this should be set BEFORE any of the play methods are called.
*
* @param audioBufferCapacityMs the capacity of the buffer in milliseconds
*/
public void setAudioBufferCapacityMs( int audioBufferCapacityMs ) {
this.audioBufferCapacityMs = audioBufferCapacityMs;
}
Upvotes: 0
Reputation: 15668
You should avoid media player for live radio streams.
I have used the following library and it works great: https://code.google.com/p/aacdecoder-android/
Upvotes: 1
Reputation: 572
I can suggest to switch from MediaPlayer to ExoPlayer. With ExoPlayer is feasible to setup buffering params as following:
public static ExoPlayer newInstance(int rendererCount, int minBufferMs, int minRebufferMs) {
return new ExoPlayerImpl(rendererCount, minBufferMs, minRebufferMs);
}
minBufferMS means a minimum duration of data that must be buffered for playback to start or resume following a user action such as a seek.
minRebufferMs means a minimum duration of data that must be buffered for playback to resume after a player invoked rebuffer (i.e. a rebuffer that occurs due to buffer depletion, and not due to a user action such as starting playback or seeking).
Default values are 500 and 5000, respectively.
Upvotes: 3