无法使用 JavaCV 合并 Android 中的视频("Sample Description" 错误)

Unable to merge videos in Android using JavaCV ("Sample Description" Error)

我正在通过 FFMPEG 从图像创建视频,我能够从图像中获取视频。我还使用 JavaCV 合并两个视频,并且我可以使用 JavaCV 加入视频而不会出现任何问题,前提是这两个视频都是通过相机拍摄的,即实际通过移动相机录制的视频。

我面临的问题:

我无法将使用图像从 FFMPEG 生成的视频与用户选择的视频合并,这主要是不是通过移动相机生成和拍摄的视频。

代码: 通过图像生成视频的代码:

                  FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(path + "/" + "dec16.mp4", 800, 400);
                            try {
                                recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
                                //recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
                                recorder.setVideoCodecName("H264");
                                recorder.setVideoOption("preset", "ultrafast");
                                recorder.setFormat("mp4");
                                recorder.setFrameRate(frameRate);
                                recorder.setVideoBitrate(60);
                                recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
                                startTime = System.currentTimeMillis();
                                recorder.start();
                                for(int j=0;j<MomentsGetStarted.chosen_images_uri.size();j++)
                                {
                                    if(MomentsGetStarted.chosen_images_uri.get(j).video_id==0)
                                    {
                                        chosen_images.add(MomentsGetStarted.chosen_images_uri.get(j));
                                    }

                                }
                                for (int i = 0; i < chosen_images.size(); i++) {

                                    opencv_core.IplImage image = cvLoadImage(chosen_images.get(i).sdcardPath);

                                    long t = 3000 * (System.currentTimeMillis() - startTime);
                                    if (t > recorder.getTimestamp()) {

                                        recorder.setTimestamp(t);
                                        recorder.record(image);
                                    }
                                }
                                recorder.stop();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

合并视频的代码:

 int count = file_path.size();
            System.out.println("final_joined_list size " + file_path.size());
            if (file_path.size() != 1) {
                try {
                    Movie[] inMovies = new Movie[count];
                    mediaStorageDir = new File(
                            Environment.getExternalStorageDirectory()
                                    + "/Pictures");

                    for (int i = 0; i < count; i++) {
                        File file = new File(file_path.get(i));
                        System.out.println("fileeeeeeeeeeeeeeee " + file);
                        System.out.println("file exists!!!!!!!!!!");

                        FileInputStream fis = new FileInputStream(file);
                        FileChannel fc = fis.getChannel();
                        inMovies[i] = MovieCreator.build(fc);
                        fis.close();
                        fc.close();

                    }
                    List<Track> videoTracks = new LinkedList<Track>();
                    List<Track> audioTracks = new LinkedList<Track>();
                    Log.d("Movies length", "isss  " + inMovies.length);
                    if (inMovies.length != 0) {

                        for (Movie m : inMovies) {

                            for (Track t : m.getTracks()) {
                                if (t.getHandler().equals("soun")) {
                                    audioTracks.add(t);
                                }
                                if (t.getHandler().equals("vide")) {
                                    videoTracks.add(t);
                                }
                                if (t.getHandler().equals("")) {

                                }
                            }

                        }
                    }

                    Movie result = new Movie();

                    System.out.println("audio and videoo tracks : "
                            + audioTracks.size() + " , " + videoTracks.size());
                    if (audioTracks.size() > 0) {
                        result.addTrack(new AppendTrack(audioTracks
                                .toArray(new Track[audioTracks.size()])));
                    }
                    if (videoTracks.size() > 0) {
                        result.addTrack(new AppendTrack(videoTracks
                                .toArray(new Track[videoTracks.size()])));
                    }
                    IsoFile out = null;
                    try {
                        out = (IsoFile) new DefaultMp4Builder().build(result);
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    long timestamp = new Date().getTime();
                    String timestampS = "" + timestamp;

                    File storagePath = new File(mediaStorageDir
                            + File.separator);
                    storagePath.mkdirs();
                    File myMovie = new File(storagePath, String.format("%s.mp4", timestampS));
                    FileOutputStream fos = new FileOutputStream(myMovie);
                    FileChannel fco = fos.getChannel();
                    fco.position(0);
                    out.getBox(fco);
                    fco.close();
                    fos.close();

                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                String mFileName = Environment.getExternalStorageDirectory()
                        .getAbsolutePath();
                // mFileName += "/output.mp4";

                File sdCardRoot = Environment.getExternalStorageDirectory();
                File yourDir = new File(mediaStorageDir + File.separator);
                for (File f : yourDir.listFiles()) {
                    if (f.isFile())
                        name = f.getName();
                    // make something with the name
                }
                mFileName = mediaStorageDir.getPath() + File.separator
                        + "output-%s.mp4";
                System.out.println("final filename : "
                        + mediaStorageDir.getPath() + File.separator
                        + "output-%s.mp4" + "names of files : " + name);
                single_video = false;
                return name;
            } else {
                single_video = true;
                name = file_path.get(0);
                return name;
            }

错误:

我在尝试合并通过图像生成的视频和普通视频时遇到的错误是

12-15 12:26:06.155  26022-26111/? W/System.err﹕ java.io.IOException: Cannot append com.googlecode.mp4parser.authoring.Mp4TrackImpl@45417c38 to com.googlecode.mp4parser.authoring.Mp4TrackImpl@44ffac60 since their Sample Description Boxes differ
12-15 12:26:06.155  26022-26111/? W/System.err﹕ at com.googlecode.mp4parser.authoring.tracks.AppendTrack.<init>(AppendTrack.java:48)

我试过的修复方法:

Google 建议我将 JavaCV 中的 CODEC 从 avcodec.AV_CODEC_ID_MPEG4 更改为 avcodec.AV_CODEC_ID_H264。但是当我这样做时,我无法从图像中获取视频,从而引发以下错误:

12-15 12:26:05.840  26022-26089/? W/linker﹕ libavcodec.so has text relocations. This is wasting memory and is a security risk. Please fix.
12-15 12:26:05.975  26022-26089/? W/System.err﹕ com.googlecode.javacv.FrameRecorder$Exception: avcodec_open2() error -1: Could not open video codec.
12-15 12:26:05.975  26022-26089/? W/System.err﹕ at com.googlecode.javacv.FFmpegFrameRecorder.startUnsafe(FFmpegFrameRecorder.java:492)
12-15 12:26:05.975  26022-26089/? W/System.err﹕ at com.googlecode.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:267)

我需要什么:

从图像创建视频是不可避免的,并且该视频肯定会用于与可能具有任何编解码器格式的其他视频合并。所以我需要找到一种方法来合并任何类型的视频,而不管它们的编解码器或任何其他参数。我试图通过仅使用 Jars 和 SO 文件来保持简单,并且我不想通过全面实施 FFMPEG 库来让自己发疯。话虽如此,如果我没有任何其他方法来实现我想要的,我也准备好研究该库,但是非常感谢具有几乎可以工作代码的可靠资源。干杯。

更新: 我查看了 OpenCV GitHub 中提到的问题,但没有从中找到任何可靠的东西。 OpenCV Issues

您正在使用 MP4 解析器,这意味着它不会触及视频的编码。这仅在两个视频共享相同的编码器设置(如分辨率、帧率以列出一些最明显的设置)时才有效。

如果您需要合并具有不同编解码器或参数的视频,那么您必须重新编码它们以针对通用格式和参数集,在这种情况下,一个简单的MP4 解析器不会做。

您可以直接使用 ffmpeg 实现。