在Android端FFMPEG对于视频的剪切、转码、添加水印

这篇文章根据徐福记的文章学的。特别感谢!

涉及到的库导入以及相关配置。比如build.gradle,CMAKE可以参考之前的音频文章。https://blog.csdn.net/howlaa/article/details/112977790

1.视频的转码包括格式、码率、尺寸大小等转换。-f代表强制转换格式,-b代表码率,-s代表尺寸,-r代表帧率:

    /**
     * 使用ffmpeg命令行进行视频转码
     * @param srcFile 源文件
     * @param targetFile 目标文件(后缀指定转码格式)
     * @return 转码后的文件
     */
    public static String[] transformVideo(String srcFile, String targetFile){
        String transformVideoCmd = "ffmpeg -i %s -r 25 -b 200 -s 1080x720 %s";
        transformVideoCmd = String.format(transformVideoCmd, srcFile, targetFile);
        return transformVideoCmd.split(" ");//以空格分割为字符串数组
    }

所以上面的命令就很容易理解了,把源视频文件转码成帧率为25,码率为200,尺寸为1080*720的视频文件。

2.视频的剪切

视频的剪切就是从指定时间开始,剪切指定时长。-ss代表开始时间(start seconds),单位为秒。-t代表时长。

    /**
     * 使用ffmpeg命令行进行视频剪切
     * @param srcFile 源文件
     * @param startTime 剪切的开始时间(单位为秒)
     * @param duration 剪切时长(单位为秒)
     * @param targetFile 目标文件
     * @return 剪切后的文件
     */
    public static  String[] cutVideo(String srcFile, int startTime, int duration, String targetFile){
        String cutVideoCmd = "ffmpeg -i %s -ss %d -t %d %s";
        cutVideoCmd = String.format(cutVideoCmd, srcFile, startTime, duration, targetFile);
        return cutVideoCmd.split(" ");//以空格分割为字符串数组
    }

所以,上面的命令也很清楚了。那就是对于源文件,从指定时间开始,时长多少秒,进行剪切。

3.视频的截图

视频截图是从当前视频帧截取一帧画面,保存为指定格式的图片,使用image2工具。

    /**
     * 使用ffmpeg命令行进行视频截图
     * @param srcFile 源文件
     * @param size 图片尺寸大小
     * @param targetFile 目标文件
     * @return 截图后的文件
     */
    public static  String[] screenShot(String srcFile, String size, String targetFile){
        String screenShotCmd = "ffmpeg -i %s -f image2 -t 0.001 -s %s %s";
        screenShotCmd = String.format(screenShotCmd, srcFile, size, targetFile);
        return screenShotCmd.split(" ");//以空格分割为字符串数组
    }

还记得上面我们说过的这几个命令的意义吗?所以,上面的命令行我们可以很快理解:

-f强制格式转换,-t时间 -s尺寸

4.添加水印

给视频添加水印,就包括在视频上打上文字和图片。

    /**
     * 使用ffmpeg命令行给视频添加水印
     * @param srcFile 源文件
     * @param waterMark 水印文件路径
     * @param targetFile 目标文件
     * @return 添加水印后的文件
     */
    public static  String[] addWaterMark(String srcFile, String waterMark, String targetFile){
        String waterMarkCmd = "ffmpeg -i %s -i %s -filter_complex overlay=0:0 %s";
        waterMarkCmd = String.format(waterMarkCmd, srcFile, waterMark, targetFile);
        return waterMarkCmd.split(" ");//以空格分割为字符串数组
    }

-i 对于文件的指定,-filter_complex滤波器, overlay图片在视频上的遮罩位置。

文字水印,其实也是把文字转换成图片,最终都是以图片形式加在视频上的。

文字转图片如下:

 /**
     * 文本转成Bitmap
     * @param text 文本内容
     * @param context 上下文
     * @return 图片的bitmap
     */
    private static Bitmap textToBitmap(String text , Context context) {
        float scale = context.getResources().getDisplayMetrics().scaledDensity;
        TextView tv = new TextView(context);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        tv.setLayoutParams(layoutParams);
        tv.setText(text);
        tv.setTextSize(scale * TEXT_SIZE);
        tv.setGravity(Gravity.CENTER_HORIZONTAL);
        tv.setDrawingCacheEnabled(true);
        tv.setTextColor(TEXT_COLOR);
        tv.setBackgroundColor(Color.WHITE);
        tv.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
        tv.buildDrawingCache();
        Bitmap bitmap = tv.getDrawingCache();
        int rate = bitmap.getHeight() / 20;
        return Bitmap.createScaledBitmap(bitmap, bitmap.getWidth()/rate, 20, false);
    }
 
    /**
     * 文字生成图片
     * @param filePath filePath
     * @param text text
     * @param context context
     * @return 生成图片是否成功
     */
    public static boolean textToPicture(String filePath, String text , Context context){
        Bitmap bitmap = textToBitmap(text , context);
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(filePath);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }finally {
            try {
                if(outputStream != null){
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

5.视频截取gif动图

    /**
     * 使用ffmpeg命令行进行视频转成Gif动图
     * @param srcFile 源文件
     * @param startTime 开始时间
     * @param duration 截取时长
     * @param targetFile 目标文件
     * @return Gif文件
     */
    public static  String[] generateGif(String srcFile, int startTime, int duration, String targetFile){
        //String screenShotCmd = "ffmpeg -i %s -vframes %d -f gif %s";
        String screenShotCmd = "ffmpeg -i %s -ss %d -t %d -s 320x240 -f gif %s";
        screenShotCmd = String.format(screenShotCmd, srcFile, startTime, duration, targetFile);
        return screenShotCmd.split(" ");//以空格分割为字符串数组
    }

根据命令,我们就可以理解这句命令行的含义。

6、图片合成视频

这个就是把文件的有序命名图片,使用-image2合成视频:

    /**
     * 使用ffmpeg命令行进行图片合成视频
     * @param srcFile 源文件
     * @param targetFile 目标文件(mpg格式)
     * @return 合成的视频文件
     */
    public static  String[] pictureToVideo(String srcFile, String targetFile){
        //-f image2:代表使用image2格式,需要放在输入文件前面
        String combineVideo = "ffmpeg -f image2 -r 1 -i %simg#d.jpg -vcodec mpeg4 %s";
        combineVideo = String.format(combineVideo, srcFile, targetFile);
        combineVideo = combineVideo.replace("#", "%");
        Log.i("VideoHandleActivity", "combineVideo=" + combineVideo);
        return combineVideo.split(" ");//以空格分割为字符串数组
    }

我想这个srcFile应该是那个文件夹,图片以img1.jpg,img2.jpg等命名。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值