项目实训—基于AI的智能视频剪辑器(十)视频速度调整


前言

用户得到返回的视频片段后,可以对其进行播放倍速处理,基本页面如下:
在这里插入图片描述


布局文件

布局上使用了 com.google.android.material.slider.Slider 这一组件,使用户进行速度调整

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/black">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4">

        <com.dueeeke.videoplayer.player.VideoView
            android:id="@+id/mVideoView"
            android:layout_width="wrap_content"
            android:layout_height="300dp"
            app:layout_constraintDimensionRatio="16:10"
            android:layout_centerInParent="true"/>
        <TextView
            android:id="@+id/mTvOkSpeed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="完成"
            android:textSize="15sp"
            android:padding="10px"
            android:layout_alignParentRight="true"
            android:layout_marginTop="20dp"
            android:layout_marginRight="15dp"
            android:textColor="@color/xui_btn_blue_normal_color"/>

        <TextView
            android:id="@+id/mTvCancelSpeed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="取消"
            android:textSize="15sp"
            android:padding="10px"
            android:layout_alignParentLeft="true"
            android:layout_marginTop="20dp"
            android:layout_marginLeft="15dp"
            android:textColor="@android:color/white"/>

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2">
        <GridLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:columnCount="5"
            android:rowCount="1"
            android:orientation="horizontal">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_row="0"
                android:layout_column="0"
                android:layout_columnWeight="1">
                <TextView
                    android:id="@+id/X0.25"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="0.25X"
                    android:textSize="15dp"
                    android:textColor="@android:color/white"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_row="0"
                android:layout_column="1"
                android:layout_columnWeight="1">
                <TextView
                    android:id="@+id/X0.5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="0.5X"
                    android:textSize="15dp"
                    android:textColor="@android:color/white"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_row="0"
                android:layout_column="2"
                android:layout_columnWeight="1">
                <TextView
                    android:id="@+id/X1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="1X"
                    android:textSize="15dp"
                    android:textColor="@android:color/white"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_row="0"
                android:layout_column="3"
                android:layout_columnWeight="1">
                <TextView
                    android:id="@+id/X1.5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="1.5X"
                    android:textSize="15dp"
                    android:textColor="@android:color/white"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:layout_row="0"
                android:layout_column="4"
                android:layout_columnWeight="1">
                <TextView
                    android:id="@+id/X2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:text="2X"
                    android:textSize="15dp"
                    android:textColor="@android:color/white"/>
            </LinearLayout>
        </GridLayout>
        <com.google.android.material.slider.Slider
            android:id="@+id/mSlider"
            android:theme="@style/Theme.MaterialComponents"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:valueTo="4"
            android:valueFrom="0"
            android:value="2"
            android:stepSize="1"/>
    </RelativeLayout>


</LinearLayout>

SpeedCutFragment

SpeedCutFragment 首先设置视频路径,初始化页面,并且为 Slider 设置 addOnChangeListener,根据不同的value设置不同的速度,调用 ffmpeg 命令进行处理

public class SpeedCutFragment extends BaseFragment<FragmentSpeedcutBinding> implements View.OnClickListener{
    String TAG = "SpeedCutFragment";
    private String work_path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/DCIM/easycut/Work/";
    private String video_url_work;
    private String temp_url;
    private String fileName;
    private FFmpegCmd fFmpegCmd;
    private VideoView mVideoView;
    private Slider mSlider;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        fileName = bundle.getString("fileName");
        int short_video_index = bundle.getInt("shortVideoName");
        work_path = work_path + fileName + "/";
        temp_url = work_path + "temp.mp4";
        video_url_work = work_path + short_video_index + ".mp4";
        fFmpegCmd = new FFmpegCmd();
    }

    @NonNull
    @Override
    protected FragmentSpeedcutBinding viewBindingInflate(LayoutInflater inflater, ViewGroup container) {
        return FragmentSpeedcutBinding.inflate(inflater, container, false);
    }

    @Override
    protected TitleBar initTitle() {
        return null;
    }

    @Override
    protected void initViews() {
        // VideoView
        mVideoView = binding.mVideoView;
        StandardVideoController controller = new StandardVideoController(this.getContext());
        controller.setEnableOrientation(true);
        PrepareView prepareView = new PrepareView(this.getContext());//准备播放界面
        prepareView.setClickStart();
        ImageView thumb = prepareView.findViewById(R.id.thumb);//封面图
        Glide.with(this).setDefaultRequestOptions(
                new RequestOptions()
                        .frame(0)
                        .centerCrop()
        ).load(video_url_work).placeholder(android.R.color.darker_gray).into(thumb);
        controller.addControlComponent(prepareView);
        controller.addControlComponent(new CompleteView(this.getContext()));//自动完成播放界面
        controller.addControlComponent(new ErrorView(this.getContext()));//错误界面
        TitleView titleView = new TitleView(this.getContext());//标题栏
        controller.addControlComponent(titleView);
        VodControlView vodControlView = new VodControlView(this.getContext());//点播控制条
        controller.addControlComponent(vodControlView);
        GestureView gestureControlView = new GestureView(this.getContext());//滑动控制视图
        controller.addControlComponent(gestureControlView);
        mVideoView.setVideoController(controller);
        mVideoView.addOnStateChangeListener(mOnStateChangeListener);
        mVideoView.setUrl(video_url_work);
        mVideoView.start();

        mSlider = binding.mSlider;
        mSlider.addOnChangeListener(new Slider.OnChangeListener() {
            @Override
            public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
                PageLog.dTag(TAG,value + "");
                double speed = 1.0;
                if(Math.round(value) == 0){
                    speed = 4;
                }
                if(Math.round(value) == 1){
                    speed = 2;
                }
                if(Math.round(value) == 2){
                    speed = 1;
                }
                if(Math.round(value) == 3){
                    speed = 0.7;
                }
                if(Math.round(value) == 4){
                    speed = 0.5;
                }
                String cmd = "ffmpeg -i "+ video_url_work +" -vf setpts="+ speed +"*PTS " + temp_url;
                PageLog.dTag(TAG, cmd);
                fFmpegCmd.ffmpeg_cmd(cmd);
                mVideoView.release();
                mVideoView.setUrl(temp_url);
                mVideoView.start();
            }
        });
    }

    @Override
    protected void initListeners() {
        binding.mTvCancelSpeed.setOnClickListener(this);
        binding.mTvOkSpeed.setOnClickListener(this);
    }

    private VideoView.OnStateChangeListener mOnStateChangeListener = new VideoView.SimpleOnStateChangeListener() {
        @Override
        public void onPlayerStateChanged(int playerState) {
            switch (playerState) {
                case VideoView.PLAYER_NORMAL://小屏
                    break;
                case VideoView.PLAYER_FULL_SCREEN://全屏
                    break;
            }
        }

        @Override
        public void onPlayStateChanged(int playState) {
            switch (playState) {
                case VideoView.STATE_IDLE:
                    break;
                case VideoView.STATE_PREPARING:
                    break;
                case VideoView.STATE_PREPARED:
                    break;
                case VideoView.STATE_PLAYING:
                    break;
                case VideoView.STATE_PAUSED:
                    break;
                case VideoView.STATE_BUFFERING:
                    break;
                case VideoView.STATE_BUFFERED:
                    break;
                case VideoView.STATE_PLAYBACK_COMPLETED:
                    break;
                case VideoView.STATE_ERROR:
                    break;
            }
        }
    };

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if(id == R.id.mTvOkSpeed){
            File video = new File(video_url_work);
            video.delete();
            new File(temp_url).renameTo(new File(video_url_work));
            XToast.success(getContext(), "视频速度调整成功").show();
            Bundle params = new Bundle();
            params.putString("fileName", fileName);
            openPage(WorkFragment.class, params);
        }
        if(id == R.id.mTvCancelSpeed){
            File dir = new File(temp_url);
            dir.delete();
            Bundle params = new Bundle();
            params.putString("fileName", fileName);
            openPage(WorkFragment.class, params);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值