web-dev-qa-db-fra.com

Comment définir l'aperçu de l'image en vidéo avant de jouer

J'ai créé une VideoView dans mon activité. Vous trouverez ci-dessous le code. 

VideoView vvVideos = (VideoView) rootView.findViewById(R.id.videoView);
MediaController mediacontroller = new MediaController(ctx);
mediacontroller.setAnchorView(vvVideos);
    Uri video = Uri.parse("Android.resource://" + packageName +"/"+R.raw.sample);
    vvVideos.setMediaController(mediacontroller);

    LayoutParams params=vvVideos.getLayoutParams();
    params.height=150;
    vvVideos.setLayoutParams(params);

    vvVideos.setVideoURI(video);
    vvVideos.requestFocus();
    vvVideos.setOnPreparedListener(new OnPreparedListener() {
        public void onPrepared(MediaPlayer mp) {
            vvVideos.start();
        }
    });

Maintenant, la vidéo commence à jouer lorsque l'activité est créée. Je veux faire mon activité comme suit 

  1. La vidéo ne devrait pas être lue lorsque l'activité est ouverte. 
  2. Il doit afficher l’image vidéo de départ (elle affiche actuellement la couleur noire) 
  3. Il ne devrait être lu que lorsque l'utilisateur clique sur la vidéo.
    Aidez-moi, s'il vous plaît.
45
Vignesh

Utilisez seekTo( 1 ) pour afficher la première image.

Assurez-vous que le film est en pause, puis utilisez seekTo() pour afficher la première image de la vidéo:

VideoView mVideoView = (VideoView) findViewById( R.id.video_preview );

mVideoView.setVideoURI( yourVideoPath );

mVideoView.seekTo( 1 );                 // 1 millisecond (0.001 s) into the clip.

REMARQUE: Nous utilisons .seekTo( 1 ) car le réglage de .seekTo( 0 ) ne fonctionnait pas sous Android 9.

Le faire jouer lorsque l'on clique dessus a été répondu par @Lingviston dans une autre réponse.

91
Joshua Pinter

Créer une vignette vidéo en utilisant ceci 

Bitmap thumb = ThumbnailUtils.createVideoThumbnail("file path/url",
                            MediaStore.Images.Thumbnails.MINI_KIND);

et mis à visionner

BitmapDrawable bitmapDrawable = new BitmapDrawable(thumb);
            mVideoView.setBackgroundDrawable(bitmapDrawable);
26
Shijil

il suffit de chercher une vidéo à 100 millisecondes, la miniature est affichée à l'aide de la méthode seekTo ()

videoView.seekTo(100);
6
saigopi

Vous pouvez le faire avec Glide 4.x. Il ira chercher la première image de votre vidéo et la montrera dans une ImageView

ajouter à votre build.gradle

compile 'com.github.bumptech.glide:glide:4.3.1'

et dans ta classe

GlideApp.with(context)
                .load("your video URL")
                .into(videoImageView);;
3
N.Droid

Je pensais partager ma solution. La méthode seekTo fonctionne très bien, mais uniquement pour certains périphériques. Voici mon travail autour. Je traite cela dans la méthode onPrepared pour le onPreparedListener mais c'est à vous de décider.

@Override
public void onPrepared(MediaPlayer mp) {
  MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
  mediaMetadataRetriever.setDataSource(uri.getPath());
  try {
    Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(currentPosition);
    videoView.setBackgroundDrawable(new BitmapDrawable(bitmap));
  } catch (OutOfMemoryError outOfMemoryError) {
    //Not entirely sure if this will ever be thrown but better safe than sorry.
    videoView.seekTo(currentPosition);
  }
}

Maintenant, lorsque vous lisez la vidéo, vous devez supprimer cette image d’arrière-plan de la manière suivante:

private void play() {
  ...
  videoView.setBackgroundDrawable(null);
  ..
}

Prendre plaisir!

3
DroidT

Je sais que c'est une vieille question, mais j'avais besoin de la même solution et ne pouvais trouver la réponse nulle part ailleurs, alors j'ai fait la solution et je partage l'amour ici:

Je viens de créer un petit cours pour ça:

   public class LoadFirstVideoFrame implements Runnable {

      private static Handler uiHandler = new Handler(Looper.getMainLooper());
      private VideoView videoView;

      private LoadFirstVideoFrame(VideoView videoView) {
         this.videoView = videoView;
         videoView.start();
         videoView.resume();
         uiHandler.post(this);
      }

      public void stop() {
         videoView = null;
         uiHandler.removeCallbacks(this);
      }

      @Override public void run() {
         if (videoView == null) return;
         if (videoView.isPlaying()) {
            videoView.pause();  
            videoView.seekTo(0);

            videoView = null;
         } else {
            uiHandler.post(this);
         }
      }
   }

il demande simplement de commencer à jouer et met la vidéo en pause sur la première image dès qu'elle est en cours de lecture (ce qui signifie que le fichier a été chargé et qu'il est déjà affiché sur SurfaceView).

La note importante ici est de rappeler d’appeler stop() sur cette classe afin qu’elle puisse nettoyer correctement et éviter toute fuite de mémoire.

J'espère que ça aide.

2
Budius

Vous pouvez utiliser la réponse de @Joshua Pinter pour résoudre le problème. Mais je veux vous donner plus de suggestions à ce sujet. Vous répondez vous-même que seekTo(100) fonctionne au lieu de seekTo(1). Aucune des deux manières n'est parfaite. En effet, seekTo(1) obtiendrait une image en noir et seekTo(100) aurait une exception. 

Je préfère faire comme ça: 

// calculate the during time of the media

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
long time = mediaPlayer.getDuration();

// use a proper number
mVideoView.seekTo(time/2);

Si vous n'avez pas le serveur principal, cela pourrait être mieux. Ou, si vous aviez un serveur principal, vous pouvez l'essayer de cette façon.

La vignette est calculée par le serveur, le client n'affiche que l'image à laquelle répond le backend. Et quand il s'agit du côté serveur, vous pouvez faire beaucoup de choses. 

  • Quelle image est la meilleure? Et si la photo est noire aussi?
  • Le serveur doit-il le générer? Ou le côté serveur doit-il simplement mettre en cache l'image du support?

Si vous souhaitez discuter davantage des deux questions, nous pourrons en discuter plus tard.

0
blackdog

J'ai créé un ImageView pour une vignette comme celle-ci

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@color/white"
    Android:clickable="true"
    Android:focusable="true">

 <VideoView
    Android:id="@+id/video_view"
    Android:layout_width="match_parent"
    Android:layout_height="220dp"/>
<ImageView
    Android:id="@+id/videoView_thumbnail"
    Android:layout_width="match_parent"
    Android:layout_height="220dp"
    Android:scaleType="centerCrop"/>

</RelativeLayout>

Et ajouter setOnPreparedListener et setOnCompletionListener en Java comme ceci

  VideoView videoView = (VideoView) view.findViewById(R.id.video_view);
  ImageView thumbnailView=(ImageView)view.findViewById(R.id.videoView_thumbnail);

  Glide.with(getApplicationContext()).load(your_Image_Path).into(thumbnailView);
 //you can add progress dialog here until video is start playing;

    mediaController= new MediaController(getContext());
    mediaController.setAnchorView(videoView);
    videoView.setMediaController(mediaController);
    videoView.setKeepScreenOn(true);
    videoView.setVideoPath(your_video_path);
    videoView.start();         //call this method for auto playing video

    videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {
            thumbnailView.setVisibility(View.GONE);
 //you can Hide progress dialog here when video is start playing;

        }
    });
    videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            videoView.stopPlayback();
            thumbnailView.setVisibility(View.VISIBLE);

        }
    });

Cela fonctionne très bien pour moi, j'espère que c'est utile pour tous

0
Dilip Sonigra