zoukankan      html  css  js  c++  java
  • android 视频开发2分之2(仿美拍,糗百)

    上一篇写了分段录制和合并视频。这一篇则是选择视频,然后截断视频。

    1、从sdcard中找到视频资源;
    2、分析视频,拿到你须要的帧数当你的图片。(我的是依据參数来算的多少秒1帧的图片,通常是1秒1帧来显示图片)
    3、给个 可拉动 控件来选择截断区域 。

    (我的是基本參数是最少5秒。最大15秒。如需改动。仅仅需改(MIN_TIME,MAX_TIME)这2个參数则以)

    先上图:
    视频选择界面
    视频切断界面

    咱们来看代码。首先是选择视频的:

    package com.example.shipin;
    
    import java.util.ArrayList;
    
    import android.annotation.SuppressLint;
    import android.content.ContentResolver;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.media.ThumbnailUtils;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.provider.MediaStore;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.BaseAdapter;
    import android.widget.GridView;
    import android.widget.ImageView;
    import android.widget.RelativeLayout.LayoutParams;
    import android.widget.TextView;
    
    public class VideoNewSelectActivity extends BaseActivity {
        /** 图片展示器 */
        private GridView gridview;
        /** 图片适配器 */
        private ViewNewSelectAdapter adapter;
        /** 数据集 */
        private ArrayList<ViewNewSelectBean> list;
    
        private ImageView img_back;
    
        /** 显示图片的宽 */
        private int width;
    
        @Override
        protected int getContentViewId() {
            return R.layout.activity_video_new_select;
        }
    
        @SuppressWarnings("deprecation")
        @Override
        protected void findViews() {
            img_back = (ImageView) findViewById(R.id.video_new_img_back);
            gridview = (GridView) findViewById(R.id.video_new_select_gridview);
    
            width = (getWindowManager().getDefaultDisplay().getWidth() - DisplayUtil.dip2px(VideoNewSelectActivity.this, 60)) / 3;
        }
    
        @Override
        protected void init() {
            list = new ArrayList<ViewNewSelectBean>();
            adapter = new ViewNewSelectAdapter(list, width, VideoNewSelectActivity.this);
            gridview.setAdapter(adapter);
    
            getList();
        }
    
        @Override
        protected void widgetListener() {
            img_back.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
    
            gridview.setOnItemClickListener(new OnItemClickListener() {
    
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Bundle bundle = new Bundle();
                    bundle.putSerializable("serializable", list.get(position));
                    Intent intent = new Intent(VideoNewSelectActivity.this, VideoNewCutActivity.class);
                    intent.putExtras(bundle);
                    startActivity(intent);
                }
            });
        }
    
        private Handler handler = new Handler() {
            public void handleMessage(android.os.Message msg) {
                if (msg.what == 1) {
                    adapter.notifyDataSetChanged();
                }
            };
        };
    
        /**
         * 获取数据
         *
         * @version 1.0
         * @createTime 2015年6月16日,下午6:14:09
         * @updateTime 2015年6月16日,下午6:14:09
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         */
        private void getList() {
            new Thread(new Runnable() {
    
                @Override
                public void run() {
                    // 若为图片则为MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    Uri originalUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    ContentResolver cr = getContentResolver();
                    Cursor cursor = cr.query(originalUri, null, null, null, null);
                    if (cursor == null) {
                        return;
                    }
                    while (cursor.moveToNext()) {
                        ViewNewSelectBean bean = new ViewNewSelectBean();
                        bean.set_id(cursor.getLong(cursor.getColumnIndex("_ID")));
                        bean.setName(cursor.getString(cursor.getColumnIndex("_display_name")));// 视频名字
                        bean.setPath(cursor.getString(cursor.getColumnIndex("_data")));// 路径
                        bean.setWidth(cursor.getInt(cursor.getColumnIndex("width")));// 视频宽
                        bean.setHeight(cursor.getInt(cursor.getColumnIndex("height")));// 视频高
                        bean.setDuration(cursor.getLong(cursor.getColumnIndex("duration")));// 时长
                        list.add(bean);
    
                    }
    
                    Message message = handler.obtainMessage();
                    message.what = 1;
                    handler.sendMessage(message);
    
                    // /data/data/com.android.providers.media/databases/external.db
                    // {5dd10730} 数据库位置
                }
            }).start();
        }
    
        private class ViewNewSelectAdapter extends BaseAdapter {
            private Context context;
            /** 数据集 */
            private ArrayList<ViewNewSelectBean> list;
            /** 图片宽 */
            private int width;
    
            public ViewNewSelectAdapter(ArrayList<ViewNewSelectBean> list, int width, Context context) {
                this.list = list;
                this.width = width;
                this.context = context;
            }
    
            @Override
            public int getCount() {
                return list.size();
            }
    
            @Override
            public Object getItem(int position) {
                return list.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @SuppressLint("InflateParams")
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                final ViewHolder viewHolder;
                final ViewNewSelectBean bean = list.get(position);
                if (convertView == null) {
                    viewHolder = new ViewHolder();
                    convertView = LayoutInflater.from(context).inflate(R.layout.item_video_new_select_gridview, null);
                    viewHolder.txt = (TextView) convertView.findViewById(R.id.item_video_new_select_txt_time);
                    viewHolder.img = (ImageView) convertView.findViewById(R.id.item_video_new_select_img);
                    convertView.setTag(viewHolder);
                } else {
                    viewHolder = (ViewHolder) convertView.getTag();
                }
    
                LayoutParams layoutParams = (LayoutParams) viewHolder.img.getLayoutParams();
                layoutParams.width = width;
                layoutParams.height = width;
                viewHolder.img.setLayoutParams(layoutParams);
                // 获取图片
                Bitmap bitmap = getVideoThumbnail(bean.getPath(), width, width, MediaStore.Images.Thumbnails.MICRO_KIND);
                if (bitmap != null) {
                    // 设置图片
                    viewHolder.img.setImageBitmap(bitmap);
                }
                // 设置时长
                viewHolder.txt.setText(String.format("时长:%1$s s", bean.getDuration() / 1000));
    
                return convertView;
            }
    
            /**
             * 获取视频的缩略图
             * 先通过ThumbnailUtils来创建一个视频的缩略图,然后再利用ThumbnailUtils来生成指定大小的缩略图。
             * 假设想要的缩略图的宽和高都小于MICRO_KIND,则类型要使用MICRO_KIND作为kind的值,这样会节省内存。

    * * @param videoPath * 视频的路径 * @param width * 指定输出视频缩略图的宽度 * @param height * 指定输出视频缩略图的高度度 * @param kind * 參照MediaStore.Images. * Thumbnails类中的常量MINI_KIND和MICRO_KIND。 * 当中,MINI_KIND: 512 x 384,MICRO_KIND: 96 x 96 * @return 指定大小的视频缩略图 */ private Bitmap getVideoThumbnail(String videoPath, int width, int height, int kind) { Bitmap bitmap = null; // 获取视频的缩略图 bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind); bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); return bitmap; } private class ViewHolder { private ImageView img; private TextView txt; } } }

    看到选择之后就到重点部分了,视频截断。首先得从上个activity拿到视频的数据bean,然后通过视频路径。分析视频,通过自己设置的须要多少帧一张的图片来进行取图片。取完图片则是通过android的新控件RecyclerView来进行显示,听说RecyclerView是Listview的升级版(支持横向和竖向)。我还须要他滚动的距离来进行计算切断的位置。RecyclerView貌似拿不到滚动距离,所以咱们得自己计算了(通过拿到当前滑到的position*view的宽度-view距左边的距离就得到滚动距离了)。还有个矩形框来进行拉动选择截断大小哦。好了咱们来看代码吧(代码凝视量还是比較大的,应该都懂,不懂留言给我一一解答):

    package com.example.shipin;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    
    import android.annotation.SuppressLint;
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.graphics.Bitmap.CompressFormat;
    import android.media.MediaMetadataRetriever;
    import android.media.MediaPlayer;
    import android.media.MediaPlayer.OnCompletionListener;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.widget.LinearLayoutManager;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnTouchListener;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.RelativeLayout.LayoutParams;
    import android.widget.VideoView;
    
    import com.example.shipin.MyRecyclerView.OnItemScrollChangeListener;
    import com.example.shipin.VideoNewCutAdapter.MyItemClickListener;
    
    public class VideoNewCutActivity extends BaseActivity {
        /**返回*/
        private ImageView img_back;
        /**确认*/
        private TextView txt_enter;
        /** 视频bean */
        private ViewNewSelectBean bean;
        /** 横向listview */
        private MyRecyclerView recyclerView;
        /** 封面图button */
        private ImageView img_bg;
        /** 阴影色块left */
        private ImageView img_left;
        /** 阴影色块right */
        private ImageView img_right;
        /** 显示时间 */
        private TextView txt_time;
        /** 封面容器 */
        private RelativeLayout relative;
        /** 进度条 */
        private RelativeLayout relative1;
        /** 视频播放 */
        private VideoView videoView;
        /** 数据集 */
        private ArrayList<String> list;
        /** 列表适配器 */
        private VideoNewCutAdapter adapter;
        /** 屏幕宽度 */
        private int width;
        /** 暂时保存文件路径 */
        private String savePath;
    
        /** 最少多少秒 */
        public static final int MIN_TIME = 5000;
        /** 最大多少秒 */
        public static final int MAX_TIME = 15000;
        /** 屏幕中1像素占有多少毫秒 */
        private float picture = 0;
        /** 多少秒一帧 */
        private float second_Z;
    
        /** 是否中断线性 */
        private boolean isThread = false;
    
        /** 左边拖动button */
        private Button txt_left;
        /** 右边拖动button */
        private Button txt_right;
    
        /** 按下时X抽坐标 */
        private float DownX;
    
        /** 拖动条容器 */
        private LayoutParams layoutParams_progress;
        /** 阴影背景容器 */
        private LayoutParams layoutParams_yin;
        /** 拖动条的宽度 */
        private int width_progress = 0;
        /** 拖动条的间距 */
        private int Margin_progress = 0;
        /** 阴影框的宽度 */
        private int width1_progress = 0;
    
        /** 不能超过右边多少 */
        private int right_margin = 0;
        /** 全部图片长度 */
        private int img_widthAll = 0;
        /** 最少保留的多少秒长度 */
        private int last_length = 0;
        /** 左边啦了多少 */
        private int left_lenth = 0;
        /** 滚动的长度 */
        private int Scroll_lenth = 0;
        /** 路径 */
        private String Ppath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videoTest/Image/";
    
        @Override
        protected int getContentViewId() {
            return R.layout.activity_video_new_cut;
        }
    
        @SuppressWarnings("deprecation")
        @Override
        protected void findViews() {
            img_back = (ImageView) findViewById(R.id.video_new_img_back);
            txt_enter = (TextView) findViewById(R.id.video_new_txt_enter);
            recyclerView = (MyRecyclerView) findViewById(R.id.recyclerview_horizontal);
            videoView = (VideoView) findViewById(R.id.video_new_cut_videoview);
            img_bg = (ImageView) findViewById(R.id.video_new_cut_img_bg);
            img_left = (ImageView) findViewById(R.id.video_new_cut_img_left);
            img_right = (ImageView) findViewById(R.id.video_new_cut_img_right);
            relative = (RelativeLayout) findViewById(R.id.video_new_cut_relative);
            txt_time = (TextView) findViewById(R.id.video_new_cut_txt_time);
            relative1 = (RelativeLayout) findViewById(R.id.video_new_cut_relative1);
    
            txt_left = (Button) findViewById(R.id.video_new_cut_txt_left);
            txt_right = (Button) findViewById(R.id.video_new_cut_txt_right);
    
            width = getWindowManager().getDefaultDisplay().getWidth();
    
            LayoutParams layoutParams = (LayoutParams) relative.getLayoutParams();
            layoutParams.width = width;
            layoutParams.height = width;
            relative.setLayoutParams(layoutParams);
    
            // 创建一个线性布局管理器
            LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
            // 设置布局管理器
            recyclerView.setLayoutManager(layoutManager);
    
            list = new ArrayList<String>();
            adapter = new VideoNewCutAdapter(list);
        }
    
        @Override
        protected void initGetData() {
            super.initGetData();
            if (getIntent().getExtras() != null) {
                bean = (ViewNewSelectBean) getIntent().getExtras().getSerializable("serializable");
            }
        }
    
        @Override
        protected void init() {
    
            // 创建目录
            File file = new File(Ppath);
            if (!file.exists()) {
                file.mkdir();
            }
    
            recyclerView.setAdapter(adapter);
    
            videoView.setVideoPath(bean.getPath());
            videoView.requestFocus();
    
            /** 一个屏幕1像素是多少毫秒 13.88888 */
            picture = (float) MAX_TIME / (float) width;
            /** 1.66666 */
            second_Z = (float) MAX_TIME / 1000f / ((float) width / (float) DisplayUtil.dip2px(VideoNewCutActivity.this, 60));
    
            getBitmapsFromVideo(bean.getPath(), (int) bean.getDuration());
        }
    
        private Handler handler = new Handler() {
            public void handleMessage(android.os.Message msg) {
                if (msg.what == 1) {
    
                    adapter.notifyItemInserted(msg.arg1);
    
                    if (msg.arg1 == 0) {
                        sendVideo(DisplayUtil.dip2px(VideoNewCutActivity.this, 60));
                    }
    
                } else if (msg.what == 2) {
    
                    img_widthAll = (int) (msg.arg1 * 1000 / picture);
    
                    last_length = (int) (MIN_TIME / picture);
    
                    if (img_widthAll < width) {
                        right_margin = width - img_widthAll;
                        LayoutParams layoutParams_right = (LayoutParams) img_right.getLayoutParams();
                        layoutParams_right.width = width - img_widthAll;
                        img_right.setLayoutParams(layoutParams_right);
    
                        layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                        layoutParams_progress.width = img_widthAll;
                        layoutParams_progress.rightMargin = width - img_widthAll;
                        relative1.setLayoutParams(layoutParams_progress);
    
                        txt_time.setText(msg.arg1 + ".0 s");
                    } else {
                        img_widthAll = width;
                        layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                        layoutParams_progress.width = width;
                        relative1.setLayoutParams(layoutParams_progress);
    
                        txt_time.setText((MAX_TIME / 1000) + ".0 s");
                    }
                } 
            };
        };
    
        /**
         * 获取视频帧图片
         *
         * @version 1.0
         * @createTime 2015年6月17日,上午11:49:54
         * @updateTime 2015年6月17日,上午11:49:54
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         * @param dataPath
         * @param lenth
         */
        public void getBitmapsFromVideo(final String dataPath, final int lenth) {
            new Thread(new Runnable() {
    
                @SuppressLint("NewApi")
                @Override
                public void run() {
                    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                    retriever.setDataSource(dataPath);
                    // 取得视频的长度(单位为秒)
                    int seconds = lenth / 1000;
    
                    Message message = handler.obtainMessage();
                    message.what = 2;
                    message.arg1 = seconds;
                    handler.sendMessage(message);
                    Bitmap bitmap;
                    // 得到每一秒时刻的bitmap比方第一秒,第二秒
                    int index = 0;
                    for (float f = second_Z; f <= (float) seconds; f += second_Z) {
    
                        if (isThread) {
                            return;
                        }
                        bitmap = retriever.getFrameAtTime((long) (f * 1000 * 1000), MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
    
                        String path = Ppath + System.currentTimeMillis() + ".jpg";
                        FileOutputStream fos = null;
                        try {
                            fos = new FileOutputStream(path);
                            bitmap.compress(CompressFormat.JPEG, 80, fos);
                            fos.close();
    
                            list.add(path);
                            Message message1 = handler.obtainMessage();
                            message1.what = 1;
                            message1.arg1 = index;
                            handler.sendMessage(message1);
                            index++;
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    
        @Override
        protected void widgetListener() {
            /** 列表点击事件 */
            adapter.setOnClickListener(new MyItemClickListener() {
    
                @Override
                public void onItemClick(View view, int position) {
                    sendVideo((position + 1) * view.getWidth());
                }
            });
            /** 返回 */
            img_back.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
    
            /** 完毕 */
            txt_enter.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    handler.post(runnable3);                
                }
            });
    
            /** 播放 */
            relative.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    if (videoView.isPlaying()) {
                        img_bg.setVisibility(View.VISIBLE);
                        videoView.pause();
    
                        handler.removeCallbacks(runnable);
    
                    } else {
                        videoView.setVisibility(View.VISIBLE);
                        img_bg.setVisibility(View.GONE);
                        videoView.start();
    
                        layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                        // 会误差 200-800毫秒
                        handler.postDelayed(runnable, (long) (layoutParams_progress.width * picture) + 500);
                    }
                }
            });
    
            /** 左边拖动button */
            txt_left.setOnTouchListener(new OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
    
                    switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        DownX = event.getRawX();
    
                        layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                        layoutParams_yin = (LayoutParams) img_left.getLayoutParams();
    
                        width_progress = layoutParams_progress.width;
                        Margin_progress = layoutParams_progress.leftMargin;
                        width1_progress = layoutParams_yin.width;
    
                        break;
                    case MotionEvent.ACTION_MOVE:
    
                        LeftMoveLayout(event.getRawX() - DownX, event.getRawX());
    
                        break;
                    case MotionEvent.ACTION_UP:
    
                        sendVideo();
    
                        layoutParams_progress = null;
                        layoutParams_yin = null;
    
                        break;
                    default:
                        break;
                    }
                    return false;
                }
            });
    
            /** 右边拖动button */
            txt_right.setOnTouchListener(new OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        DownX = event.getRawX();
    
                        layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                        layoutParams_yin = (LayoutParams) img_right.getLayoutParams();
    
                        width_progress = layoutParams_progress.width;
                        Margin_progress = layoutParams_progress.rightMargin;
                        width1_progress = layoutParams_yin.width;
    
                        break;
                    case MotionEvent.ACTION_MOVE:
    
                        RightMoveLayout(DownX - event.getRawX());
    
                        break;
                    case MotionEvent.ACTION_UP:
                        layoutParams_progress = null;
                        layoutParams_yin = null;
                        break;
    
                    default:
                        break;
                    }
                    return false;
                }
            });
            /** 视频播放完回调 */
            videoView.setOnCompletionListener(new OnCompletionListener() {
    
                @Override
                public void onCompletion(MediaPlayer mp) {
                    img_bg.setVisibility(View.VISIBLE);
                    handler.removeCallbacks(runnable);
                }
            });
    
            /** 滚动监听 */
            recyclerView.setOnItemScrollChangeListener(new OnItemScrollChangeListener() {
    
                @Override
                public void onChange(View view, int position) {
                    Scroll_lenth = position * view.getWidth() - view.getLeft();
    
                    if (Scroll_lenth <= 0) {
                        Scroll_lenth = 0;
                    }
    
    //               sendVideo();//打开凝视就是边滑动变更新视图
                }
    
                @Override
                public void onChangeState(int state) {
                    if (state == 0) {// 精巧情况时候才调用
                        sendVideo();
                    }
                }
            });
        }
    
        private Runnable runnable3 = new Runnable() {
    
            @Override
            public void run() {
                try {
                    layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
    
                    savePath = Ppath + System.currentTimeMillis() + ".mp4";
    
                    FUckTest.startTrim(new File(bean.getPath()), new File(savePath), (long) ((Scroll_lenth + left_lenth) * picture), (long) ((Scroll_lenth
                            + left_lenth + layoutParams_progress.width) * picture));
    
                    Intent it = new Intent(VideoNewCutActivity.this,VideoActivity.class);
                    it.putExtra("path", savePath);
                    startActivity(it);
    
                } catch (IOException e) {
    
                    e.printStackTrace();
                }
            }
        };
    
    
        /**
         * 向右边啦
         * 
         * @version 1.0
         * @createTime 2015年6月18日,上午9:44:32
         * @updateTime 2015年6月18日,上午9:44:32
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         * @param MoveX
         */
        private void LeftMoveLayout(float MoveX, float X) {
            if (layoutParams_progress != null && layoutParams_yin != null) {
                if (Margin_progress + (int) MoveX > 0 && width_progress - (int) MoveX > last_length) {
                    layoutParams_progress.width = width_progress - (int) MoveX;
                    layoutParams_progress.leftMargin = Margin_progress + (int) MoveX;
                    layoutParams_yin.width = width1_progress + (int) MoveX;
    
                    relative1.setLayoutParams(layoutParams_progress);
                    img_left.setLayoutParams(layoutParams_yin);
    
                    txt_time.setText((float) (Math.round((layoutParams_progress.width * picture / 1000) * 10)) / 10 + " s");
    
                    left_lenth = layoutParams_yin.width;
                }
            }
        }
    
        /**
         * 向左边拉
         *
         * @version 1.0
         * @createTime 2015年6月18日,上午9:45:16
         * @updateTime 2015年6月18日,上午9:45:16
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         * @param MoveX
         */
        private void RightMoveLayout(float MoveX) {
            if (layoutParams_progress != null && layoutParams_yin != null) {
                if (Margin_progress + (int) MoveX > right_margin && width_progress - (int) MoveX > last_length) {
                    layoutParams_progress.width = width_progress - (int) MoveX;
                    layoutParams_progress.rightMargin = Margin_progress + (int) MoveX;
                    layoutParams_yin.width = width1_progress + (int) MoveX;
    
                    txt_time.setText((float) (Math.round((layoutParams_progress.width * picture / 1000) * 10)) / 10 + " s");
    
                    relative1.setLayoutParams(layoutParams_progress);
                    img_right.setLayoutParams(layoutParams_yin);
                }
            }
        }
    
        private Runnable runnable = new Runnable() {
    
            @Override
            public void run() {
                if (!img_bg.isShown()) {
                    img_bg.setVisibility(View.VISIBLE);
                }
                if (videoView.isPlaying()) {
                    videoView.pause();
                }
            }
        };
    
        /**
         * 移动起始播放位置
         *
         * @version 1.0
         * @createTime 2015年6月18日,下午2:34:31
         * @updateTime 2015年6月18日,下午2:34:31
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         * @param proSlide
         */
        private void sendVideo() {
            if (!videoView.isShown()) {
                videoView.setVisibility(View.VISIBLE);
            }
            if (videoView.isPlaying()) {
                videoView.pause();
            }
            if (!img_bg.isShown()) {
                img_bg.setVisibility(View.VISIBLE);
            }
    
            handler.removeCallbacks(runnable);
    
            videoView.seekTo((int) ((Scroll_lenth + left_lenth) * picture));
        }
    
        /**
         * 移动起始播放位置
         *
         * @version 1.0
         * @createTime 2015年6月18日,下午6:09:50
         * @updateTime 2015年6月18日,下午6:09:50
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         * @param lenth
         *                长度
         */
        private void sendVideo(int lenth) {
            if (!videoView.isShown()) {
                videoView.setVisibility(View.VISIBLE);
            }
            if (videoView.isPlaying()) {
                videoView.pause();
            }
            if (!img_bg.isShown()) {
                img_bg.setVisibility(View.VISIBLE);
            }
    
            handler.removeCallbacks(runnable);
    
            videoView.seekTo((int) (lenth * picture));
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            isThread = true;
            deleteFile();
        }
    
        /**
         * 退出时删除暂时文件
         *
         * @version 1.0
         * @createTime 2015年6月17日,下午1:58:52
         * @updateTime 2015年6月17日,下午1:58:52
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         */
        private void deleteFile() {
            for (int i = 0; i < list.size(); i++) {
                File file = new File(list.get(i));
                if (file.exists()) {
                    file.delete();
                }
            }
        }
    }
    
    

    如今是自己定义RecyclerView:

    package com.utoow.diver.view;
    
    import android.content.Context;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.RecyclerView.OnScrollListener;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class MyRecyclerView extends RecyclerView implements OnScrollListener {
    
        /**记录当前第一个View*/
        private View mCurrentView;
    
        private OnItemScrollChangeListener mItemScrollChangeListener;
    
        public void setOnItemScrollChangeListener(OnItemScrollChangeListener mItemScrollChangeListener) {
            this.mItemScrollChangeListener = mItemScrollChangeListener;
        }
    
        public interface OnItemScrollChangeListener {
            void onChange(View view, int position);
            void onChangeState(int state);
        }
    
        public MyRecyclerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.setOnScrollListener(this);
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
        }
    
        @Override
        public void onScrollStateChanged(int arg0) {
            if (mItemScrollChangeListener != null) {
                mItemScrollChangeListener.onChangeState(arg0);
            }
        }
    
        /**
         * 滚动时,推断当前第一个View是否发生变化。发生才回调
         *
         * @version 1.0
         * @createTime 2015年6月20日,下午4:14:30
         * @updateTime 2015年6月20日,下午4:14:30
         * @createAuthor WangYuWen
         * @updateAuthor WangYuWen
         * @updateInfo (此处输入改动内容,若无改动可不写.)
         *
         * @param arg0
         * @param arg1
         */
        @Override
        public void onScrolled(int arg0, int arg1) {
            mCurrentView = getChildAt(0);
            if (mItemScrollChangeListener != null && mCurrentView != null) {
                mItemScrollChangeListener.onChange(mCurrentView, getChildPosition(mCurrentView));
            }
    
        }
    
    }
    

    最后再把视频截断和视频合并的工具类贴出来:

    package com.example.shipin;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.channels.FileChannel;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.List;
    
    import com.coremedia.iso.boxes.Container;
    import com.coremedia.iso.boxes.TimeToSampleBox;
    import com.googlecode.mp4parser.authoring.Movie;
    import com.googlecode.mp4parser.authoring.Track;
    import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
    import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
    import com.googlecode.mp4parser.authoring.tracks.AppendTrack;
    import com.googlecode.mp4parser.authoring.tracks.CroppedTrack;
    
    public class FUckTest {
    
        public static void startTrim(File src, File dst, long start, long end) throws IOException {
            Movie movie = MovieCreator.build(src.getAbsolutePath());
    
            // 删除全部跟踪我们将创建新的跟踪从旧
            List<Track> tracks = movie.getTracks();
            movie.setTracks(new LinkedList<Track>());
    
            double startTime = start / 1000;
            double endTime = end / 1000;
            boolean timeCorrected = false;
    
            // 我们试图找到一个样品同步跟踪。由于我们仅仅能開始解码在这样一个样品我们应该确保新的片段的開始就是这种一个框架
            for (Track track : tracks) {
                if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
                    if (timeCorrected) {
                        // 这个异常可能是假阳性,以防我们有多个与同步跟踪样品在同样的位置。

    比方一部电影包括多个品质同样的视频(微软平滑流媒体文件) throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported."); } startTime = correctTimeToSyncSample(track, startTime, false);// true endTime = correctTimeToSyncSample(track, endTime, true);// false timeCorrected = true; } } for (Track track : tracks) { long currentSample = 0; double currentTime = 0; long startSample = -1; long endSample = -1; for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); for (int j = 0; j < entry.getCount(); j++) { // entry.getDelta()的数量当前样本覆盖。

    if (currentTime <= startTime) { // 眼下的样品仍然在新的開始时间之前 startSample = currentSample; } if (currentTime <= endTime) { // 当前样本后,新的開始时间和仍在新endtime前 endSample = currentSample; } else { // 眼下样品结束后出现的视频 break; } currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale(); currentSample++; } } movie.addTrack(new CroppedTrack(track, startSample, endSample)); // break;//取消凝视。仅仅截视频不截音频 } Container container = new DefaultMp4Builder().build(movie); if (!dst.exists()) { dst.createNewFile(); } FileOutputStream fos = new FileOutputStream(dst); FileChannel fc = fos.getChannel(); container.writeContainer(fc); fc.close(); fos.close(); } /** * 视频拼接, * * @version 1.0 * @createTime 2015年6月10日,下午5:12:15 * @updateTime 2015年6月10日,下午5:12:15 * @createAuthor WangYuWen * @updateAuthor WangYuWen * @updateInfo (此处输入改动内容,若无改动可不写.) * * @param videos * 视频文件数据。

    《路径》 * @param desName * 合并之后的文件名称 * @param pro * @throws IOException */ public static void appendVideo(String[] videos, String desName) throws IOException { Movie[] inMovies = new Movie[videos.length]; int index = 0; for (String video : videos) { inMovies[index] = MovieCreator.build(video); index++; } List<Track> videoTracks = new LinkedList<Track>(); List<Track> audioTracks = new LinkedList<Track>(); for (Movie m : inMovies) { for (Track t : m.getTracks()) { if (t.getHandler().equals("soun")) { audioTracks.add(t); } if (t.getHandler().equals("vide")) { videoTracks.add(t); } } } Movie result = new Movie(); if (audioTracks.size() > 0) { result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()]))); } if (videoTracks.size() > 0) { result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()]))); } Container out = new DefaultMp4Builder().build(result); FileChannel fc = new RandomAccessFile(String.format(desName), "rw").getChannel(); out.writeContainer(fc); fc.close(); } protected static long getDuration(Track track) { long duration = 0; for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) { duration += entry.getCount() * entry.getDelta(); } return duration; } private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) { double[] timeOfSyncSamples = new double[track.getSyncSamples().length]; long currentSample = 0; double currentTime = 0; for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); for (int j = 0; j < entry.getCount(); j++) { if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) { // 样品总是从1開始,但我们从零因此+ 1開始 timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime; } currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale(); currentSample++; } } double previous = 0; for (double timeOfSyncSample : timeOfSyncSamples) { if (timeOfSyncSample > cutHere) { if (next) { return timeOfSyncSample; } else { return previous; } } previous = timeOfSyncSample; } return timeOfSyncSamples[timeOfSyncSamples.length - 1]; } }

    好了,代码比較长。假设有不懂能够留言。(还有就是有的视频文件比較大就算切断了之后也有30多M,假设说这用到项目中肯定须要上传到server的肯定是不行的,须要的你们能够自己去研究下压缩视频,一般须要用到ffmgep这个c库来进行压缩,顺便说下ffmpeg这个c库真的非常不错非常成熟值得研究)。

    最后就是:
    希望大家多多关注我的博客,多多支持我。
    如有好意见或更好的方式欢迎留言谈论。

    尊重原创转载请注明:(http://blog.csdn.net/u013895206) !

    以下是地址传送门:
    http://download.csdn.net/detail/u013895206/8850751

  • 相关阅读:
    bzoj4555
    bzoj4516
    树莓派/Debian 挂载硬盘
    树莓派/Debian Apache2 安装腾讯云 SSL 证书
    2019-2020-2《网络对抗技术》 Exp2 后门原理与实践
    kali 开启 SSH 服务
    Docker 入门 7 构建镜像
    Docker 入门 6 获取、加速镜像.md
    Docker 入门 5 数据管理
    Docker 入门 4 容器端口映射 和 Nginx 演示部署
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7048848.html
Copyright © 2011-2022 走看看