- I am working on a project which needs to play video in slow motion.
- I am well aware that Android doesn't provide these functionality.
- I found PVPlayer Engine and libVLC which possessed these capabilities, but i didn't found any tutorial or proper documentation of including them in the android project and using them.
- So i tried doing this by using Runnable and Handler, it was successful in slowing down the video but they possessed jerks during playing.
public class MainActivity extends Activity {
VideoView vx;
Button mbutt;
Handler h ;
int curr = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
h = new Handler();
vx = (VideoView)findViewById(R.id.videoView);
mbutt = (Button)findViewById(R.id.button_Play);
vx.setVideoPath("/mnt/sdcard/you.mp4");
mbutt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
vx.start();
}
});
Runnable r = new Runnable() {
#Override
public void run() {
if (vx != null) {
if (vx.isPlaying()){
vx.pause();
}
else{
vx.start();
}
}
h.postDelayed(this, 50);
}
};
h.postDelayed(r, 200);
}
}
- I have tried various combination of pause time and playing time to remove the jerks but all in vain, can anyone help me in removing these jerks so it plays a nice slow motion video or suggest another easy to integrate library into my android project.
Thanks in advance......
I am late but I found a solution for API 23 and above. Android 6.0 added PlaybackParams class to control playback behavior. -
Use setPlaybackParams method of MediaPlayer as given below -
videoview = (VideoView)findViewById(R.id.videoview);
videoview.setVideoURI("Your Video URI");
videoview.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
//works only from api 23
PlaybackParams myPlayBackParams = new PlaybackParams();
myPlayBackParams.setSpeed(0.5f); //here set speed eg. 0.5 for slow 2 for fast mode
mp.setPlaybackParams(myPlayBackParams);
videoview.start();//start your video.
}
});
If you are searching how to embedded VLC into android, you can ref to this.
and you can change the speed by calling setRate(0.5f) to libVLC for slow motion.
Related
I am to play video in android from Vimeo doing online streaming. For this, Right now, I am using VideoView. Now, I wanna control the video playback speed control feature like: 0.5x,1x,1,5x,2x And video cache support.
Are both of these possible with Android VideoView or is there any third player that I can use?
Help!
Hi for the best control i advice you with vlc lib or pvPlayer. or you can use this simple code but it dosen't work well.
public void slowMotion(){
final Handler handler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
if (videoview != null) {
if (videoview.isPlaying()){
videoview.pause();
}
else{
videoview.start();
}
}
handler.postDelayed(this, 50);
}
};
handler.postDelayed(r, 800);
}
Good luck :D
i have a button that plays a sound.
When i push the button multiple times, it plays the sound multiple times.
This is oke, i want this.
But when i click the stop button it must stop all sounds currently playing.
I used:
while (mediaPlayer.isPlaying()){mediaPlayer.stop();}
but it is not working, the sounds keep on playing. Can someone help me?
Here is my full code:
public class HelloSoundboard extends Activity {
MediaPlayer mediaPlayer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button item1 = (Button)findViewById(R.id.item1);
item1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mediaPlayer = MediaPlayer.create(getBaseContext(), R.raw.atyourservice);
mediaPlayer.start();
}
});
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
while (mediaPlayer.isPlaying()){mediaPlayer.stop();}
// mediaPlayer.stop();
}
});
}
}
SoundPool is a much better alternative for this purpose. I would caution strongly against instantiating multiple MediaPlayer instances as most systems do not have the resources to generate many parallel active instances. You wil find on many device that hitting the button upwards of 5 times will cause a memory based crash.
As far as stopping all active streams, there is not baked-in function for this, but it's easy to accomplish in a manner to similar to your existing code. As a side note, there is an autoPause() method, which halts all streams, but it doesn't truly end their playback (as the method name insinuates). Here is a simple example to manage your audio streams:
//SoundPool initialization somewhere
SoundPool pool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
//Load your sound effect into the pool
int soundId = pool.load(...); //There are several versions of this, pick which fits your sound
List<Integer> streams = new ArrayList<Integer>();
Button item1 = (Button)findViewById(R.id.item1);
item1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int streamId = pool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f);
streams.add(streamId);
}
});
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (Integer stream : streams) {
pool.stop(stream);
}
streams.clear();
}
});
It is much more memory efficient to manage a list of streamID values than MediaPlayer instances, and your users will thank you. Also, note that it is safe to call SoundPool.stop() even if the streamID is no longer valid, so you don't need to check for existing playback.
HTH
I'm not sure about this, but I think is better if you use a SoundPool.
"SoundPool is designed for short clips which can be kept in memory decompressed for quick access, this is best suited for sound effects in apps or games".
"MediaPlayer is designed for longer sound files or streams, this is best suited for music files or larger files".
You can use a list of MediaPlayers:
List<MediaPlayer> mps = new ArrayList<MediaPlayer>();
Button item1 = (Button)findViewById(R.id.item1);
item1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
MediaPlayer mp = MediaPlayer.create(getBaseContext(), R.raw.atyourservice);
mp.start();
mps.add(mp);
}
});
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (int i = mps.size() - 1; i >= 0; --i) { //changed ++i to --i
if (mps.get(i).isPlaying()) {
mps.get(i).stop();
}
mps.remove(i);
}
}
});
Hi I am creating an app which will play livestream.com's rtsp live channel.
I am launching the player using intent within my app as following:
iPlayer = new Intent(Intent.ACTION_VIEW);
//iPlayer.setType("video/*");
iPlayer.setData(Uri.parse(videoUrl));
startActivity(iPlayer);
When the media player is launched through my Application, the video performance is very poor. It stops for buffering every few seconds, plays for few seconds and pauses for buffering again.
ON the other hand, If I open the url in android browser (eg. http://m.livestream.com/abcalbania) it has a video tag on that page and triggers video player. THIS time, the video runs very smooth.
Any Idea why this might happen? And how this can be fixed?
I do not want to launch browser URL as intent.
This is done on Atmel cortex A9 chipset with Android 2.3.4
The problem is caused by the codecs that probably are not supported by your player.
for example i have a video created with MPEG Audio codec along with the H.264 video codec.
if i launch the video through my Application the video runs smoothly, but if i launch a video in Ooyala Hook Player it has a very poor performance, it plays the video every 3 seconds, the reason is that the stream use MPEG audio codec instead of AAC Audio codec that is supported.
You will find the answer with:
what codecs are used to create de video, and what are supported by
your player?
Use this code for smooth STREAM
String videoUrl = "rtmp://mystream";
Intent i = new Intent(android.content.Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse(videoUrl), "video/*");
startActivity(i);
Why not you play this in your own activity, create activity and render the video view like
private String path2 = "rtsp://...";
Uri video = Uri.parse(path2);
mVideoView.setVideoURI(video);
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();
mVideoView.postInvalidateDelayed(100);
mVideoView.start();
Also you can buffer before start playing maybe 5 secs and than successive buffering will be fast. you can control more thing by your own.
Android's MediaPlayer handle very well RTSP - don't open an external app - it's not necessary and product-wise wrong.
About your question - the browser might send another parameters to the video player that help the video play smooth, I didn't check it but it sounds like the only possible option for what you're describing. Example for the extra param might be the video resolution / encoding / size .. you can get all of them easily using MediaMetaDataRetriever.
If you don't want to use the native VideoView or MediaPlayer you can always add external player to your
app, like libVLC or Vitamio.
I recommend of using Vitamio, is really easy to use and integrate. LibVLC is in native code, it means you'll have to build it using ndk and add its libs to your project.
You can find here how to do that.
Android video view support RTSP urls well no need to pass intent to other application.Try out with this code, pass xml with declaration of video view and find it inside this activity.
public class VideoPlayer extends Activity
{
private VideoView mVideoView;
String videoURL="";
static Utility utility;
static Context context;
//MediaController mediaController;
//int iCurrentpostion=0;
int counter=0;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_video_player);
setupViews();
}
private void setupViews()
{
context=VideoPlayer.this;
//utility=new Utility(VideoPlayer.this);
showProgressDialog("Please wait", "Loading video..");
//videoURL=getIntent().getExtras().getString("url");
mVideoView=(VideoView)findViewById(R.id.xvdvwTab);
// mediaController=new MediaController(context);
// mVideoView.setMediaController(mediaController);
mVideoView.setOnPreparedListener(new OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
utility.hideProgressDialog();
mVideoView.start();
mVideoView.requestFocus();
}
});
mVideoView.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
finish();
}
});
mVideoView.setOnErrorListener(new OnErrorListener()
{
#Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
utility.hideProgressDialog();
return false;
}
});
playVideoFile();
}
private void playVideoFile()
{
try
{
mVideoView.setVideoURI(Uri.parse("your url"));
}
catch (Exception e)
{
utility.hideProgressDialog();
if (mVideoView != null)
{
mVideoView.stopPlayback();
}
}
}
#Override
protected void onResume()
{
/*if(mVideoView!=null)
{
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mVideoView.requestFocus();
if(iCurrentpostion!=0)
mVideoView.seekTo(iCurrentpostion);
mVideoView.start();
}
super.onResume();*/
}
#Override
protected void onDestroy()
{
try
{
if (mVideoView != null)
{
mVideoView.stopPlayback();
mVideoView=null;
}
super.onDestroy();
} catch (Exception e)
{}
}
public void showProgressDialog(String title,String Message)
{
hideProgressDialog();
progressDialog=new ProgressDialog(mActivity);
progressDialog.setTitle(title);
progressDialog.setMessage(Message);
if(Constant.isActivityisRunning)
progressDialog.show();
}
public void hideProgressDialog()
{
if (progressDialog != null)
{
if (progressDialog.isShowing())
{
progressDialog.dismiss();
progressDialog = null;
}
}
}
}
I think play video by Asynchronously for better performance. My code is:
private class myAsync extends AsyncTask<Void, Integer, Void> {
int duration = 0;
//int current = 0;
#Override
protected Void doInBackground(Void... params) {
videoView.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
progressDialog.dismiss();
videoView.seekTo(check);
videoView.start();
duration = videoView.getDuration();
}
});
do {
current = videoView.getCurrentPosition();
System.out.println("duration - " + duration + " current- "
+ current);
}
if (sync.isCancelled())
break;
} while (current != duration || current == 0);
return null;
}
}
i am using VideoView and seek bar but when i seekTo(..) on desired position through seekBar it play video from starting.
i trying this code:
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
mVideoView.seekTo(progress);
}
As Reno mentioned, you have to wait for the seeking to complete.
VideoView does not have a OnSeekCompleteListener() but you can access the MediaPlayer from the onPrepared method of the VideoView and then set the OnSeekCompleteListener, like this :
mVideoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnSeekCompleteListener(new OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mp) {
//TODO: Your code here
}
});
}
});
The call to VideoView.seekTo() is a wrapper around MediaPlayer.seekTo(). This function returns almost immediately even though the actual seeking is still being performed. Therefore you want to wait for seeking to complete via MediaPlayer.OnSeekCompleteListener.
However, as Reno mentioned, the standard VideoView does not support OnSeekCompleteListener.
But you can copy and locally customize the VideoView class to add this support yourself.
First, start with a copy of VideoView.java. Or you can clone the entire frameworks/base repo but warning it is over 1 gig of data to download.
Copy VideoView.java into your Eclipse Android project and it will start building but fail. Here's what I did to get it to compile:
Update the package statement to match your project.
Comment out the references to MetaData. The fix for this is on my todo list. These need to be replaced with calls to MediaMetadataRetriever.
Replace mContext with calls to getBaseContext()
Now you are ready to add the code for OnSeekCompleteListener. The implementation is similar to the other listeners, i.e OnCompletionListener.
public class VideoView extends SurfaceView
implements MediaPlayerControl {
// The client's listener which is the notification callback.
private OnSeekCompleteListener mOnSeekCompleteListener;
// Set up MediaPlayer to forward notifications to client.
private MediaPlayer.OnSeekCompleteListener mSeekCompleteListener =
new MediaPlayer.OnSeekCompleteListener() {
public void onSeekComplete(MediaPlayer mp) {
if (mOnCompletionListener != null) {
mOnCompletionListener.onCompletion(mMediaPlayer);
}
}
};
// API for client to set their listener.
public void setOnSeekCompleteListener(OnSeekCompleteListener l)
{
mOnSeekCompleteListener = l;
}
}
Finally, update your own code:
Update references to android.widget.VideoView to use your customized VideoView.
Implement a listener and set it via by calling setOnSeekCompleteListener().
Your code now receives notifications when the seek has really completed and it can then perform subsequent seeks.
You have to wait for the seeking to complete, unfortunately VideoView does not have a OnSeekCompleteListener() (why Google? -_-)
use my method works like charm
Take mediaPlayer
MediaPlayer mediaPlayer;
init mediaPlayer
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer = mp;
}
});
use seekTo method like this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mediaPlayer.seekTo((int) mStartPosition, MediaPlayer.SEEK_CLOSEST);
} else {
mediaPlayer.seekTo((int) mStartPosition);
}
You should use
mVideoView.seekTo(progress, SEEK_CLOSEST)
I have the following code to take a video as a raw resource, start the video and loop it but I need the video to loop seamlessly as of now when it comes to an end of the clip and starts the clip again the transition between causes a flicker for a split second, which I really can't have for my app.
public class Example extends Activity {
VideoView vv;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
vv = (VideoView)findViewById(R.id.VideoView01);
//Video Loop
vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
vv.start(); //need to make transition seamless.
}
});
Uri uri = Uri.parse("android.resource://com.example/"
+ R.raw.video);
vv.setVideoURI(uri);
vv.requestFocus();
vv.start();
}
}
The clip is only 22 seconds long but was created to be seamless so it is possible to work without the delay.
Try this it will work 100%
VideoView videoView;<---write this in outside of method or else declare it as final variable.
videoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setLooping(true);
}
});
In Kotlin simply use
videoView.setOnPreparedListener { it.isLooping = true }
Not sure if this helps years later, but I used
vv.start();
vv.setOnCompletionListener ( new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
vv.start();
}
});
and it has a seamless loop
The pause is for the underlying MediaPlayer to refresh its buffers. How long that will take will depend on a number of factors, many of which are outside your control (e.g., speed of CPU, speed of on-board flash storage).
One you can control is to get your video out of the resource and into the filesystem. Resources are stored in the APK, which is a ZIP file, so extracting the video this way probably takes extra time.
You may need to switch away from VideoView and use a SurfaceView with two MediaPlayers, alternating between them -- one is playing while the next is preparing, so when the playing one ends you can switch to the new player. I have not tried this, and so I do not know what the ramifications might be. However, I know that this technique is frequently used for audio playback to transition from one clip to another.
Little late, but any reason that you can't use the following?
MediaPlayer.setLooping(true);
If you are using Kotlin
videoView.setOnPreparedListener(object : MediaPlayer.OnPreparedListener {
override fun onPrepared(mp: MediaPlayer?) {
//Start Playback
videoView.start()
//Loop Video
mp!!.isLooping = true;
Log.i(TAG, "Video Started");
}
});
Using Arrow Expression short form
videoView.setOnPreparedListener { mp ->
//Start Playback
videoView.start()
//Loop Video
mp!!.isLooping = true;
Log.i(TAG, "Video Started");
};
Answer to this is to remove the audio from the video and convert that to a .ogg file which can be looped seamlessly and then use the video without audio to loop round and this works.
Here is answer friends, you must use vv.resume in setOnCompletionListener class
[https://stackoverflow.com/a/27606389/3414469][1]