我需要帮助制作视频拼贴,尝试了所有方法但没有成功

I want help in making video collage, tried everything but unsuccessful

我想制作Video Collage,其中应该在一帧中显示2个或更多个视频,然后可以将它们转换为一个视频文件。 我尝试了示例,但他们只是在每个视频的末尾添加视频以制作一个很长的组合视频。 请提供任何帮助

String FILE_PATH = "/storage/sdcard0/testing.mp4";
String FILE_PATH2 = "/storage/sdcard0/testing1.mp4";
String FILE_PATH3 = "/storage/sdcard0/testing2.mp4";
File file1 = new File(FILE_PATH);
File file2 = new File(FILE_PATH2);
File file3 = new File(FILE_PATH3);

private ProgressDialog pDialog;
ImageView img,img2,img3;
MediaMetadataRetriever retriever2 = new MediaMetadataRetriever();
MediaMetadataRetriever retriever3 = new MediaMetadataRetriever();
ArrayList<Bitmap> bitmapArray1 = new ArrayList<Bitmap>();
ArrayList<Bitmap> bitmapArray2 = new ArrayList<Bitmap>();
ArrayList<Bitmap> bitmapArray3 = new ArrayList<Bitmap>();
File ScreenDIR = new File("/sdcard/Screens/");

// 如果需要,让对象构建目录结构。

double id1=0,id2=0,id3=0;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ScreenDIR.mkdirs();

     img = (ImageView)findViewById(R.id.imageView);
    img2 = (ImageView)findViewById(R.id.imageView2);
    img3 = (ImageView)findViewById(R.id.imageView3);

    new LoadAllProducts().execute();




}

class LoadAllProducts extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("Extracting Frames. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();
    }

    /**
     * getting All products from url
     * */
    protected String doInBackground(String... args) {
        if(file1.exists()){


            for (long i = 0; i < 5000; i += 1000/14) { // lenms - video length in milliseconds

                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                retriever.setDataSource(file1.toString());

               // Bitmap bitmap = retriever.getFrameAtTime((i*1000/14), MediaMetadataRetriever.OPTION_CLOSEST_SYNC);

                saveBitmapToCahche( getResizedBitmap((retriever.getFrameAtTime((i*1000/14), MediaMetadataRetriever.OPTION_CLOSEST_SYNC)), 500) ,String.valueOf(id1));
                id1++;
                //bitmapArray1.add(bitmap);

               /* File file = new File(ScreenDIR, "sketchpad1" + id1 + ".png");
                FileOutputStream fOut = null;
                try {
                    fOut = new FileOutputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

                //bitmap.compress(Bitmap.CompressFormat.PNG, 30, fOut);

                try {
                    fOut.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fOut.close();


                } catch (IOException e) {
                    e.printStackTrace();
                }*/
            }

            }
       /* if(file2.exists()){
            retriever2.setDataSource(file2.toString());
            for (long i = 0; i < 3000; i += 1000/24) { // lenms - video length in milliseconds
                bitmap2 = retriever2.getFrameAtTime(i*1000/29, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                //bitmapArray2.add(bitmap2);

                File file = new File(ScreenDIR, "sketchpad2" + id2 + ".png");
                FileOutputStream fOut = null;
                try {
                    fOut = new FileOutputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

                bitmap2.compress(Bitmap.CompressFormat.PNG, 85, fOut);
                try {
                    fOut.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fOut.close();
                    id2++;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }



        }
        if(file3.exists()){
            retriever3.setDataSource(file3.toString());
            for (long i = 0; i < 3000; i += 1000/24) { // lenms - video length in milliseconds
                bitmap3 = retriever3.getFrameAtTime(i*1000/29, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
               // bitmapArray3.add(bitmap3);

                File file = new File(ScreenDIR, "sketchpad3" + id3 + ".png");
                FileOutputStream fOut = null;
                try {
                    fOut = new FileOutputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

                bitmap3.compress(Bitmap.CompressFormat.PNG, 85, fOut);
                try {
                    fOut.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fOut.close();
                    id3++;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            }*/




        return null;
    }
    /**
     * After completing background task Dismiss the progress dialog
     * **/
    protected void onPostExecute(String file_url) {
        // dismiss the dialog after getting all products
        pDialog.dismiss();



        img.setImageBitmap(retrieveBitmapFromCache(String.valueOf(id2)));
        id2 = 50;

        img2.setImageBitmap(retrieveBitmapFromCache(String.valueOf(id2)));
        id2 = 69;

        img3.setImageBitmap(retrieveBitmapFromCache(String.valueOf(id2)));


       // img2.setImageBitmap(bitmapArray2.get(0));
       // img3.setImageBitmap(bitmapArray3.get(0));

        }




    }


public void saveBitmapToCahche(Bitmap bb,String ID ){

    Cache.getInstance().getLru().put(ID, bb);


}
public Bitmap retrieveBitmapFromCache(String ID) {


    Bitmap bitmap = (Bitmap) Cache.getInstance().getLru().get(ID);

    return  bitmap;

}
public Bitmap getResizedBitmap(Bitmap image, int maxSize) {
    int width = image.getWidth();
    int height = image.getHeight();

    float bitmapRatio = (float)width / (float) height;
    if (bitmapRatio > 0) {
        width = maxSize;
        height = (int) (width / bitmapRatio);
    } else {
        height = maxSize;
        width = (int) (height * bitmapRatio);
    }
    return Bitmap.createScaledBitmap(image, width, height, true);
}
}

`

将视频分割成帧,例如

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
File file1 = new File(directory, "file.mp4");
retriever.setDataSource(file1.toString());
for (long i = 0; i < lenms; i += 1000/fps) { // lenms - video length in milliseconds
    Bitmap bitmap = retriever.getFrameAtTime(i*1000/fps, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
}

并从位图制作新帧

为视频的每一帧创建位图非常慢,而且根本不适合存储。除此之外 MediaMetadataRetriever 会给你很多冗余帧。当您完成为两个视频创建位图后,您将只有 4-5 个来自两个视频的不同位图。

要从视频中提取每一帧,您必须将 MediaCodec 与 MediaExtractor 结合使用。

创建拼贴画有点棘手。一件事是 H264 编码仅支持某些帧大小。当您并排添加两个视频时,它不一定适合支持的帧大小。

也就是说,我认为可以将两个视频的帧并排渲染到 GLSurfaceView 并将该表面共享给 Mediacodec,后者会将这些帧编码为 h264。我还没有实现这个,但我相信这是一种无需处理 NDK 即可实现的方法。

FFMPEG 也为此内置了功能。如果您对 NDK 感到满意。