FFmpeg将图像水印添加到视频过程非常慢 [英] FFmpeg adding image watermark to video process is very slow

查看:134
本文介绍了FFmpeg将图像水印添加到视频过程非常慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在FFmpeg的帮助下向视频添加图像水印,但是FFmpeg使用以下命令花费了过多的时间-

I am adding image watermark to video with help of FFmpeg but FFmpeg takes an inordinate amount of time with the below command-

String[] cmd = {"-i",videoPath, "-i", waterMark.toString(),"-filter_complex","overlay=5:5","-codec:a", "copy", outputPath};

所以我尝试了另一个命令,该命令稍微快一点,但是增加了输出文件的大小(我不想要)

so i tried another command which was little bit faster but increase output file size(which i do not want)

String[] cmd = {"-y","-i", videoPath, "-i", waterMark.toString(), "-filter_complex", "overlay=5:5", "-c:v","libx264","-preset", "ultrafast", outputPath};

请有人向我说明如何在不增加输出大小的情况下提高FFmpeg加水印速度.谢谢.

Some one please explain to me how to increase the speed of FFmpeg watermarking speed without increasing the size of output. Thanks.

推荐答案

您提到7MB视频需要30-60秒.

You mentioned that a 7MB video takes between 30-60 seconds.

在速度和质量之间进行选择时总是需要权衡的.

There is always a trade off when choosing between speed and quality.

我使用7MB的文件在手机上进行了测试,它花了13秒的时间,但仍然很慢,但是我们不能指望有比这更好的了.

I tested on my phone using a 7MB file and it took 13 seconds, still slow, but we can't expect much better then that.

提高速度的方法:

  • 使用 -r 命令降低帧速率
  • 使用 -b:v -b:a 命令更改比特率
  • 使用 -crf 更改恒定速率因子.默认值为 21
  • Lowering the frame rate, using the -r command
  • Changing the bitrate, using the -b:v and -b:a commands
  • Change the Constant Rate Factor, using -crf. The default value is 21

量化标度的范围是0-51:其中0为无损,默认为23,最坏可能为51.较低值表示较高的质量,主观理智的范围是18-28.考虑18在视觉上无损或近似如此:它应该看起来与输入相同或几乎相同,但在技术上并非无损.

The range of the quantizer scale is 0-51: where 0 is lossless, 23 is default, and 51 is worst possible. A lower value is a higher quality and a subjectively sane range is 18-28. Consider 18 to be visually lossless or nearly so: it should look the same or nearly the same as the input but it isn't technically lossless.

这是我发现在大多数android设备上最有效的方法:

This is what I have found works the best on most android devices:

String[] s = {"-i", VideoPath, "-i", ImagePath, "-filter_complex", "[0:v]pad=iw:if(lte(ih\\,iw)\\,ih\\,2*trunc(iw*16/9/2)):(ow-iw)/2:(oh-ih)/2[v0];[1:v][v0]scale2ref[v1][v0];[v0][v1]overlay=x=(W-w)/2:y=(H-h)/2[v]", "-map", "[v]", "-map", "0:a", "-c:v", "libx264", "-preset", "ultrafast", "-r", myFrameRate, directoryToStore[0] + "/" + SavedVideoName};

我略微降低了帧速率,您可以尝试最适合自己的帧速率.我正在使用 mp4parser 来获取帧频.

I reduced my framerate slightly, you can experiment what works best for you. I'm using mp4parser to retrieve the frame rate.

我必须赞扬@Gyan,它为我提供了一种完美缩放放置在视频顶部的图像的方法,您可以看看我问的问题

I have to give credit to @Gyan that provided me with a way to perfectly scale images that is being placed on top of a video, you can look at the question I asked here.

如果不确定帧速率,可以将其从命令中删除,然后首先测试速度是否降低.

If you are unsure about the frame rate, you can remove it from the command and first test if your speed is reduced.

尝试一下,如果有任何疑问,请询问.

Try it, if you have any questions, please ask.

OP选择使用以下命令:

OP opted to go with the following command:

String[] cmd = {"-y","-i", videoPath, "-i", waterMark.toString(), "-filter_complex", "overlay=(main_w-overlay_w-10):5", "-map", "0:a","-c:v", "libx264", "-crf", "28","-preset", "ultrafast" ,outputPath};


修改

只需添加我提到的命令,并提供有关如何使用它的详细说明,等等:

Just to add on the command I mentioned and provide a detailed explanation of how to use it etc:

String[] cmd = {"-i", videoPath, "-i", waterMark.toString(), "-filter_complex", "[0:v]pad=iw:if(lte(ih\\,iw)\\,ih\\,2*trunc(iw*16/9/2)):(ow-iw)/2:(oh-ih)/2[v0];[1:v][v0]scale2ref[v1][v0];[v0][v1]overlay=x=(W-w)/2:y=(H-h)/2[v]", "-map", "[v]", "-map", "0:a", "-c:v", "libx264", "-preset", "ultrafast", "-r", myFrameRate, outputPath};

这是针对显示宽高比为 16:9 的设备.如果要让该滤镜在所有设备上都起作用,则必须获取设备的宽高比,并分别更改滤镜 16/9/2 .

This is for device's that has a display aspect ratio of 16:9. If you want this filter to work on all device's you will have to get the aspect ratio of the device and change the filter 16/9/2 respectively.

您可以通过创建以下方法来获得设备的宽高比:

You can get the device aspect ratio by creating this methods:

int gcd(int p, int q) { 
    if (q == 0) return p; 
    else return gcd(q, p % q); 
} 
void ratio(int a, int b) { 
    final int gcd = gcd(a,b); 
    if(a > b) { 
        setAspectRatio(a/gcd, b/gcd); 
    } else { 
        setAspectRatio(b/gcd, a/gcd); 
    } 
} 
void setAspectRatio(int a, int b) { 
    System.out.println("aspect ratio = "+a + " " + b); 
    //This is the string that will be used in the filter (instead of hardcoding 16/9/2
    filterAspectRatio = a + "/" + b + "/" + "2"; 
}

现在您具有正确的宽高比,可以相应地更改滤镜了.

Now you have the correct aspect ratio and you can change the filter accordingly.

接下来,创建一个水印并将其添加到视图中,使该视图的设备大小( match_parent )并将水印缩放/放置在所需位置.然后,您可以通过调用以下命令获取位图:

Next, create a watermark and add it to a view, make that view the size of the device (match_parent) and scale/place the watermark where you would like it to be. You can then get the bitmap by calling:

Bitmap waterMarkBitmap = watermarkView.getDrawingCache();

并从 Bitmap 创建文件,如下所示:

and create a file from the Bitmap, like this:

String outputFilename = "myCoolWatermark.png"; //provide a name for you saved watermark
File path = Environment.getExternalStorageDirectory(); //this can be changed to where you want to store the bitmap
File waterMark = new File(path, outputFilename); 

try (FileOutputStream out = new FileOutputStream(waterMark)) { 
    waterMarkBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // PNG is a lossless format, the compression factor (100) is ignored 
} catch (IOException e) { 
    e.printStackTrace(); 
}

水印已创建并可以重复使用,也可以在完成后将其删除.

The watermark is created and can be reused, or you can delete it when you are done with it.

现在您可以调用上面提到的命令.

Now you can call the command mentioned above.

这篇关于FFmpeg将图像水印添加到视频过程非常慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆