web-dev-qa-db-ja.com

再生前にビデオビューでプレビュー画像を設定する方法

アクティビティで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. ユーザーがビデオをクリックしたときにのみ再生する必要があります。
    私を助けてください。
53
Vignesh

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 )の設定はAndroid 9。では機能しなかったため、.seekTo( 0 )を使用します。

クリックされたときに再生するには、別の回答で@Lingvistonが回答しています。

98
Joshua Pinter

これを使用してビデオのサムネイルを作成します

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

そして、videoviewに設定します

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

1)onPrepareListenerを削除します。アクティビティの作成後に動画の再生が開始される理由はわかりませんが、onViewpareListenerはvideoView.start()の後に呼び出されます。

2)VideoViewの上にあるレイアウトにImageViewウィジェットを追加します。次に、次のように別の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;
};
};
_

タップで再生を開始/停止します。

9
Lingviston

ビデオを100ミリ秒までシークするだけで、seekTo()メソッドを使用してサムネイルを表示します。

videoView.seekTo(100);
6
saigopi

Glide 4.xでできます。ビデオの最初のフレームを取得し、ImageViewで表示します

build.gradleに追加します

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

そしてあなたのクラスで

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

私のソリューションを共有すると思いました。 seekToメソッドはうまく機能しますが、一部のデバイスでのみ機能します。これが私の回避策です。これはonPreparedListenerのonPreparedメソッドで処理しますが、それはあなた次第です。

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

楽しい!

3
DroidT

私はそれが古い質問であることを知っていますが、同じ解決策が必要であり、他のどこにも答えを見つけることができなかったので、解決策を行い、ここで愛を共有しています:

ちょっとしたクラスを作成しました。

_   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()を呼び出すことを忘れないでください。そうすれば、適切にクリーンアップでき、メモリリークは発生しません。

役に立てば幸いです。

2
Budius

このようなサムネイル用の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 Like This Wayに追加

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

        }
    });

それは私のために非常にうまく機能します

1
Dilip Sonigra

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

バックエンドサーバーがない場合は、より良い可能性があります。または、バックエンドサーバーがある場合は、この方法で試すことができます。

サムネイルはサーバーによって計算され、クライアントはバックエンドが応答する画像を表示するだけです。そして、サーバー側に来るとき、あなたは多くのことをすることができます。

  • どちらの写真が良いですか?絵も黒い場合はどうなりますか?
  • サーバー側で生成する必要がありますか?または、サーバー側はメディアの画像をキャッシュするだけですか?

2つの質問について詳しく話したい場合は、後で説明します。

0
blackdog