Как установить изображение для предварительного просмотра в видеопросмотре перед воспроизведением

Я создал VideoView в своей деятельности, код ниже.

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();
        }
    });

Теперь видео начинает воспроизводиться, когда создается действие. Я хочу вести свою деятельность следующим образом

  1. Видео не должно воспроизводиться при открытии занятия.
  2. Он должен отображать начальное видеоизображение (в настоящее время отображается черный цвет)
  3. Он должен воспроизводиться только тогда, когда пользователь нажимает на видео.
    Пожалуйста, помогите мне.

person Vignesh    schedule 13.06.2013    source источник


Ответы (12)


Используйте seekTo( 1 ), чтобы показать первый кадр.

Убедитесь, что фильм приостановлен, а затем используйте seekTo(), чтобы показать первый кадр видео:

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

mVideoView.setVideoURI( yourVideoPath );

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

ПРИМЕЧАНИЕ. Мы используем .seekTo( 1 ), потому что настройка .seekTo( 0 ) не работает на Android 9.

Чтобы включить воспроизведение при нажатии, @Lingviston ответил в другом ответе.

person Joshua Pinter    schedule 15.03.2014
comment
спасибо, чувак, ты спас мне день! кстати, вызов mVideoView.seekTo(0); имеет тот же результат загрузки первого кадра - person Guillaume; 23.04.2014
comment
@snayde Спасибо за внимание, еще не пробовал на 5. - person Joshua Pinter; 16.03.2015
comment
не работает и на моем Nexus 5 ... все еще ищу решение без использования MediaPlayer и textureview - person Lion789; 08.05.2015
comment
Работает на Panasonic CM1 с Android 5. Похоже, это зависит от стандартного видеоплеера, установленного на устройстве. - person OneWorld; 22.03.2016
comment
Он работает и на Android 5, если вы зайдете в настройки разработчика и установите медиаплеер на AwesomePlayer (старый). Это не производственное исправление (очевидно), но оно проясняет, в чем проблема. - person Lukas Knuth; 27.09.2016
comment
Android 9 здесь. .seekTo(0); у меня не сработало, но .seekTo(100); помогло. Спасибо! - person rjr-apps; 30.10.2018
comment
@ nope4561759 Спасибо за подтверждение! Можете ли вы попробовать использовать .seekTo(10) и .seekTo(1), чтобы проверить, работают ли они? Спасибо! - person Joshua Pinter; 30.10.2018
comment
Я могу подтвердить, что и .seekTo(1), и seekTo(10) работали нормально. - person rjr-apps; 31.10.2018
comment
@ nope4561759 Отлично сделано! Очень признателен, что вы это подтвердили. Я собираюсь обновить свой ответ, чтобы отразить .seekTo(1), потому что я думаю, что большинство людей хотели бы сделать это. - person Joshua Pinter; 31.10.2018
comment
такая же проблема для moto g / android 5.1. работает с awesomeplayer. Раздражающий - person unludo; 04.11.2018

Создайте миниатюру видео с помощью этого

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

и установите для просмотра видео

BitmapDrawable bitmapDrawable = new BitmapDrawable(thumb);
            mVideoView.setBackgroundDrawable(bitmapDrawable);
person Shijil    schedule 24.07.2014
comment
setBakgroundDrawable устарел - person Apurva; 03.08.2015
comment
Превосходно. Работает потрясающе, и, учитывая его декодирование видео, относительно быстро. Я использовал дополнительный ImageView в том же макете, что и видео, поскольку setBakgroundDrawable не подходит для VideoView. - person Iman Akbari; 18.11.2015
comment
Вместо этого @Apurva user setBackground (Drawable background). - person Ashraf Alshahawy; 24.12.2015

1) Удалите файл onPrepareListener. Я не знаю, почему ваше видео начинает воспроизводиться после создания действия, но onPrepareListener вызывается после videoView.start ().

2) Добавьте виджет ImageView в макет поверх VideoView. Затем установите еще один onPrepareListener следующим образом:

vvVideos.setOnPreparedListener(new OnPreparedListener() {
            public void onPrepared(MediaPlayer mp) {
                previewImage.setVisibility(View.GONE);
            }
        });

Я заметил, что onPreparedListener срабатывает слишком рано, поэтому вы можете использовать

new Handler().postDelay(Runnable, timeInMilis)

чтобы закрыть изображение предварительного просмотра.

3) Добавьте OnTouchListener с любым обнаружением жестов к вашему VideoView. Вот пример того, что я использую сейчас:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_video);

    mGestureDetector = new GestureDetector(this, mGestureListener);

    ((VideoView) findViewById(R.id.activity_video_videoview)).setOnTouchListener(mTouchListener);
}
    private OnTouchListener mTouchListener = new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mGestureDetector.onTouchEvent(event);
        return true;
    }
};
private SimpleOnGestureListener mGestureListener = new SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
    if(mVideoView.isPlaying())
        mVideoView.pause();
    else
        mVideoView.start();
    return true;
};
};

Запускает / останавливает воспроизведение по касанию.

person Lingviston    schedule 14.06.2013
comment
Спасибо @Lingviston, еще одна помощь. Я не хочу отображать некоторые изображения поверх видео. Мне нужно отобразить начальное изображение видео. В настоящее время отображается как черный цвет. - person Vignesh; 17.06.2013
comment
Попробуйте использовать seekTo () с любым небольшим значением, например 100-200. - person Lingviston; 17.06.2013
comment
После использования жеста мой медиконтроллер не работает при нажатии на видео .... - person Vignesh; 17.06.2013

просто ищите видео до 100 миллисекунд, он показывает миниатюру с помощью метода seekTo ()

videoView.seekTo(100);
person Sai Gopi Me    schedule 12.11.2017

Вы можете сделать это с помощью Glide 4.x. Он получит первый кадр вашего видео и покажет его в ImageView

добавить в свой build.gradle

implementation 'com.github.bumptech.glide:glide:4.x.x'

и в вашем классе

GlideApp.with(context)
                .load("your video URL")
                .into(videoImageView);;
person N.Droid    schedule 25.11.2017
comment
как мы можем добавить кнопку Play, если файл видео в золоте, я не хочу играть. - person Uday Nayak; 18.11.2019

Думал поделиться своим решением. Метод seekTo отлично работает, но только для некоторых устройств. Вот моя работа. Я обрабатываю это в методе onPrepared для onPreparedListener, но решать вам.

@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);
  }
}

Теперь, когда вы воспроизводите видео, вам нужно будет удалить это фоновое изображение следующим образом:

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

Наслаждаться!

person DroidT    schedule 12.04.2016
comment
Похоже, это не работает для онлайн-видеопотока, источником данных должен быть локальный файл. В противном случае возникнет исключение IllegalArgumentException. - person cmoaciopm; 17.08.2016
comment
если кто-то вроде меня находится в глубоком поиске (ищет, почему seekTo не работает ранее) и закончил здесь, это не сработает. - person kolboc; 23.01.2018

Я знаю, что это старый вопрос, но мне нужно было такое же решение, и я не мог найти ответа в другом месте, поэтому я нашел решение и разделяю его любовь здесь:

Я только что создал для него небольшой класс:

   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);
         }
      }
   }

он просто просит начать воспроизведение и снова приостанавливает воспроизведение первого кадра, как только оно фактически воспроизводится (то есть загружает файл и уже отображает его на SurfaceView).

Важное замечание: не забудьте вызвать stop() для этого класса, чтобы он мог правильно очистить и не допустить утечки памяти.

Я надеюсь, что это помогает.

person Budius    schedule 20.07.2015
comment
videoView.pause () должен произойти перед поиском - person Łukasz Wiśniewski; 22.07.2015
comment
@ ŁukaszWiśniewski Я это тестировал, и он работал нормально. Вы обнаружили какие-либо проблемы с этим кодом? - person Budius; 23.07.2015
comment
Когда звонить stop @Budius? - person Shajeel Afzal; 26.08.2015
comment
Недостатком этого метода является то, что он воспроизводит видео в течение нескольких миллисекунд. - person Shajeel Afzal; 26.08.2015
comment
@ShajeelAfzal 'onStop ()' вашей активности или фрагмента - person Budius; 26.08.2015
comment
@Budius отлично показывает миниатюру, но когда я воспроизводю видео, он не показывает воспроизведение видео, однако я слышу звук видео. - person Shajeel Afzal; 26.08.2015

Я создал ImageView для подобного эскиза

<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>

И добавьте setOnPreparedListener и setOnCompletionListener в Java, как это

  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);

        }
    });

Это работает для меня очень хорошо, я надеюсь, что он полезен для всех

person Dilip Sonigra    schedule 26.12.2018

очень простой !!! вы можете использовать библиотеку скольжения.

сначала добавьте imageView в videoView и используйте приведенный ниже код:

   GlideApp.with(getApplicationContext()).load("empty")
        .thumbnail(GlideApp.with(getApplicationContext()).load("videoURL"))
        .into(imageView);

этот код загрузит изображение и, в конечном итоге, приведет к меньшему потреблению интернета.

person farhad mohammadi    schedule 29.04.2020

Вы можете использовать ответ @Joshua Pinter, чтобы решить проблему. Но я хочу дать вам больше советов по этому поводу. Вы сами отвечаете, что seekTo(100) работает вместо seekTo(1). Ни один из двух способов не идеален. Это потому, что seekTo(1) получит черное изображение, а seekTo(100) может получить исключение.

Я предпочитаю поступать так:

// 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);

Если у вас нет внутреннего сервера, это может быть лучше. Или, если у вас есть внутренний сервер, вы можете попробовать его таким же образом.

Миниатюра вычисляется сервером, клиент просто отображает изображение, на которое отвечает серверная часть. А когда дело доходит до серверной части, вы можете многое сделать.

  • Какая картинка лучше? Что делать, если картинка тоже черная?
  • Должна ли его генерировать сторона сервера? Или серверная сторона должна просто кэшировать изображение мультимедиа?

Если вы хотите подробнее обсудить эти два вопроса, мы можем обсудить их позже.

person blackdog    schedule 26.12.2018

Добавьте это в свой xml

    `<RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/dimen180"
            android:background="@color/color_bg">

            <com.google.android.exoplayer2.ui.PlayerView
                android:id="@+id/epPlayer"
                android:layout_width="match_parent"
                android:visibility="gone"
                android:layout_height="match_parent"/>

            <FrameLayout
                android:id="@+id/flTv"
                android:layout_width="match_parent"
                android:background="@color/color_bg"
                android:layout_height="match_parent">
                <androidx.appcompat.widget.AppCompatImageView
                    android:id="@+id/ivTv"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@drawable/tv"/>
            </FrameLayout>




            <ProgressBar
                android:id="@+id/pbVideoView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:layout_centerInParent="true"
                android:indeterminate="true" />
        </RelativeLayout>

`для пользователей котлина

объявить переменную

private var simpleExoPlayer: ExoPlayer? = null

использовать этот

  simpleExoPlayer = SimpleExoPlayer.Builder(this).build()
    epPlayer.player = simpleExoPlayer
    val dataSourceFactory = DefaultDataSourceFactory(
        this,
        Util.getUserAgent(this, getString(R.string.app_name))
    )
    val videoSource = ProgressiveMediaSource.Factory(dataSourceFactory)
                    .createMediaSource(Uri.parse(it1))
                simpleExoPlayer!!.prepare(videoSource)
                simpleExoPlayer!!.playWhenReady = true
                simpleExoPlayer!!.addListener(object : Player.EventListener{
                    override fun onPlayerStateChanged(
                        playWhenReady: Boolean,
                        playbackState: Int
                    ) {
                        if(playbackState== Player.STATE_READY)
                        {
                            pbVideoView.visibility= View.GONE
                            epPlayer.visibility= View.VISIBLE
                            flTv.visibility= View.GONE
                        }
                        if (playbackState== Player.STATE_BUFFERING)
                        {
                            pbVideoView.visibility= View.VISIBLE
                        }
                    }
                })

Я надеюсь, что это помогает.

person Prat137    schedule 09.01.2020

Чтобы ваше видео перестало воспроизводиться, когда начинается действие, просто удалите метод video.start().

person David Joel Lukombo    schedule 07.08.2018