美文网首页FFmpegAndroid开发Android知识
android端使用ffmpeg给视频添加图片水印

android端使用ffmpeg给视频添加图片水印

作者: 书柜里的松鼠 | 来源:发表于2017-04-18 15:40 被阅读3784次

直接举个栗子:

public static String[] addwaterMark(String imageUrl,String videoUrl,String outputUrl){
        String[] commands = new String[9];
        commands[0] = "ffmpeg";
        //输入
        commands[1] = "-i";
        commands[2] = videoUrl;
        //水印
        commands[3] = "-i";
        commands[4] = imageUrl;//此处的图片地址换成带透明通道的视频就可以合成动态视频遮罩。
        commands[5] = "-filter_complex";
        commands[6] = "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2";
        //覆盖输出
        commands[7] = "-y";//直接覆盖输出文件
        //输出文件
        commands[8] = outputUrl;
        return commands;
    }

private void makeVideo(){
        final String[] _commands=addwaterMark(imageUrl,videoUrl,outputUrl);
        Runnable compoundRun=new Runnable() {
            @Override
            public void run() {
                FFmpegKit.execute(_commands, new FFmpegKit.KitInterface() {
                    @Override
                    public void onStart() {
                        Log.d("FFmpegLog LOGCAT","FFmpeg 命令行开始执行了...");
                    }

                    @Override
                    public void onProgress(int progress) {
                        Log.d("FFmpegLog LOGCAT","done com"+"FFmpeg 命令行执行进度..."+progress);
                    }

                    @Override
                    public void onEnd(int result) {
                        Log.d("FFmpegLog LOGCAT","FFmpeg 命令行执行完成...");
                    }
                });
            }
        };
        ThreadPoolUtils.execute(compoundRun);
    }

addwaterMark()中的videoUrl是原始文件地址,imageUrl是水印图片地址,outputUrl是视频输出地址。
-filter_complex 参数是表示使用混合滤镜把图片叠加到视频上。
overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 是将图片居中,当然这里的具体位置可以自己调。
一般来说,加个水印就这样就可以了。

然而,实际中我们总是需要来点大小的调整。
使用scale参数可以调整水印大小。
像这样

String[] commands = new String[9];
commands[0] = "ffmpeg";
//输入
commands[1] = "-i";
commands[2] = videoUrl;
//水印
commands[3] = "-i";
commands[4] = imageUrl;//此处的图片地址换成带透明通道的视频就可以合成动态视频遮罩。
commands[5] = "-filter_complex";
commands[6] = "[1:v]scale=100:200[s];[0:v][s]overlay=0:0";
//覆盖输出
commands[7] = "-y";//直接覆盖输出文件
//输出文件
commands[8] = outputUrl;
return commands;

好,现在你可以随意添加任意大小位置的水印了。
那么,能不能再给力一点?我们使用两张图片叠加双重水印。
命令行格式如下:

String[] commands = new String[11];
commands[0] = "ffmpeg";
//输入
commands[1] = "-i";
commands[2] = videoUrl;
//水印
commands[3] = "-i";
commands[4] = image1;
commands[5] = "-i";
commands[6] = image2;
commands[7] = "-filter_complex";
commands[8] = "[1:v]scale=100:100[img1];[2:v]scale=1280:720[img2];[0:v][img1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[bkg];[bkg][img2]overlay=0:0";
//覆盖输出
commands[9] = "-y";//直接覆盖输出文件
//输出文件
commands[10] = outputUrl;
return commands;
附1:

用来当水印的图片也支持gif格式,那么gif要在整个视频播放阶段循环的话就请使用-ignore_loop参数。这个参数的值为1则忽略gif文件本身的循环设置,为0的话则使用文件本身的设置。
比如这样:

String[] commands = new String[11];
commands[0] = "ffmpeg";
//输入
commands[1] = "-i";
commands[2] = videoUrl;
//水印
commands[3] = "-ignore_loop";
commands[3] = "0";
commands[3] = "-i";
commands[4] = image1.gif;
commands[5] = "-i";
commands[6] = image2;
commands[7] = "-filter_complex";
commands[8] = "[1:v]scale=100:100[img1];[2:v]scale=1280:720[img2];[0:v][img1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[bkg];[bkg][img2]overlay=0:0";
//覆盖输出
commands[9] = "-y";//直接覆盖输出文件
//输出文件
commands[10] = outputUrl;
return commands;
附2:

以上命令也适用与透明视频的叠加。把图片地址换成带透明通道的视频文件的地址就好了。(带透明通道的视频素材网上可以下载到很多,一般都是mov格式)(然而不知道怎么像gif那样设置循环,叠加的视频仅播放一次。有知道的同学分享下经验呗。)

附3:

ffmpeg的命令行参数除了头尾,中间各组的顺序是无关的,但是各组参数内部不能放错。比如属于设置滤镜的参数穿插到了输出里了的话就会出错。


相关:
在android studio中使用FFmpeg
FFmpeg命令行语法之-filter_complex


使用ffmpeg添加文字水印一直没有成功,打包了freetype也没有搞定。暂时只好把文字生成为png图片凑合一下。有没有小伙伴提供下思路或者范例的?

相关文章

网友评论

  • 991e6fbb6177:大佬,按照你的命令格式(ffmpeg -i /sdcard/affmpeg/video.mp4 -i /sdcard/affmpeg/watermark.png -filter_complex [1:v]scale=1920:1080[s];[0:v][s]overlay=0:0 -y /sdcard/affmpeg/output.mp4), 可以导出MP4文件,但是不能播放;还有就是我按这个方式(ffmpeg -i /sdcard/affmpeg/video.mp4 -i /sdcard/affmpeg/watermark.png -b:v 1500K -filter_complex [1:v]scale=1920:1080[s];[0:v][s]overlay=0:0 -y /sdcard/affmpeg/output.mp4)设置码率之后,会崩溃,请指教,谢谢。
    书柜里的松鼠:@巴巴罗萨_3c7e 光这么我也看不出什么来,不知道啊。
  • 991e6fbb6177:楼主好,不管是导入你的工程,还是按照你的文章来操作,都会出现这个底层错误,请指教,谢谢。
    A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x18 in tid 25549 (AsyncTask #9)

    [ 09-02 20:17:33.521 425: 425 W/ ]
    debuggerd: handling request: pid=24833 uid=11036 gid=11036 tid=25549

    [ 09-02 20:17:33.545 584:25538 I/ ]
    virtual buffer_md_t *hw::COutMetaSplit::splitOutMeta(hw::CDataTable &, hw::ISensorModuleSpec *), ae_state=2, trigger_id=0, preflash_state=0, need_lcd_compension=0,flash_state=2, capflash_ae_effect=0, resume_ae_doing=0ae_mode=1, ae_precapture=0
    书柜里的松鼠:@巴巴罗萨_3c7e 这个提示其实也并不底层,然后这样也看不出什么,估摸着是文件不能加载之类。多打点log看看。
  • 魏魏魏魏:博主,请教一下:我的需求是将MP4文件的字幕流取出来(视频文件是在网上),我找到一个ffmpeg的命令行——ffmpeg -i Life.of.Pi.has.subtitles.mkv-map 0:s:0 sub1.srt(链接地址:http://www.voidcn.com/article/p-ttzcvbvh-sh.html)。我已经按照文章的提示编译了一个so,请问如何调用执行这个命令行呢?
  • EricKwoc:我想把logo和字幕一起压制到视频里
    我的命令是
    `ffmpeg -i source.mkv -i Logo_White.ico -filter_complex "[0:v][1:v]overlay[logo];[logo]ass=source.ass[sub]" -map [sub] output.final.mp4`
    执行成功没有报错,但是出来的文件没有音频流,请问是什么问题呢?
    EricKwoc:@EricKwoc 更正,是 -map 0,0 不是 -map 0:0
    EricKwoc:问题解决了
    `ffmpeg -i source.mkv -i Logo_White.ico -filter_complex "[0:v][1:v]overlay[logo];[logo]ass=source.ass[sub]" -map [sub] -map 0:0 output.final.mp4`
    这样就好了
  • 成都啊噢网络科技有限公司:添加图片水印,速度很慢,有法解决吗?
    书柜里的松鼠:@xxx小黄瓜 基本没有
  • 吉凶以情迁:加上去之后视频帧一直是第一帧
    书柜里的松鼠:@情随事迁666 可以看一下我另一篇关于命令的语法介绍的帖子。
    另外,文字的话比较特殊,一种方法是使用freetype库,但是这个我目前使用的时候还不是很理想,不知哪里没搞对。实际中我使用的另一种方法是先把文字生成为图片再合成到视频上。
    吉凶以情迁:@书柜里的松鼠 解决了,我多传递了一个参数,请问加多个文字和图片混用在一起的水印怎么搞,网上的教程都看不明白,我比较喜欢一条直接的命令,别人那个各种类似语法我输入发现并不是想要的结果,出错了,很郁闷
    书柜里的松鼠:光这么说,实在是不知道发生了什么
  • 护她此生周全:大神,你好,我这边图片水印加上去了,但是一个10秒的视频都要估计5分钟,这速度能不能得到优化,如果不能,还有什么好的解决方案,项目这边急!求指教,跪求
    书柜里的松鼠:@护她此生周全 这个确实是很慢的,但是5分钟似乎也太长了。和手机本身的性能有点关系。
  • 逸云天:楼主,您好。可以直接给gif图添加图片水印吗?我试了类似的命令没成功。不知楼主有没有方法
    书柜里的松鼠:@逸云天 用视频的命令应该是不行啦。用图片合并的命令行不行我也不确定,你试试?
  • d3f62d9df74f:添加水印时报错,Encoder (codec aac) not found for output stream #0:1 请问这个是什么问题啊?
    书柜里的松鼠:没有aac编码库,你需要重新编译一个包含aac的so
  • 766a546ee35d:你好,怎么能保证添加水印大小统一性? 我现在视频不一样,水印显示的大小就不一样。谢谢
    书柜里的松鼠: @lance_0ea7 你得根据不同的视频大小使用不同的scale值 。
  • BertSir:Encoder (codec mpeg4) not found for output stream #0:0这个是什么意思呢
    书柜里的松鼠: @BertSir 这倒没有仔细查过有没有
    BertSir:@书柜里的松鼠 VCamera理论上自带mp4编码器了呀
    书柜里的松鼠: @BertSir mp4的编码器没找到。
  • 0d2de636ee71:博主 能留个qq吗 向您请教一下啊
  • 0d2de636ee71:我那边显示和的和你的那个文件类型不一样 我的全是 .c 或者.h 而你的全是 c++, 我不会重新编译啊 楼主
  • 0d2de636ee71:我导入你的项目下面的jni里面的c++文件报错
    并且 Caused by: java.lang.UnsatisfiedLinkError: No implementation found for int com.user.video.ffmpegCentre.FFmpegKit.run(java.lang.String[]) (tried Java_com_user_video_ffmpegCentre_FFmpegKit_run and Java_com_user_video_ffmpegCentre_FFmpegKit_run___3Ljava_lang_String_2)
    at com.user.video.ffmpegCentre.FFmpegKit.run(Native Method)
    at com.user.video.ffmpegCentre.FFmpegKit$1.doInBackground(FFmpegKit.java:31)
    at com.user.video.ffmpegCentre.FFmpegKit$1.doInBackground(FFmpegKit.java:22)
    at android.os.AsyncTask$2.call(AsyncTask.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
    at java.lang.Thread.run(Thread.java:818) 
    书柜里的松鼠: @岁月无声_fd70 15051607
    不过别太指望,我也是刚开始研究这个。
    0d2de636ee71:@书柜里的松鼠 博主 能留个qq吗 向您请教一下啊
    书柜里的松鼠: @岁月无声_fd70 看错误信息,感觉是不是libs下的so文件没有编译?不过我猜的。光这么我也看不出多少东西。

本文标题:android端使用ffmpeg给视频添加图片水印

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