Android ffmpeg视频剪辑

Android ffmpeg视频剪辑,android,ffmpeg,Android,Ffmpeg,我试图在我的Android应用程序中使用FFmpeg编辑一些视频,但当我试图只拍摄视频的一部分时,我遇到了一些问题 我正在使用这个ffmpeg编译/库 我尝试使用此命令来修剪/剪切视频 "-y -i input.mp4 -ss 00:00:01.00 -t 00:00:15.000 -c copy output.mp4" String[] cmd = new String[]{"-y","-i",input,"-ss","00:00:05.000","-vcodec","copy",

我试图在我的Android应用程序中使用FFmpeg编辑一些视频,但当我试图只拍摄视频的一部分时,我遇到了一些问题

我正在使用这个ffmpeg编译/库

我尝试使用此命令来修剪/剪切视频

"-y -i input.mp4 -ss 00:00:01.00 -t 00:00:15.000 -c copy output.mp4"
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();
    }
但有些视频会出现黑屏,或者视频会冻结。这声音在我所有的测试中都很好

用这个命令

"-y -i input.mp4 -ss 00:00:01.000 -t 00:00:15.000 -async 1 output.mp4"
在我所有的测试(视频/声音)中,一切正常,但生成输出文件需要太多时间,生成这个15秒的文件需要2分钟以上

我尝试了这些命令的其他变体,但我总是遇到视频流问题(黑屏或冻结),或者生成输出需要太多时间(用户只能选择15秒的视频发送到我的服务器)

谢谢你的帮助

编辑:

这是剪辑视频的代码部分

"-y -i input.mp4 -ss 00:00:01.00 -t 00:00:15.000 -c copy output.mp4"
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();
    }
这是原始文件:[

这是输出:0BzqJL_nNetbReENjRGMtVXQ5VHM/view?usp=共享(堆栈溢出不允许我添加超过2个链接)

尝试:

-y-i-ss 00:00:00.00输入路径-vcodec副本-acodec副本-t 00:00:00.00-严格-2输出路径

-ss是开始时间,-t是持续时间。HH:MM:ss.ss


速度太快了。不重新编码就进行修剪

我曾经遇到过同样的问题,在挖了很多后,我找到了一个完美的解决方案

 /**
 * 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
    }
}

我参加聚会有点晚了,但这可能会对未来的人们有所帮助。我在使用FFMEPG中的微调功能时遇到了很多问题,尤其是在处理准确性和速度时。我找到的最佳解决方案是下面的命令

-ss 00:00:00.00 -t 00:00:00.00 -noaccurate_seek -i input.mp4 -codec copy -avoid_negative_ts 1 output.mp4
下面是对发生的事情的解释:

  • -i:输入文件
  • -ss:这被放置在输入文件之前,因为它寻求输入文件中的这个位置以获得速度
  • -t:命令将要剪切到的位置
  • -noaccurate_seek:保留-ss和下一个关键帧之间的帧,否则默认情况下会删除这些帧
  • -编解码器复制:复制视频和音频编解码器,以提高速度
  • -avoid_negative_ts 1:将第一个时间戳设置为1,并避免它变为负数
  • -输出文件是命令的最后一部分

在测试了许多命令后,这是一个能够提供最快和最准确结果的命令,没有任何黑屏、缺少帧或执行时间过长。

我尝试了这一个命令,效果稍好一些,但我在一些视频中仍然存在问题,再多研究一点,我意识到我遇到这个问题的几乎所有文件都是可供查看的操作系统由WhatsAPP处理,用户没有录制,你知道为什么会发生这种情况吗?你能提供一些代码吗?你必须严格遵守上面提到的命令行顺序。顺便问一下,视频的格式是什么?我用sorce代码和命令编辑了我的问题,我添加了原始文件和输出文件的链接同样。感谢您的帮助!流复制时,视频只能在关键帧处修剪。因此,如果您的
-ss
12
且关键帧为
10
,则输出视频将冻结/变黑,直到下一个关键帧出现。确定,更改-ss的顺序将修复视频帧开始(),但是有没有一种简单的方法可以在关键帧处修剪视频的结尾(即使视频会比我需要的大一点)?我读了一些关于这方面的文章,一些人正在使用ffprobe获取关键帧时间戳,但我今天的Android版本中没有。你使用过类似FFmpeg的库吗?或者你自己构建了整个FFmpeg?@Quantum_VC只使用Androidlibrary@MuhamedRiyasM这对mp4文件格式有效吗?我在这个命令中遇到错误,无法为“-avoid\u negative\u ts”找到合适的输出格式-avoid\u negative\u ts:无效参数