前言
用户得到返回的视频片段后,可以对其进行播放倍速处理,基本页面如下:
布局文件
布局上使用了 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);
}
}
}