美文网首页
Android 图片视频互转

Android 图片视频互转

作者: 禄眠 | 来源:发表于2019-08-16 11:33 被阅读0次

视频转图片

简而言之就是把视频的每一帧保存为图片,使用MediaMetadataRetriever

String dir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "输出图片" + File.separator;
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 创建文件夹
                File folder = new File(dir);
                if (!folder.exists()) {
                    folder.mkdir();
                }

                int fps = 15;
                //  这里以raw下的视频为例
                Uri videoUrI = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.test_5s);
                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                retriever.setDataSource(MainActivity.this, videoUrI);

                //  视频总长度(ms)
                String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                //  以每秒15帧所需要的时间
                int seconds = Integer.parseInt(duration) / 1000 * fps;
                Log.d("MainActivity", "seconds:" + seconds);
                for (int i = 0; i < seconds; i++) {
                    //  注意此处的getFrameAtTime传入的单位是微秒
                    Bitmap bitmap = retriever.getFrameAtTime(i * 1000 * 1000 / fps, MediaMetadataRetriever.OPTION_CLOSEST);
                    if (bitmap == null) continue;
                }
            }
        }).start();

这样就能获取到相应的图片了,我们也可以保存到本地

public void saveBitmap(Bitmap bitmap) {
        FileOutputStream fos;
        try {
            String name = "";
            fos = new FileOutputStream(name, false);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

图片转视频

有时候需要处理视频里的图像,就需要把视频分解处理完再进行合成,需要用到AndroidSequenceEncoder

new Thread(new Runnable() {
            @Override
            public void run() {
                File folder = new File(dir);
                if (!folder.exists()) {
                    folder.mkdir();
                }
                AndroidSequenceEncoder encoder = null;
                File videoFile = new File(dir + "out.mp4");
                try {
                    int fps = 15;
                    encoder = AndroidSequenceEncoder.createSequenceEncoder(videoFile, fps);
                    //  此处就是对本地获取的bitmap进行合并
                    Bitmap tempBitmap = null;
                    encoder.encodeImage(tempBitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    encoder.finish();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

整合

如果先分解,再保存本地,最后读取进行合成比较繁琐,所以一般在分解时直接进行图像处理操作,最后进行合成
完整代码

new Thread(new Runnable() {
            @Override
            public void run() {
                File folder = new File(dir);
                if (!folder.exists()) {
                    folder.mkdir();
                }
                AndroidSequenceEncoder encoder = null;
                //  设置输出路径
                File videoFile = new File(dir + "out.mp4");
                try {
                    int fps = 15;
                    encoder = AndroidSequenceEncoder.createSequenceEncoder(videoFile, fps);

                    Uri videoUrI = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.test_5s);
                    System.out.println(videoUrI);
                    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                    retriever.setDataSource(MainActivity.this, videoUrI);
                    String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                    int seconds = Integer.parseInt(duration) / 1000 * fps;
                    Log.d("MainActivity", "seconds:" + seconds);
                    for (int i = 0; i < seconds; i++) {
                        Bitmap bitmap = retriever.getFrameAtTime(i * 1000 * 1000 / fps, MediaMetadataRetriever.OPTION_CLOSEST);
                        if (bitmap == null) continue;
                        //  这里就可以对图像进行相关操作
                        
                        //  处理完后加到encoder中
                        Bitmap tempBitmap = null;
                        encoder.encodeImage(tempBitmap);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Log.d("MainActivity", "处理结束");
                try {
                    encoder.finish();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

当然这个有一个很大的缺点,就是非常耗时,实测10s的视频从分解到合并大约需要3分钟,听说使用ffmpeg效率能有成倍提升,等后续使用上了再发一篇。

参考文章

Android平台下的图片/视频转Ascii码图片/视频 (一) (github持续更新)
android_图片转视频_image2video

相关文章

网友评论

      本文标题:Android 图片视频互转

      本文链接:https://www.haomeiwen.com/subject/tehfsctx.html