My app needs to record video with a maximum time of 8 seconds. This is already implemented with MediaRecorder.setMaxDuration(long milliseconds).
The app also needs a progress bar in the top and a label with a count down of the remaining time.
The problem here is that there's an offset between the UI and the MediaRecorder progress, and this leads to confusion in the user. For example, the user thinks that he/she recorded something because the progress in the UI said so, but the media recorder cut off the video a second earlier.
The challenge is to start the progress bar and counter at the exact same time as the recorder actually starts recording.
I've tried starting the timer after MediaRecorder.start(), in a callback when the created file is modified for the first time, but I haven't found a way to achieve this in a correct way. We tried setting a hard coded offset to these values but of course it didn't work the same for every device.
I wish there was a callback from the MediaRecorder to inform that it has actually started to record the video, or maybe the current length.
Is the problem clear? Has someone solved this before?
MediaRecorder has known issues with cutting off audio early. I implemented a recorder with a button - clicking the button to stop the recorder would actually yield an audio file with the last second cut off.
Not sure if your UI offset is a separate issue, but I would try extending the MediaRecorder by half a second after the user attempts to end it. You can either do this by changing the maximum time to 8.5 seconds, or just using this line of code:
android.os.SystemClock.sleep(500);
Related
When I play a sound in my app it comes off as clippy and distorted. Here is a recording: recording.
Here is the sound file as it was uploaded to android studio: success sound cue
Here is the function that calls the sound from the .raw
public void playCorrectAnswerSound() {
final MediaPlayer mp = MediaPlayer.create(this, R.raw.correct);
mp.start();
}
Heres how I call it:
Thread t = new Thread(){
public void run(){
playCorrectAnswerSound();
}
};
t.start()
This is my first time debugging a sound related issue. I don't know what else to include in this post, so if you need more info please say so.
EDIT: I was asked to record more of the distortion. Here it is. Also I should say that after more testing, my physical device lacks the sound distortion while the sound distortion is present on 3 different emulators.
I'm going to say this is stuttering due to underrun (starvation) of the MediaPlayer's internal playback buffer. That is, the MediaPlayer can't supply data fast enough to keep up with the sound hardware (which suggests a severe lack of processing power). If the buffer starves, it'll start to play back old data (because it's a circular buffer). This causes a sharp phase transition, which sounds like a "click". Presumably the MediaPlayer recovers quickly enough that the "correct" sound resumes playing shortly thereafter.
Here is a picture of the spectrum from Audacity. 0-4KHz. The first row is the clean .mp3; the next four rows are the distorted recordings (in no particular order). All rows have been aligned in time, and are roughly the same amplitude. The large vertical stripes in the last four rows represent the distortion/clicks that you hear.
We are trying play audio from url (m3u8 file). Media player starts fine no issues. Audio also plays cleanly. Issue starts when do seek in the player. Behavior very strange. it seeks to the proper position then starts playing audio. After while it seeks again like couples seconds (better word is skips some seconds since it jumps to the position directly) and can be observed in the media playback time counter, again plays for a while again jumps some seconds and this continues till end of the media.
We have our custom seek bar which is nothing but a progressbar, and when we do seek the progress bar we send same seek position to media player by calling onseek() method.
Note: Issue Happens only Lollipop nexus devices(tablet and phone).
Strange observation jump happens only if the time counters last position 9
(i.e if mediaplayed 12:29[mm:ss] then will jump to some other random place 12:3X[mm:ss],again mediaplayed 12:39[mm:ss] then will jump to some other random place 12:4X [mm:ss] )
Why is it happening?
You should pass the outer manifest to the player. This should resolve your issue.
When using MediaPlayer, I noticed that whenever my phone stucks, the MediaPlayer glitches and then continues playing from the position in the audio it glitched.
This is bad for my implementation since I want the audio to be played at a specific time.
If I have a song of 1000 millisecond length, I want is the ability to set MediaPlayer to start playing at some specific time t, and then exactly stop at at time t+1000.
This means that I actually need two things:
1) Start MediaPlayer at a specific time with a very small delay.
2) Making MediaPlayer glitches ignore the audio they glitched on and continue playing in order to finish the song on time.
The delay of the functions is very important to me and I need the audio to be played exactly(~) at the time it was supposed to be played.
Thanks!
You will need to use possibly mp.getDuration(); and/or mp.getCurrentPosition(); although it's impossible to know exactly what you mean by "I need the audio to be played exactly(~) at the time it was supposed to be played."
Something like this should get you started:
int a = (mp.getCurrentPosition() + b);
Thanks for the answer Mike. but unfortunately this won't help me. Let's say that I asked MediaPlayer to start playing a song of length 3:45 at 00:00. At 01:00 I started using the phone's resources, due to the heavy usage my phone glitched making MediaPlayer pause for 2 seconds.
Time:
00:00-01:00 - I heard the audio at 00:00-01:00
01:00-01:02 - I heard silence because the phone glitched
01:02-03:47 - I heard the audio at 01:00-03:45 with 2 second time skew
Now from what I understood MediaPlayer is a bad choice of usage on this problem domain, since MediaPlayer provides a high level API.I am currently experimenting with the
AudioTrack class which should provide me with what I need:
//Creating a new audio track
AudioTrack audioTrack = new AudioTrack(...)
//Get start time
long start = System.currentTimeMillis();
// loop until finished
for (...) {
// Get time in song
long now = System.currentTimeMillis();
long nowInSong = now - start;
// get a buffer from the song at time nowInSong with a length of 1 second
byte[] b = getAudioBuffer(nowInSong);
// play 1 second of music
audioTrack.write(b, 0, b.length);
// remove any unplayed data
audioTrack.flush();
}
Now if I glitch I only glitch for 1 second and then I correct myself by playing the right audio at the right time!
NOTE
I haven't tested this code but it seems like the right way to do it. If it will actually work I will update this post again.
P.S. seeking in MediaPlayer is:
1. A heavy operation that will surely delay my music (every millisecond counts here)
2. Is not thread safe and cannot be used from multiple threads (seeks, starts etc...)
In my app I set a mediaplayer with with this instructions:
mpBackGround = MediaPlayer.create(context, R.raw.bg_music);
mpBackGround.setVolume(0.7f, 0.7f);
mpBackGround.setLooping(true);
mpBackGround.start();
but at the end of first loop I have a little pause between first cycle and second cycle; I also have cut silence spaces in the file (bg_music). With files of type .mid I have not problem but with mp3, wav and other I have this problem...and I have all mp3 files (not midi).
Is there another solution to solve this problem? thanks
just out of curiosity, is this little pause between the cycles roughly equivalent to the time it takes to seek from one end of the file to the other? It sounds like a performance issue related issue to me.
If thats the case, I would create two instances of media players, and handle the repeating my self. As in, .start() one when the other one finishes. Then you can "rewind" one while the other is playing.
I am creating a program which requires me to change a setting in the program when the video reaches specific points (at 1/3 of the video's completion, 2/3's and on completion). Android has a built in callback method for completion so performing an action at that point in time is not difficult. However, I don't know how to go about checking when the video has reached 1/3 and 2/3's of completion.
Using a MediaPlayer control you will get
the total duration of your media file in milliseconds:
myMediaPlayer.getDuration()
you will implement a thread that check every second for the current position at 1/3, 2/3 and 3/3 of the videos completion, with
myMediaPlayer.getCurrentPosition(); //***current Position in milliseconds.