android 无缝连续播放视频

android 无缝连续播放视频

最近在做视频合成的时候要求把用户选择的视频能够连续预览,第一想的是用户在预览的时候把视频拼接后在预览,结果发现拼接的时间太久了,这种方式不行,结果搞了一天用mediaplayer多少个视频生成多少个mediaplayer然后预备起,这样就可以无缝播放视频了。

看图说话
在这里插入图片描述

下面是代码 话不多说


public class VideoPreviewView extends SurfaceView implements  MediaPlayerWrapper.IMediaCallback,SurfaceHolder.Callback {
    private MediaPlayerWrapper mMediaPlayer;

    /**视频播放状态的回调*/
    private MediaPlayerWrapper.IMediaCallback callback;

    public VideoPreviewView(Context context) {
        this(context,null);
    }

    public VideoPreviewView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }


    private void init(Context context) {
        mMediaPlayer = new MediaPlayerWrapper();
        mMediaPlayer.setOnCompletionListener(this);
        getHolder().addCallback(this);
    }

    /**设置视频的播放地址*/
    public void setVideoPath(List<String> paths){
        mMediaPlayer.setDataSource(paths);
    }
	

    /**是否循环播放*/
    public void setLooping(boolean isLooping) {
        mMediaPlayer.setLooping(isLooping);
    }

    public void play(){
        mMediaPlayer.play();
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Surface surface = holder.getSurface();
        mMediaPlayer.setSurface(surface);
        try {
            mMediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
     //   mMediaPlayer.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    public void onDestroy(){
        if (mMediaPlayer != null) {
            if(mMediaPlayer.isPlaying()){
                mMediaPlayer.stop();
            }
            mMediaPlayer.release();
        }
    }
    public void onTouch(final MotionEvent event){

    }


    @Override
    public void onVideoPrepare() {
        if (callback!= null){
            callback.onVideoPrepare();
        }
    }

    @Override
    public void onVideoStart() {
        if(callback!=null){
            callback.onVideoStart();
        }
    }
	
    public int getVideoWidth(){
        return mMediaPlayer.getVideoWidth();
    }

    public int getVideoHeight(){
        return mMediaPlayer.getVideoHeight();
    }


    @Override
    public void onVideoPause() {
        if (callback != null){
            callback.onVideoPause();
        }
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        if (callback != null){
            callback.onCompletion(mp);
        }
    }


    @Override
    public void onVideoChanged(final VideoInfo info) {
        if(callback!=null){
            callback.onVideoChanged(info);
        }
    }
    /**
     * isPlaying now
     * */
    public boolean isPlaying(){
        return mMediaPlayer.isPlaying();
    }
    /**
     * pause play
     * */
    public void pause(){
        if (mMediaPlayer != null) {
            mMediaPlayer.pause();
        }
    }

    /**
     * start play video
     * */
    public void setVolume(float leftVolume, float rightVolume){
        mMediaPlayer.setVolume(leftVolume);
    }

    /**
     * start play video
     * */
    public void start(){
        mMediaPlayer.start();
    }

	

    /**
     * 跳转到指定的时间点
     * */
    public void seekTo(int time) {
        mMediaPlayer.seekTo(time);
    }

    /**
     * 获取视频的长度
     * */
    public int getVideoDuration(){
        return mMediaPlayer.getVideoDuration();
    }

	

    /**
     * 获取当前视频的长度
     * */
    public int getCurPosition(){
        return mMediaPlayer.getCurPosition();
    }

    public void setIMediaCallback(MediaPlayerWrapper.IMediaCallback callback){
        this.callback=callback;
    }



}

下面是播放控制器


/**
 * Created by Administrator on 2020/6/29 0029.
 * desc:MediaPlayer的代理类 支持循环播放多个视频
 */

public class MediaPlayerWrapper implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener {
    private MediaPlayer mCurMediaPlayer;    //current player
    private List<MediaPlayer> mPlayerList;  //player list
    private List<String> mSrcList;          //video src list
    private List<VideoInfo> mInfoList;      //video info list
    private Surface surface;
    private IMediaCallback mCallback;
    private int curIndex;                   //current player index

    public MediaPlayerWrapper() {
        mPlayerList = new ArrayList<>();
        mInfoList = new ArrayList<>();
    }

    public void setOnCompletionListener(IMediaCallback callback) {
        this.mCallback = callback;
    }

    /**
     * 设置播放源
     *
     * @param dataSource
     */
    public void setDataSource(List<String> dataSource) {
        this.mSrcList = dataSource;
        MediaMetadataRetriever retr = new MediaMetadataRetriever();
        for (int i = 0; i < dataSource.size(); i++) {
            VideoInfo info = new VideoInfo();
            String path = dataSource.get(i);
            retr.setDataSource(path);
            String rotation = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
            String width = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
            String height = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
            String duration = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);

            info.path = path;
            try {
                info.rotation = Integer.parseInt(rotation);
                info.width = Integer.parseInt(width);
                info.height = Integer.parseInt(height);
                info.duration = Integer.parseInt(duration);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            } finally {
                mInfoList.add(info);
            }
        }
    }

    public List<VideoInfo> getVideoInfo() {
        return mInfoList;
    }

    public void setSurface(Surface surface) {
        this.surface = surface;
    }

    public void prepare() throws IOException {
        for (int i = 0; i < mSrcList.size(); i++) {
            MediaPlayer player = new MediaPlayer();
            player.setAudioStreamType(AudioManager.STREAM_MUSIC);
            player.setOnCompletionListener(this);
            player.setOnErrorListener(this);
            player.setOnPreparedListener(this);
            player.setDataSource(mSrcList.get(i));
            player.prepare();
            mPlayerList.add(player);
            if (i == 0) {
                mCurMediaPlayer = player;
                if (mCallback != null) {
                    mCallback.onVideoChanged(mInfoList.get(0));
                }
            }
        }

    }

    public VideoInfo getPlayInfo() {
        return mInfoList.get(curIndex);
    }

    public void play() {
        mCurMediaPlayer.start();
    }

    public void start() {
        if (surface.isValid()) {
            mCurMediaPlayer.setSurface(surface);
            mCurMediaPlayer.start();
            if (mCallback != null) {
                mCallback.onVideoStart();
            }
        }

    }

    public void setLooping(boolean isLooping) {
        mCurMediaPlayer.setLooping(isLooping);
    }


    public void setSpeed(int speed) {
        if (AndroidUtil.isMarshMallowOrLater()) {
            PlaybackParams playbackParams = mCurMediaPlayer.getPlaybackParams();
            playbackParams.setSpeed(speed);
            mCurMediaPlayer.setPlaybackParams(playbackParams);
        } else {
            ToastUtils.showToast("手机版本过低,暂不支持倍速播放预览");
        }
    }

    public void pause() {
        if (mCurMediaPlayer != null) {
            mCurMediaPlayer.pause();
            if (mCallback != null) {
                mCallback.onVideoPause();
            }
        }
    }



    public int getVideoDuration() {
        if (mSrcList.size() == 0) {
            throw new IllegalStateException("please set video src first");
        }
        int duration = 0;
        for (int i = 0; i < mSrcList.size(); i++) {
            duration += mInfoList.get(i).duration;
        }
        return duration;
    }

    public int getCurPosition() {
        int position = 0;
        for (int i = 0; i < curIndex; i++) {
            position += mInfoList.get(i).duration;
        }
        position += mCurMediaPlayer.getCurrentPosition();
        return position;
    }

    public int getVideoWidth() {
        return mCurMediaPlayer.getVideoWidth();
    }

    public int getVideoHeight() {
        return mCurMediaPlayer.getVideoHeight();
    }


    public void seekTo(int time) {
        int posTime = 0;
        for (int i = 0; i < mInfoList.size(); i++) {
            VideoInfo mVideoInfo = mInfoList.get(i);
            if (mVideoInfo.duration + posTime > time) {
                curIndex = i;
                if (mPlayerList.get(curIndex) != mCurMediaPlayer) {
                    mCurMediaPlayer.pause();
                }
                switchPlayer(mCurMediaPlayer);
                mCurMediaPlayer.seekTo(time - posTime);
                break;
            }
            posTime += mVideoInfo.duration;
        }
    }

   

    public boolean isPlaying() {
        if (mCurMediaPlayer != null) {
            return mCurMediaPlayer.isPlaying();
        } else {
            return false;
        }
    }


    @Override
    public void onCompletion(MediaPlayer mp) {
        curIndex++;
        if (curIndex >= mSrcList.size()) {
            curIndex = 0;
            if (mCallback != null) {
                mCallback.onCompletion(mp);
            }
        }
        if (mSrcList.size() >= 2) {
            switchPlayer(mp);
            mCurMediaPlayer.seekTo(0);
        }
    }

    private void switchPlayer(MediaPlayer mp) {
        mp.setSurface(null);
        if (mCallback != null) {
            mCallback.onVideoChanged(mInfoList.get(curIndex));
        }
        mCurMediaPlayer = mPlayerList.get(curIndex);
        mCurMediaPlayer.setSurface(surface);
        mCurMediaPlayer.start();

    }

    public void stop() {
        mCurMediaPlayer.stop();
    }

    public void release() {
        for (int i = 0; i < mPlayerList.size(); i++) {
            mPlayerList.get(i).release();
        }
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        return false;
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        if (mCallback != null) {
            mCallback.onVideoPrepare();
        }
    }

    public void setVolume(float volume) {
        for (int i = 0; i < mPlayerList.size(); i++) {
            MediaPlayer mediaPlayer = mPlayerList.get(i);
            mediaPlayer.setVolume(volume, volume);
        }
    }

    public int[] getVideoWH() {
        int[] ints = new int[2];
        int videoWidth = mCurMediaPlayer.getVideoWidth();
        int videoHeight = mCurMediaPlayer.getVideoHeight();
        ints[0] = videoWidth;
        ints[1] = videoHeight;
        return ints;
    }

    public interface IMediaCallback {
        /**
         * callback when all the player prepared
         */
        void onVideoPrepare();

        /**
         * callback when player start
         */
        void onVideoStart();

        /**
         * callback when player pause
         */
        void onVideoPause();

        /**
         * callback when all the videos have been played
         *
         * @param mp
         */
        void onCompletion(MediaPlayer mp);

        /**
         * callback when video changed
         *
         * @param info
         */
        void onVideoChanged(VideoInfo info);
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值