我正在尝试使用FFmpeg在我的Android应用中编辑一些视频,但是当我尝试拍摄视频的一部分时,我遇到了一些问题。
我正在使用这个ffmpeg编译/ lib https://github.com/WritingMinds/ffmpeg-android-java
我尝试使用此命令修剪/剪切视频
"-y -i input.mp4 -ss 00:00:01.00 -t 00:00:15.000 -c copy output.mp4"
但有些视频我的黑屏或视频只是冻结。在我的所有测试中声音都很好。
使用此命令
"-y -i input.mp4 -ss 00:00:01.000 -t 00:00:15.000 -async 1 output.mp4"
在我的所有测试(视频/声音)中一切正常但生成输出文件需要太多时间,这个15s文件生成时间超过2分钟。
我尝试了这些命令的其他变体,但我总是遇到视频流问题(黑屏或冻结)或花费太多时间来生成输出(用户只能选择15s的视频发送到我的服务器)
感谢您的帮助!
编辑:
这是修剪视频的代码的一部分
String[] cmd = new String[]{"-y","-i",input,"-ss","00:00:05.000","-vcodec","copy",
"-acodec","copy","-t","00:00:15.00","-strict","-2",output };
final FFmpeg ffmpeg = FFmpeg.getInstance(this);
try {
ffmpeg.execute(cmd, new FFmpegExecuteResponseHandler() {
@Override
public void onSuccess(String message) {
Log.i("VideoEditActivity", "Success " + message);
is_video_generated_ = true;
}
@Override
public void onProgress(String message) {
Log.i("VideoEditActivity", "Progress updated " + message);
}
@Override
public void onFailure(String message) {
Log.e("VideoEditActivity", "ERROR! " + message);
}
@Override
public void onStart() {
progress_dialog_.setMessage(getString(R.string.str_video_generating));
progress_dialog_.show();
}
@Override
public void onFinish() {
Log.i("VideoEditActivity", "Finished");
progress_dialog_.hide();
Intent intent = new Intent(getApplicationContext(), VideoPlayActivity.class);
intent.putExtra("media", edited_video_path_);
startActivity(intent);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
e.printStackTrace();
}
这是原始文件:[https://drive.google.com/file/d/0BzqJL_nNetbRYmxvcTljanJwR00/view?usp=sharing][1]
这个输出:0BzqJL_nNetbReENjRGMtVXQ5VHM / view?usp = sharing(堆栈溢出不允许我添加2个以上的链接)
答案 0 :(得分:1)
我也遇到过同样的问题,经过大量研究,我找到了一个完美的解决方案。
/**
* Command for cutting video
*/
private void executeCutVideoCommand(long startMs, long endMs) {
String destPath = "/storage/emulated/0/DCIM/test/";//Replace ypur dest Path
File externalStoragePublicDirectory = new File(destPath);
if (!externalStoragePublicDirectory.exists() ? externalStoragePublicDirectory.mkdir() : true) {
String yourRealPath = "YOUR INPUT PATH";//getPath(MainActivity.this, selectedVideoUri);
String filePrefix = yourRealPath.substring(yourRealPath.lastIndexOf("."));
String destFileName = "cut_video";
boolean isFastMode = false;
File dest = (filePrefix.equals(".webm") || filePrefix.equals(".mkv")) ? new File(externalStoragePublicDirectory, destFileName + ".mp4") : new File(externalStoragePublicDirectory, destFileName + filePrefix);
int fileNo = 0;
while (dest.exists()) {
fileNo++;
dest = (filePrefix.equals(".webm") || filePrefix.equals(".mkv")) ? new File(externalStoragePublicDirectory, destFileName + fileNo + ".mp4") : new File(externalStoragePublicDirectory, destFileName + fileNo + filePrefix);
}
Log.d(TAG, "startTrim: src: " + yourRealPath);
Log.d(TAG, "startTrim: dest: " + dest.getAbsolutePath());
Log.d(TAG, "startTrim: startMs: " + startMs);
Log.d(TAG, "startTrim: endMs: " + endMs);
filePath = dest.getAbsolutePath();
final String[] complexCommand = isFastMode ?
(filePrefix.equals(".webm") || filePrefix.equals(".mkv") || filePrefix.equals(".m4v") || filePrefix.equals(".mov")) ?
new String[]{"-ss", "" + (startMs / 1000), "-y", "-i", yourRealPath, "-preset", "ultrafast", "-t", "" + ((endMs - startMs) / 1000), "-vcodec", "mpeg4", "-b:v", "2097152", "-b:a", "48000", "-ac", "2", "-ar", "22050", "-strict", "-2", filePath}
: new String[]{"-y", "-i", yourRealPath, "-preset", "ultrafast", "-ss", "" + (startMs / 1000), "-t", "" + ((endMs - startMs) / 1000), "-c", "copy", filePath}
: (filePrefix.equals(".webm") || filePrefix.equals(".mkv") || filePrefix.equals(".m4v") || filePrefix.equals(".mov")) ?
new String[]{"-ss", "" + (startMs / 1000), "-y", "-i", yourRealPath, "-t", "" + ((endMs - startMs) / 1000), "-vcodec", "mpeg4", "-b:v", "2097152", "-b:a", "48000", "-ac", "2", "-ar", "22050", "-strict", "-2", filePath} :
new String[]{"-y", "-i", yourRealPath, "-ss", "" + (startMs / 1000), "-t", "" + ((endMs - startMs) / 1000), "-c", "copy", filePath};
execFFmpegBinary(complexCommand);
}
}
execFFmpegBinary(complexCommand)
在哪里
private void execFFmpegBinary(final String[] command) {
try {
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onFailure(String s) {
Log.d(TAG, "FAILED with output : " + s);
}
@Override
public void onSuccess(String s) {
Log.d(TAG, "SUCCESS with output : " + s);
}
@Override
public void onProgress(String s) {
Log.d(TAG, "Started command : ffmpeg " + command);
}
@Override
public void onStart() {
Log.d(TAG, "Started command : ffmpeg " + command);
}
@Override
public void onFinish() {
Log.d(TAG, "Finished command : ffmpeg " + command);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// do nothing for now
}
}
答案 1 :(得分:1)
我参加聚会有点晚了,但这可能会在将来对人们有所帮助。使用FFMEPG中的微调功能时,我遇到了很多问题,尤其是在处理准确性和速度时。我找到的最佳解决方案是以下命令。
-ss 00:00:00.00 -t 00:00:00.00 -noaccurate_seek -i input.mp4 -codec copy -avoid_negative_ts 1 output.mp4
以下是发生的情况的说明:
在测试了许多命令之后,该命令才能给出最快,最准确的结果,而不会出现黑屏,缺少帧或执行时间太长的情况。
答案 2 :(得分:0)
尝试:
-y -i -ss 00:00:00.00 input_path -vcodec copy -acodec copy -t 00:00:00.00 -strict -2 output_path
它很快就像地狱一样。修剪没有重新编码-ss是开始时间,-t是持续时间。 HH:MM:SS.SS
答案 3 :(得分:0)
请尝试使用以下 ffmpeg 命令修剪起点和终点
fun trim(): Array<String?>{
val cmdList = ArrayList<String>()
var cmds: Array<String?>? = null
try{
cmdList.add("-y")
cmdList.add("-ss")
cmdList.add(startduration.toString())
cmdList.add("-t")
cmdList.add(endduration.toString())
cmdList.add("-i")
cmdList.add(sourcevideopath)
cmdList.add("-vcodec")
cmdList.add("copy")
cmdList.add("-movflags")
cmdList.add("faststart")
cmdList.add("-preset")
cmdList.add("ultrafast")
cmdList.add(outputvideopath)
cmds = arrayOfNulls<String>(cmdList.size)
cmdList.toArray(cmds)
}catch (e:Exception){
e.printStackTrace()
}
return cmds!!
}