Tus*_*iya -1 android ffmpeg android-ffmpeg
我在 FFmpeg 的帮助下向视频添加图像水印,但 FFmpeg 使用以下命令花费了过多的时间 -
String[] cmd = {"-i",videoPath, "-i", waterMark.toString(),"-filter_complex","overlay=5:5","-codec:a", "copy", outputPath};
所以我尝试了另一个命令,它有点快,但增加了输出文件的大小(我不想要)
String[] cmd = {"-y","-i", videoPath, "-i", waterMark.toString(), "-filter_complex", "overlay=5:5", "-c:v","libx264","-preset", "ultrafast", outputPath};
有人请向我解释如何在不增加输出大小的情况下提高FFmpeg水印速度的速度。谢谢。
您提到 7MB 的视频需要 30-60 秒。
在速度和质量之间进行选择时,总是需要权衡取舍。
我使用 7MB 文件在我的手机上进行了测试,花了 13 秒,仍然很慢,但我们不能期望比这更好。
提高速度的方法:
-r命令-b:v和-b:a命令更改比特率-crf。默认值为21量化器标度的范围是 0-51:其中 0 是无损,23 是默认值,51 是最坏的。甲低的值是一个更高的质量和主观理智的范围是18-28。将 18 视为视觉无损或接近无损:它应该与输入看起来相同或几乎相同,但在技术上并非无损。
这是我发现在大多数 android 设备上效果最好的:
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检索帧速率。
我必须感谢@Gyan,它为我提供了一种完美缩放放置在视频之上的图像的方法,您可以查看我在这里提出的问题。
如果您不确定帧速率,可以将其从命令中删除,然后首先测试您的速度是否降低。
试试看,有问题请追问。
OP 选择使用以下命令:
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};
编辑
只是添加我提到的命令并提供如何使用它等的详细说明:
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分别更改过滤器。
您可以通过创建以下方法来获取设备纵横比:
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"; 
}
现在您有了正确的纵横比,您可以相应地更改过滤器。
接下来,创建一个水印并将其添加到视图中,使该视图成为设备的大小 ( match_parent) 并将水印缩放/放置在您想要的位置。然后您可以通过调用获取位图:
Bitmap waterMarkBitmap = watermarkView.getDrawingCache();
并从 中创建一个文件Bitmap,如下所示:
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(); 
}
水印已创建并可重复使用,或者您可以在完成后将其删除。
现在你可以调用上面提到的命令了。