增加视频剪切、转码、截图、水印

增加视频剪切、转码、截图、添加水印、视频转成GIF、图片合成视频
pull/107/head
xufuji456 7 years ago
parent b2ef61cc53
commit da13535830
  1. 58
      app/src/main/java/com/frank/ffmpeg/activity/AudioHandleActivity.java
  2. 5
      app/src/main/java/com/frank/ffmpeg/activity/MainActivity.java
  3. 101
      app/src/main/java/com/frank/ffmpeg/activity/MediaHandleActivity.java
  4. 218
      app/src/main/java/com/frank/ffmpeg/activity/VideoHandleActivity.java
  5. 92
      app/src/main/java/com/frank/ffmpeg/util/BitmapUtil.java
  6. 109
      app/src/main/java/com/frank/ffmpeg/util/FFmpegUtil.java
  7. 7
      app/src/main/res/layout/activity_audio_handle.xml
  8. 7
      app/src/main/res/layout/activity_media_handle.xml
  9. 80
      app/src/main/res/layout/activity_video_handle.xml
  10. 5
      app/src/main/res/values/strings.xml

@ -1,12 +1,14 @@
package com.frank.ffmpeg.activity; package com.frank.ffmpeg.activity;
import android.annotation.SuppressLint;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.ProgressBar;
import java.io.File; import java.io.File;
import com.frank.ffmpeg.FFmpegCmd; import com.frank.ffmpeg.FFmpegCmd;
import com.frank.ffmpeg.R; import com.frank.ffmpeg.R;
@ -20,9 +22,32 @@ import com.frank.ffmpeg.util.FFmpegUtil;
public class AudioHandleActivity extends AppCompatActivity implements View.OnClickListener{ public class AudioHandleActivity extends AppCompatActivity implements View.OnClickListener{
private final static String TAG = AudioHandleActivity.class.getSimpleName(); private final static String TAG = AudioHandleActivity.class.getSimpleName();
private static final String PATH = Environment.getExternalStorageDirectory().getPath(); private final static String PATH = Environment.getExternalStorageDirectory().getPath();
String srcFile = PATH + File.separator + "tiger.mp3"; private String srcFile = PATH + File.separator + "tiger.mp3";
String appendFile = PATH + File.separator + "test.mp3"; private String appendFile = PATH + File.separator + "test.mp3";
private final static int MSG_BEGIN = 11;
private final static int MSG_FINISH = 12;
private ProgressBar progress_audio;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MSG_BEGIN:
progress_audio.setVisibility(View.VISIBLE);
setGone();
break;
case MSG_FINISH:
progress_audio.setVisibility(View.GONE);
setVisible();
break;
default:
break;
}
}
};
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -33,12 +58,27 @@ public class AudioHandleActivity extends AppCompatActivity implements View.OnCli
} }
private void initView() { private void initView() {
progress_audio = (ProgressBar) findViewById(R.id.progress_audio);
findViewById(R.id.btn_transform).setOnClickListener(this); findViewById(R.id.btn_transform).setOnClickListener(this);
findViewById(R.id.btn_cut).setOnClickListener(this); findViewById(R.id.btn_cut).setOnClickListener(this);
findViewById(R.id.btn_concat).setOnClickListener(this); findViewById(R.id.btn_concat).setOnClickListener(this);
findViewById(R.id.btn_mix).setOnClickListener(this); findViewById(R.id.btn_mix).setOnClickListener(this);
} }
private void setVisible() {
findViewById(R.id.btn_transform).setVisibility(View.VISIBLE);
findViewById(R.id.btn_cut).setVisibility(View.VISIBLE);
findViewById(R.id.btn_concat).setVisibility(View.VISIBLE);
findViewById(R.id.btn_mix).setVisibility(View.VISIBLE);
}
private void setGone() {
findViewById(R.id.btn_transform).setVisibility(View.GONE);
findViewById(R.id.btn_cut).setVisibility(View.GONE);
findViewById(R.id.btn_concat).setVisibility(View.GONE);
findViewById(R.id.btn_mix).setVisibility(View.GONE);
}
@Override @Override
public void onClick(View v) { public void onClick(View v) {
int handleType; int handleType;
@ -103,17 +143,13 @@ public class AudioHandleActivity extends AppCompatActivity implements View.OnCli
@Override @Override
public void onBegin() { public void onBegin() {
Log.i(TAG, "handle audio onBegin..."); Log.i(TAG, "handle audio onBegin...");
mHandler.obtainMessage(MSG_BEGIN).sendToTarget();
} }
@Override @Override
public void onEnd(int result) { public void onEnd(int result) {
Log.i(TAG, "handle audio onEnd..."); Log.i(TAG, "handle audio onEnd...");
runOnUiThread(new Runnable() { mHandler.obtainMessage(MSG_FINISH).sendToTarget();
@Override
public void run() {
Toast.makeText(AudioHandleActivity.this, "handle audio finish...", Toast.LENGTH_SHORT).show();
}
});
} }
}); });
} }

@ -4,8 +4,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.view.View; import android.view.View;
import android.widget.Toast;
import com.frank.ffmpeg.R; import com.frank.ffmpeg.R;
/** /**
@ -38,8 +36,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
startActivity(new Intent(MainActivity.this, MediaHandleActivity.class)); startActivity(new Intent(MainActivity.this, MediaHandleActivity.class));
break; break;
case R.id.btn_video://视频处理 case R.id.btn_video://视频处理
Toast.makeText(this, "暂时还没完善该功能...", Toast.LENGTH_LONG).show(); startActivity(new Intent(MainActivity.this, VideoHandleActivity.class));
// startActivity(new Intent(MainActivity.this, VideoHandleActivity.class));
break; break;
default: default:
break; break;

@ -10,12 +10,10 @@ import android.os.Message;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.ProgressBar;
import com.frank.ffmpeg.FFmpegCmd; import com.frank.ffmpeg.FFmpegCmd;
import com.frank.ffmpeg.R; import com.frank.ffmpeg.R;
import com.frank.ffmpeg.util.FFmpegUtil; import com.frank.ffmpeg.util.FFmpegUtil;
import java.io.File; import java.io.File;
/** /**
@ -30,42 +28,58 @@ public class MediaHandleActivity extends AppCompatActivity implements View.OnCli
private String videoFile = PATH + File.separator + "flash-tree.mp4";//flash-tree.mp4 private String videoFile = PATH + File.separator + "flash-tree.mp4";//flash-tree.mp4
String temp = PATH + File.separator + "temp.mp4"; String temp = PATH + File.separator + "temp.mp4";
private boolean isMux; private boolean isMux;
private final static int MSG_MUX = 100;
private final static int MSG_BEGIN = 101;
private final static int MSG_FINISH = 102;
private ProgressBar progress_media;
@SuppressLint("HandlerLeak") @SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){ private Handler mHandler = new Handler(){
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
super.handleMessage(msg); super.handleMessage(msg);
if(msg.what == 100){ switch (msg.what){
String audioFile = PATH + File.separator + "tiger.mp3";//tiger.mp3 case MSG_MUX:
String muxFile = PATH + File.separator + "media-mux.mp4"; String audioFile = PATH + File.separator + "tiger.mp3";//tiger.mp3
String muxFile = PATH + File.separator + "media-mux.mp4";
try { try {
//使用MediaPlayer获取视频时长 //使用MediaPlayer获取视频时长
MediaPlayer mediaPlayer = new MediaPlayer(); MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(videoFile); mediaPlayer.setDataSource(videoFile);
mediaPlayer.prepare(); mediaPlayer.prepare();
//单位为ms //单位为ms
int videoDuration = mediaPlayer.getDuration()/1000; int videoDuration = mediaPlayer.getDuration()/1000;
Log.i(TAG, "videoDuration=" + videoDuration); Log.i(TAG, "videoDuration=" + videoDuration);
mediaPlayer.release(); mediaPlayer.release();
//使用MediaMetadataRetriever获取音频时长 //使用MediaMetadataRetriever获取音频时长
MediaMetadataRetriever mediaRetriever = new MediaMetadataRetriever(); MediaMetadataRetriever mediaRetriever = new MediaMetadataRetriever();
mediaRetriever.setDataSource(audioFile); mediaRetriever.setDataSource(audioFile);
//单位为ms //单位为ms
String duration = mediaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); String duration = mediaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
int audioDuration = (int)(Long.parseLong(duration)/1000); int audioDuration = (int)(Long.parseLong(duration)/1000);
Log.i(TAG, "audioDuration=" + audioDuration); Log.i(TAG, "audioDuration=" + audioDuration);
mediaRetriever.release(); mediaRetriever.release();
//如果视频时长比音频长,采用音频时长,否则用视频时长 //如果视频时长比音频长,采用音频时长,否则用视频时长
int mDuration = Math.min(audioDuration, videoDuration); int mDuration = Math.min(audioDuration, videoDuration);
//使用纯视频与音频进行合成 //使用纯视频与音频进行合成
String[] commandLine = FFmpegUtil.mediaMux(temp, audioFile, mDuration, muxFile); String[] commandLine = FFmpegUtil.mediaMux(temp, audioFile, mDuration, muxFile);
executeFFmpegCmd(commandLine); executeFFmpegCmd(commandLine);
isMux = false; isMux = false;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
break;
case MSG_BEGIN:
progress_media.setVisibility(View.VISIBLE);
setGone();
break;
case MSG_FINISH:
progress_media.setVisibility(View.GONE);
setVisible();
break;
default:
break;
} }
} }
}; };
@ -79,11 +93,24 @@ public class MediaHandleActivity extends AppCompatActivity implements View.OnCli
} }
private void initView() { private void initView() {
progress_media = (ProgressBar) findViewById(R.id.progress_media) ;
findViewById(R.id.btn_mux).setOnClickListener(this); findViewById(R.id.btn_mux).setOnClickListener(this);
findViewById(R.id.btn_extract_audio).setOnClickListener(this); findViewById(R.id.btn_extract_audio).setOnClickListener(this);
findViewById(R.id.btn_extract_video).setOnClickListener(this); findViewById(R.id.btn_extract_video).setOnClickListener(this);
} }
private void setVisible() {
findViewById(R.id.btn_mux).setVisibility(View.VISIBLE);
findViewById(R.id.btn_extract_audio).setVisibility(View.VISIBLE);
findViewById(R.id.btn_extract_video).setVisibility(View.VISIBLE);
}
private void setGone() {
findViewById(R.id.btn_mux).setVisibility(View.GONE);
findViewById(R.id.btn_extract_audio).setVisibility(View.GONE);
findViewById(R.id.btn_extract_video).setVisibility(View.GONE);
}
@Override @Override
public void onClick(View v) { public void onClick(View v) {
int handleType; int handleType;
@ -146,20 +173,16 @@ public class MediaHandleActivity extends AppCompatActivity implements View.OnCli
@Override @Override
public void onBegin() { public void onBegin() {
Log.i(TAG, "handle media onBegin..."); Log.i(TAG, "handle media onBegin...");
mHandler.obtainMessage(MSG_BEGIN).sendToTarget();
} }
@Override @Override
public void onEnd(int result) { public void onEnd(int result) {
Log.i(TAG, "handle media onEnd..."); Log.i(TAG, "handle media onEnd...");
if(isMux){ if(isMux){
mHandler.obtainMessage(100).sendToTarget(); mHandler.obtainMessage(MSG_MUX).sendToTarget();
}else { }else {
runOnUiThread(new Runnable() { mHandler.obtainMessage(MSG_FINISH).sendToTarget();
@Override
public void run() {
Toast.makeText(MediaHandleActivity.this, "handle media finish...", Toast.LENGTH_SHORT).show();
}
});
} }
} }
}); });

@ -1,20 +1,228 @@
package com.frank.ffmpeg.activity; package com.frank.ffmpeg.activity;
import android.annotation.SuppressLint;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import com.frank.ffmpeg.FFmpegCmd;
import com.frank.ffmpeg.R; import com.frank.ffmpeg.R;
import com.frank.ffmpeg.util.FFmpegUtil;
/** import java.io.File;
* 使用ffmpeg进行视频处理
* Created by frank on 2018/1/23. public class VideoHandleActivity extends AppCompatActivity implements View.OnClickListener{
*/
public class VideoHandleActivity extends AppCompatActivity { private static final String TAG = VideoHandleActivity.class.getSimpleName();
private static final int MSG_BEGIN = 101;
private static final int MSG_FINISH = 102;
private static final String PATH = Environment.getExternalStorageDirectory().getPath();
private static final String srcFile = PATH + File.separator + "hello.mp4";
private static final String appendVideo = PATH + File.separator + "test.mp4";
private ProgressBar progress_video;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MSG_BEGIN:
progress_video.setVisibility(View.VISIBLE);
setGone();
break;
case MSG_FINISH:
progress_video.setVisibility(View.GONE);
setVisible();
break;
default:
break;
}
}
};
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_handle); setContentView(R.layout.activity_video_handle);
intView();
} }
private void intView() {
progress_video = (ProgressBar)findViewById(R.id.progress_video);
findViewById(R.id.btn_video_transform).setOnClickListener(this);
findViewById(R.id.btn_video_cut).setOnClickListener(this);
findViewById(R.id.btn_video_concat).setOnClickListener(this);
findViewById(R.id.btn_screen_shot).setOnClickListener(this);
findViewById(R.id.btn_water_mark).setOnClickListener(this);
findViewById(R.id.btn_generate_gif).setOnClickListener(this);
findViewById(R.id.btn_screen_record).setOnClickListener(this);
findViewById(R.id.btn_combine_video).setOnClickListener(this);
}
private void setVisible() {
findViewById(R.id.btn_video_transform).setVisibility(View.VISIBLE);
findViewById(R.id.btn_video_cut).setVisibility(View.VISIBLE);
findViewById(R.id.btn_video_concat).setVisibility(View.GONE);
findViewById(R.id.btn_screen_shot).setVisibility(View.VISIBLE);
findViewById(R.id.btn_water_mark).setVisibility(View.VISIBLE);
findViewById(R.id.btn_generate_gif).setVisibility(View.VISIBLE);
findViewById(R.id.btn_screen_record).setVisibility(View.GONE);
findViewById(R.id.btn_combine_video).setVisibility(View.VISIBLE);
}
private void setGone() {
findViewById(R.id.btn_video_transform).setVisibility(View.GONE);
findViewById(R.id.btn_video_cut).setVisibility(View.GONE);
findViewById(R.id.btn_video_concat).setVisibility(View.GONE);
findViewById(R.id.btn_screen_shot).setVisibility(View.GONE);
findViewById(R.id.btn_water_mark).setVisibility(View.GONE);
findViewById(R.id.btn_generate_gif).setVisibility(View.GONE);
findViewById(R.id.btn_screen_record).setVisibility(View.GONE);
findViewById(R.id.btn_combine_video).setVisibility(View.GONE);
}
@Override
public void onClick(View v) {
int handleType;
switch (v.getId()){
case R.id.btn_video_transform:
handleType = 0;
break;
case R.id.btn_video_cut:
handleType = 1;
break;
case R.id.btn_video_concat:
handleType = 2;
break;
case R.id.btn_screen_shot:
handleType = 3;
break;
case R.id.btn_water_mark:
handleType = 4;
break;
case R.id.btn_generate_gif:
handleType = 5;
break;
case R.id.btn_screen_record:
handleType = 6;
break;
case R.id.btn_combine_video:
handleType = 7;
break;
default:
handleType = 0;
break;
}
doHandleVideo(handleType);
}
/**
* 调用ffmpeg处理视频
* @param handleType handleType
*/
private void doHandleVideo(int handleType){
String[] commandLine = null;
switch (handleType){
case 0://视频转码
String transformVideo = PATH + File.separator + "transformVideo.wmv";
commandLine = FFmpegUtil.transformVideo(srcFile, transformVideo);
break;
case 1://视频剪切
String cutVideo = PATH + File.separator + "cutVideo.mp4";
int startTime = 0;
int duration = 20;
commandLine = FFmpegUtil.cutVideo(srcFile, startTime, duration, cutVideo);
break;
case 2://视频合并
// commandLine = FFmpegUtil.toTs(srcFile, ts1);
// concatStep ++;
// String concatVideo = PATH + File.separator + "concatVideo.mp4";
// String appendVideo = PATH + File.separator + "test.mp4";
// File concatFile = new File(PATH + File.separator + "fileList.txt");
// try {
// FileOutputStream fileOutputStream = new FileOutputStream(concatFile);
// fileOutputStream.write(("file \'" + srcFile + "\'").getBytes());
// fileOutputStream.write("\n".getBytes());
// fileOutputStream.write(("file \'" + appendVideo + "\'").getBytes());
// fileOutputStream.flush();
// fileOutputStream.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// commandLine = FFmpegUtil.concatVideo(srcFile, concatFile.getAbsolutePath(), concatVideo);
break;
case 3://视频截图
String screenShot = PATH + File.separator + "screenShot.jpg";
String size = "1080x720";
commandLine = FFmpegUtil.screenShot(srcFile, size, screenShot);
break;
case 4://视频添加水印
//1、图片
String photo = PATH + File.separator + "launcher.png";
String photoMark = PATH + File.separator + "photoMark.mp4";
commandLine = FFmpegUtil.addWaterMark(appendVideo, photo, photoMark);
//2、文字
//String text = "Hello,FFmpeg";
//String textPath = PATH + File.separator + "text.jpg";
//boolean result = BitmapUtil.textToPicture(textPath, text, this);
//Log.i(TAG, "text to pitcture result=" + result);
//String textMark = PATH + File.separator + "textMark.mp4";
//commandLine = FFmpegUtil.addWaterMark(appendVideo, photo, textMark);
break;
case 5://视频转成gif
String Video2Gif = PATH + File.separator + "Video2Gif.gif";
int gifStart = 30;
int gifDuration = 5;
commandLine = FFmpegUtil.generateGif(srcFile, gifStart, gifDuration, Video2Gif);
break;
case 6://屏幕录制
// String screenRecord = PATH + File.separator + "screenRecord.mp4";
// String screenSize = "320x240";
// int recordTime = 10;
// commandLine = FFmpegUtil.screenRecord(screenSize, recordTime, screenRecord);
break;
case 7://图片合成视频
//图片所在路径,图片命名格式img+number.jpg
String picturePath = PATH + File.separator + "img/";
String combineVideo = PATH + File.separator + "combineVideo.mp4";
commandLine = FFmpegUtil.pictureToVideo(picturePath, combineVideo);
break;
default:
break;
}
executeFFmpegCmd(commandLine);
}
/**
* 执行ffmpeg命令行
* @param commandLine commandLine
*/
private void executeFFmpegCmd(final String[] commandLine){
if(commandLine == null){
return;
}
FFmpegCmd.execute(commandLine, new FFmpegCmd.OnHandleListener() {
@Override
public void onBegin() {
Log.i(TAG, "handle video onBegin...");
mHandler.obtainMessage(MSG_BEGIN).sendToTarget();
}
@Override
public void onEnd(int result) {
Log.i(TAG, "handle video onEnd...");
mHandler.obtainMessage(MSG_FINISH).sendToTarget();
}
});
}
} }

@ -0,0 +1,92 @@
package com.frank.ffmpeg.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* bitmap工具类文字转成图片
* Created by frank on 2018/1/24.
*/
public class BitmapUtil {
private final static int TEXT_SIZE = 16;
private final static int TEXT_COLOR = Color.RED;
/**
* 文本转成Bitmap
* @param text 文本内容
* @param context 上下文
* @return 图片的bitmap
*/
private static Bitmap textToBitmap(String text , Context context) {
float scale = context.getResources().getDisplayMetrics().scaledDensity;
TextView tv = new TextView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(layoutParams);
tv.setText(text);
tv.setTextSize(scale * TEXT_SIZE);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
tv.setDrawingCacheEnabled(true);
tv.setTextColor(TEXT_COLOR);
tv.setBackgroundColor(Color.WHITE);
tv.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
tv.buildDrawingCache();
Bitmap bitmap = tv.getDrawingCache();
int rate = bitmap.getHeight() / 20;
return Bitmap.createScaledBitmap(bitmap, bitmap.getWidth()/rate, 20, false);
}
/**
* 文字生成图片
* @param filePath filePath
* @param text text
* @param context context
* @return 生成图片是否成功
*/
public static boolean textToPicture(String filePath, String text , Context context){
Bitmap bitmap = textToBitmap(text , context);
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(filePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
}finally {
try {
if(outputStream != null){
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
/**
* 删除源文件
* @param filePath filePath
* @return 删除是否成功
*/
public static boolean deleteTextFile(String filePath) {
File file = new File(filePath);
return file.exists() && file.delete();
}
}

@ -1,9 +1,10 @@
package com.frank.ffmpeg.util; package com.frank.ffmpeg.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.util.Log;
/** /**
* ffmpeg工具拼接命令行处理音频 * ffmpeg工具拼接命令行处理音
* Created by frank on 2018/1/23. * Created by frank on 2018/1/23.
*/ */
@ -75,7 +76,7 @@ public class FFmpegUtil {
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
public static String[] mediaMux(String videoFile, String audioFile, int duration, String muxFile){ public static String[] mediaMux(String videoFile, String audioFile, int duration, String muxFile){
//-t:时长 如果忽略音视频时长,则把"-t %d"去掉 //-t:时长 如果忽略音视频时长,则把"-t %d"去掉
String mixAudioCmd = "ffmpeg -i %s -i %s -t %d -acodec copy %s"; String mixAudioCmd = "ffmpeg -i %s -i %s -t %d %s";
mixAudioCmd = String.format(mixAudioCmd, videoFile, audioFile, duration, muxFile); mixAudioCmd = String.format(mixAudioCmd, videoFile, audioFile, duration, muxFile);
return mixAudioCmd.split(" ");//以空格分割为字符串数组 return mixAudioCmd.split(" ");//以空格分割为字符串数组
} }
@ -106,4 +107,108 @@ public class FFmpegUtil {
return mixAudioCmd.split(" ");//以空格分割为字符串数组 return mixAudioCmd.split(" ");//以空格分割为字符串数组
} }
/**
* 使用ffmpeg命令行进行视频转码
* @param srcFile 源文件
* @param targetFile 目标文件后缀指定转码格式
* @return 转码后的文件
*/
public static String[] transformVideo(String srcFile, String targetFile){
// String transformVideoCmd = "ffmpeg -i %s -r 25 -b 200 -s 1080x720 %s";
String transformVideoCmd = "ffmpeg -i %s %s";
transformVideoCmd = String.format(transformVideoCmd, srcFile, targetFile);
return transformVideoCmd.split(" ");//以空格分割为字符串数组
}
/**
* 使用ffmpeg命令行进行视频剪切
* @param srcFile 源文件
* @param startTime 剪切的开始时间(单位为秒)
* @param duration 剪切时长(单位为秒)
* @param targetFile 目标文件
* @return 剪切后的文件
*/
@SuppressLint("DefaultLocale")
public static String[] cutVideo(String srcFile, int startTime, int duration, String targetFile){
String cutVideoCmd = "ffmpeg -i %s -ss %d -t %d %s";
cutVideoCmd = String.format(cutVideoCmd, srcFile, startTime, duration, targetFile);
return cutVideoCmd.split(" ");//以空格分割为字符串数组
}
/**
* 使用ffmpeg命令行进行视频截图
* @param srcFile 源文件
* @param size 图片尺寸大小
* @param targetFile 目标文件
* @return 截图后的文件
*/
public static String[] screenShot(String srcFile, String size, String targetFile){
String screenShotCmd = "ffmpeg -i %s -f image2 -t 0.001 -s %s %s";
screenShotCmd = String.format(screenShotCmd, srcFile, size, targetFile);
return screenShotCmd.split(" ");//以空格分割为字符串数组
}
/**
* 使用ffmpeg命令行给视频添加水印
* @param srcFile 源文件
* @param waterMark 水印文件路径
* @param targetFile 目标文件
* @return 添加水印后的文件
*/
public static String[] addWaterMark(String srcFile, String waterMark, String targetFile){
String waterMarkCmd = "ffmpeg -i %s -i %s -filter_complex overlay=0:0 %s";
waterMarkCmd = String.format(waterMarkCmd, srcFile, waterMark, targetFile);
return waterMarkCmd.split(" ");//以空格分割为字符串数组
}
/**
* 使用ffmpeg命令行进行视频转成Gif动图
* @param srcFile 源文件
* @param startTime 开始时间
* @param duration 截取时长
* @param targetFile 目标文件
* @return Gif文件
*/
@SuppressLint("DefaultLocale")
public static String[] generateGif(String srcFile, int startTime, int duration, String targetFile){
//String screenShotCmd = "ffmpeg -i %s -vframes %d -f gif %s";
String screenShotCmd = "ffmpeg -i %s -ss %d -t %d -s 320x240 -f gif %s";
screenShotCmd = String.format(screenShotCmd, srcFile, startTime, duration, targetFile);
return screenShotCmd.split(" ");//以空格分割为字符串数组
}
/**
* 使用ffmpeg命令行进行屏幕录制
* @param size 视频尺寸大小
* @param recordTime 录屏时间
* @param targetFile 目标文件
* @return 屏幕录制文件
*/
@SuppressLint("DefaultLocale")
public static String[] screenRecord(String size, int recordTime, String targetFile){
//-vd x11:0,0 指录制所使用的偏移为 x=0 和 y=0
//String screenRecordCmd = "ffmpeg -vcodec mpeg4 -b 1000 -r 10 -g 300 -vd x11:0,0 -s %s %s";
String screenRecordCmd = "ffmpeg -vcodec mpeg4 -b 1000 -r 10 -g 300 -vd x11:0,0 -s %s -t %d %s";
screenRecordCmd = String.format(screenRecordCmd, size, recordTime, targetFile);
Log.i("VideoHandleActivity", "screenRecordCmd=" + screenRecordCmd);
return screenRecordCmd.split(" ");//以空格分割为字符串数组
}
/**
* 使用ffmpeg命令行进行图片合成视频
* @param srcFile 源文件
* @param targetFile 目标文件(mpg格式)
* @return 合成的视频文件
*/
@SuppressLint("DefaultLocale")
public static String[] pictureToVideo(String srcFile, String targetFile){
//-f image2:代表使用image2格式,需要放在输入文件前面
String combineVideo = "ffmpeg -f image2 -r 1 -i %simg#d.jpg -vcodec mpeg4 %s";
combineVideo = String.format(combineVideo, srcFile, targetFile);
combineVideo = combineVideo.replace("#", "%");
Log.i("VideoHandleActivity", "combineVideo=" + combineVideo);
return combineVideo.split(" ");//以空格分割为字符串数组
}
} }

@ -41,4 +41,11 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"/> android:layout_centerHorizontal="true"/>
<ProgressBar
android:id="@+id/progress_audio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout> </RelativeLayout>

@ -31,4 +31,11 @@
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_below="@+id/btn_extract_audio"/> android:layout_below="@+id/btn_extract_audio"/>
<ProgressBar
android:id="@+id/progress_media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout> </RelativeLayout>

@ -5,4 +5,84 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="com.frank.ffmpeg.activity.VideoHandleActivity"> tools:context="com.frank.ffmpeg.activity.VideoHandleActivity">
<Button
android:id="@+id/btn_video_transform"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="@string/video_transform"/>
<Button
android:id="@+id/btn_video_cut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_video_transform"
android:layout_marginTop="10dp"
android:text="@string/video_cut"/>
<Button
android:id="@+id/btn_video_concat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_video_cut"
android:layout_marginTop="10dp"
android:text="@string/video_concat"
android:visibility="gone"/>
<Button
android:id="@+id/btn_screen_shot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_video_concat"
android:layout_marginTop="10dp"
android:text="@string/video_screen_shot"/>
<Button
android:id="@+id/btn_water_mark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_screen_shot"
android:layout_marginTop="10dp"
android:text="@string/video_water_mark"/>
<Button
android:id="@+id/btn_generate_gif"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_water_mark"
android:layout_marginTop="10dp"
android:text="@string/video_to_gif"/>
<Button
android:id="@+id/btn_screen_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_generate_gif"
android:layout_marginTop="10dp"
android:text="@string/video_screen_record"
android:visibility="gone"/>
<Button
android:id="@+id/btn_combine_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/btn_screen_record"
android:layout_marginTop="10dp"
android:text="@string/video_from_photo"/>
<ProgressBar
android:id="@+id/progress_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout> </RelativeLayout>

@ -15,11 +15,12 @@
<string name="video_cut">视频剪切</string> <string name="video_cut">视频剪切</string>
<string name="video_concat">视频拼接</string> <string name="video_concat">视频拼接</string>
<string name="video_text_mark">视频文字水印</string> <string name="video_water_mark">视频水印</string>
<string name="video_photo_mark">视频图片水印</string>
<string name="video_to_gif">视频转Gif</string> <string name="video_to_gif">视频转Gif</string>
<string name="video_transform">视频转码</string> <string name="video_transform">视频转码</string>
<string name="video_screen_shot">视频截图</string> <string name="video_screen_shot">视频截图</string>
<string name="video_screen_record">屏幕录制</string>
<string name="video_from_photo">图片合成视频</string>
<string name="video_extract_frame">视频抽帧</string> <string name="video_extract_frame">视频抽帧</string>
<string name="video_part_zoom">视频局部放大</string> <string name="video_part_zoom">视频局部放大</string>

Loading…
Cancel
Save