Time taken in connecting while audio streaming in android? - android

I am using simple audio streaming in android app like this:
try {
MediaPlayer media = new MediaPlayer();
media.setAudioStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
media.setDataSource("http://indiespectrum.com:9000");
media.prepare();
media.start();
}
catch(Exception e)
{
//Getting Exception
}
Where I am using four different URL .When I start the radio streaming it takes a while to start playing.Sometimes it takes 5-6 sec and sometimes around 40-45 sec to start playing the radio. I just want to know if I can speed up these time taken .As all of these uses Shoutcast is there anyway I could speed up the connection or it depends on some kind of bitrate or something.Please help?

One way to speed up things a lot is leveraging the UIMain thread and doing the audiostreaming using AsyncTask, wich enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

Related

How to reduce Buffer time on streaming app?

I'm Building an android app that is supposed to stream an online radio station from a URL.
I am currently working on a demo and I have gotten a lot of help from online tutorials but I have a problem.
When I click on the NEXT button it's supposed to get it's audio from another URL, which gives it the effect of changing the station, but it takes too much time and most times it doesn't seem to work.
Is there any way I could reduce the time by 95% cause I want it to start almost immediately you click on the next button
CODE FOR THE NEXT BUTTON
b_next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaPlayer.stop();
mediaPlayer.reset();
try {
mediaPlayer.setDataSource("http://stream.radioreklama.bg/veronika.opus");
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();
}
});
The problem may not be buffering- there might be some slow startup time on the server side for example.
Either way, if you want to monitor the buffering there is a call back provided with MediaPlayer which will do this - 'OnBufferingUpdateListener.onBufferingUpdate()'.
From the MediaPlayer documentation (https://developer.android.com/reference/android/media/MediaPlayer.html#setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)):
While in the Started state, the internal player engine calls a user supplied OnBufferingUpdateListener.onBufferingUpdate() callback method if a OnBufferingUpdateListener has been registered beforehand via setOnBufferingUpdateListener(OnBufferingUpdateListener). This callback allows applications to keep track of the buffering status while streaming audio/video.
One common technique to speed up switching between streams, across platforms, is to have the next stream prepared in advance.
For your case you would need a second media player which you would initialise and move to the prepared state, and possibly even seek to a point, and then play it as soon as you stop the other one.
For live streams this will be a little more difficult as you can't see to a point in the same way. You could experiment with having the second player playing but with the volume turned down, although this is obviously not very efficient, unless you have some reliable way to predict when the user is about to switch.

Gapless Playback with android MediaPlayer

I'm trying to repeatedly play a audio continuously, without any gap. I've tried,
mediaplayer.setLooping(true);
But it gives a gap between repeat time. And tried this,
mediaplayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp)
{
mediaplayer.start();
}
});
It gives a gap also. I've tried with different audio format. But neither way worked for me. Is there any other way in android?
When a playback finishes, the player engine would check if all tracks are completed and once done, it will check for the looping flag. Based on the looping flag, a seek to 0 seconds. As part of the seek, the player engine will read the data from the specific position and start the playback.
The delay may be due to the seek implementation along with the delay introduced by the storage medium like sdcard apart from re-initializing all tracks and restarting them. Hence, there is definite delay by the time the player reverts back to the starting position.
The underlying looping implementation can be found in this function AwesomePlayer::onStreamDone as shown here: http://androidxref.com/4.2.2_r1/xref/frameworks/av/media/libstagefright/AwesomePlayer.cpp#834
EDIT 1:
To implement a true gapless playback, you could also consider the setNextMediaPlayer() feature.
Probably MediaPlayer is re-prefetching the data from server (or even from the device itself), this may take some seconds. Only if the buffering is done, it starts playing again.
If you want to bypass this, you can AFAIK only use a second MediaPlayer which starts buffering the media file shortly before the first one stops playing. Then you can start the second one on OnCompletionListener.

Android MediaPlayer streaming stops on network change

I am streaming audio using MediaPlayer on Android.
When the device moves from Wi-Fi to the cell network or vice-versa, the MediaPlayer stops playback.
Typically there are a few seconds-worth of audio in the buffer, so playback does not cease immediately.
Ideally I would like to pick up the stream for uninterrupted playback, but I cannot see how to do it.
I am working with both mp3 files hosted on the server and a live broadcast stream.
From a servers point of view, changing network mode from WiFi to 3G (visa versa), will look like a brand new connection from a separate IP's (client).
If the server that you are downloading from does not support tracking the stream (e.g number of seconds, sequence, byte) (unlike media-servers),It will have to start serving your mp3 from 0 byte again.
If your URL is pointing to a MP3 file located at a standard HTTP server, your situation will be what to expect. You should look into using a Media streaming server, so you could resume downloading/streaming at your choice. When you receive the intent that the connection is lost/resume, you could point your mediaplayer to the new URL with file-position in the URL (e.g seconds=19, bytes=57365).
Not sure if this helps you, but it explains a bit whats going on "behind the scenes".
Try setting your setOnCompletionListener and setOnErrorListener. In on complete with a live stream you can just call prepareAsync() again and this will kick off the stream again. There is no graceful way of doing this really unless you write your own media framework.
You can also listen in you onError() for the MEDIA_ERROR_SERVER_DIED you can then fire off the prepareAsync() again.
You'll find that the MediaPlayer will either Error or Complete. If you handle both these callbacks the very least you can do is restart the stream on change of network, as for smooth playback.. that would require custom mediaframework as the android one is pretty shoddy.
I don't know why your media player is stopping, but maybe you could add an onReceive method and put "mp.start()" in the method to make it restart playback.
Android, How to handle change in network (from GPRS to Wi-fi and vice-versa) while polling for data
You might need to make a separate class, but that should explain how to create a method that is called when you switch networks, at which point you could call "mp.start()" to resume playback (assuming mp is your MediaPlayer).
This assumes, of course, that your MediaPlayer is only being paused when you are switching networks, not stopped.
As Vidar says, reestablishing the connection will be treated by the server as a new connection.
It appears that I have to double-buffer the audio playback, which means building a custom media player. This can provide continuous audio, but it will still skip when listening to a live stream.
The MP3 file is a bit easier because I can know the playback position. Not so with the live stream.
As gmaster says, I'll need a broadcast receiver to establish a new connection when the network changes.
The audio buffer from the previous network connection should continue to playback while a new audio buffer is filled via the new connection.
When the new buffer is full enough to start playback I can switch playback to it.
If I am streaming a file, with server support and a little bit of work I can ensure that the current playback position data is in both buffers and switch seamlessly.
As the live stream buffers cannot be synchronized, there will inevitably be a glitch when they switch.
A larger buffer will avoid audio drop-out if the connection takes a while to establish, but will delay the first start of playback. An MP3 file can be downloaded and fill the buffer faster than real time, but the live stream will buffer in real time.
Chris.Jenkins mentions some MediaPlayer methods that can help but points out that this does seem to need a custom framework. It will need to handle the conditions he mentions and others.
If I can make it look pretty I'll post it here. I'm going to keep the question open.

AsyncTasks and Audio

I am trying to play multiple audio files, one after the other and am currently using AsyncTasks to prepare and start the mediaPlayer but have failed to find a good way to move on the to next track at the end of the current one. Not every audio file will be played every time, and it's playing is decided by a boolean value.
Any help is much apprecieated.
I guess you have read android-sdk/docs/reference/android/media/MediaPlayer.html , it says:
When the playback reaches the end of stream, the playback completes.
If the looping mode was being set to truewith setLooping(boolean), the
MediaPlayer object shall remain in the Started state. If the looping
mode was set to false , the player engine calls a user supplied
callback method, OnCompletion.onCompletion(), if a
OnCompletionListener is registered beforehand via
setOnCompletionListener(OnCompletionListener). The invoke of the
callback signals that the object is now in the PlaybackCompleted
state. While in the PlaybackCompleted state, calling start() can
restart the playback from the beginning of the audio/video source.
So you may set a new source, prepareAsync then start in completion callback. In this way , you get continuous playback, but it is not seamless.
Doubtful using MediaPlayer for this will work like you want it to. Try this tutorial:
http://www.droidnova.com/creating-sound-effects-in-android-part-1,570.html
If that doesn't work you'll probably have to mix the sounds together yourself them stream that result directly to the hardware using AudioTrack. That's more low level, but it will give you the most control. It just depends on what you are doing if the AudioManager solution will work for you or not. It's definitely the simpler route. But, if you're trying to line up two samples so that when one finishes the next begins, like in a music app, you probably will have to mix and stream that audio yourself.
http://developer.android.com/reference/android/media/AudioTrack.html
Algorithm to mix sound

Player short audio in UI thread

Is it a good idea to play a short audio within an UI thread? The code is like:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mymp3);
mMediaPlayer.start();
}
Or, I'd better play the audio in an AsyncTask?
Thanks.
As a thumb of rule running that on the main (that's what it actually means in Android) thread is not a good idea.
There are several reasons, for example, what will happen if tomorrow it will not be a short audio sample? how will the application behave if exactly on the same time an incoming call will arrive...it can take 2-3 seconds (depends on the length of the audio sample) until the user will be able to answer.
The "good practice" for audio playing is using services.

Categories

Resources