/FFmpegTools

将视频解码为一帧一帧的图片,并能执行FFmpeg命令。

Primary LanguageC

FfmpegTool

将视频解码为一帧一帧的图片,并能执行FFmpeg命令。 在Android手机上用FFmpeg可以很方便的处理视频,裁剪、压缩、转码等。

之前遇到一个需求是将视频一秒一秒解码成一帧一帧的图片,用户滑动选择时间节点(微信朋友圈发10秒视频的编辑界面)。开始我是用的MediaMetadataRetriever类 来获取图片,但是对于分辨率比较大的视频(1920*1080)获取一个图片要0.7/0.8秒,太慢了。后来又用FFmpeg的命令来批量的解码视频成一帧一帧的图片,速度依然不快 每张图片得耗费0.5秒左右的时间。最后还是用FFmpeg,不过不是用命令行,而是用NDK,发现c解码视频再转换为图片保存起来效率大大挺高,一秒钟能解码4、5张图片,c就是快啊。

工程很简单,主要的就FfmpegTool类,里面两个方法cmdRun执行FFmpeg命令,decodToImage一秒一秒的解码图片。两个方法都是阻塞的。

cmdRun用法

String basePath = Environment.getExternalStorageDirectory().getPath();

String cmd = String.format("ffmpeg -ss 00:00:10 -i "+ basePath+"/test/"+"c.mp4"
                   +" -f image2 -y  "+basePath+"/test"+"/"+"aaaa.jpg");
                   
           String dir=basePath+File.separator+"test"+File.separator;
           
           String videoPath=dir+"c.mp4";
           
           String out=dir+"out.mp4";
           
           String cmd2=String.format("ffmpeg -ss 10"+" -t 15 -i "+videoPath
                   +" -vcodec copy -acodec copy "+out);

           String regulation="[ \\t]+";
           
           Log.i("MainActivity","cmd:"+cmd);
           
           Log.i("MainActivity","cmd2:"+cmd2);
           
           final String[] split = cmd.split(regulation);
           final String[] split2 = cmd2.split(regulation);
           int result=FfmpegTool.cmdRun(split2);

decodToImage用法

String path= Environment.getExternalStorageDirectory().getPath()+ File.separator+"test"+File.separator;

String video=path+"c.mp4";

FfmpegTool.decodToImage(video.replaceAll(File.separator,"/"),path.replaceAll(File.separator,"/"),0,60);

//新加方法 public native int decodToImageWithCall(String srcPath,String savePath,int startTime,int count); 该方法与decodToImage功能相同,不过该方法添加了jni回调,每当有一幅图片解码保存完成后都会调用public void decodToImageCall(String path,int index)(类FfmpegTool中的方法),用户可根据该方法监听进度。 用法:

    FfmpegTool  ffmpegTool=new FfmpegTool() ;
    
    new Thread(){
        @Override
        public void run() {
            String path= Environment.getExternalStorageDirectory().getPath()+ File.separator+"test"+File.separator;
            String video=path+"c.mp4";
            ffmpegTool.decodToImageWithCall(video.replaceAll(File.separator,"/")
                    ,Environment.getExternalStorageDirectory().getPath()
                    + File.separator+"test2"+File.separator,0,10);
        }
    }.start();