FFmpeg 应用多个过滤器(徽标叠加、亮度变化和文本叠加)
FFmpeg apply multiple filters (Logo overlay, Brightness change and text overlay)
我正在尝试使用 Android 中的 ffmpeg 向 png 文件添加三个过滤器(我正在使用 writing mind 库)。
到目前为止,我设法将 cmd 整合在一起:
-i /storage/emulated/0/videoApp/temp/firstFrameOfMergedVideo.png
-i /storage/emulated/0/videoApp/temp/logo.png
-filter_complex
第一个过滤器
[1:v]scale=h=-1:w=100[overlay_scaled],[0:v][overlay_scaled]overlay=eval=init:x=W-100-W*0.1:y=W*0.1,
第二个过滤器
drawtext=fontfile=/system/fonts/Roboto-Regular.ttf:text='xbsg':fontcolor=white:fontsize=60:box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-(text_h*2)-(h*0.1):enable='between(t,0,2)',
第三个过滤器
drawtext=fontfile=/system/fonts/Roboto-Regular.ttf:text='cbeh':fontcolor=white:fontsize=30:box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-text_h-(h*0.1)+25:enable='between(t,0,2)',
第四个过滤器
eq=contrast=1:brightness=0.26180276:saturation=1:gamma=1:gamma_r=1:gamma_g=1:gamma_b=1:gamma_weight=1
-c:a
copy
/storage/emulated/0/videoApp/temp/frameWithFilters.png
现在我正在尝试使用 ,
来分离过滤器,但我也尝试过 ;
它让我退缩:
Input #0, png_pipe, from '/storage/emulated/0/videoApp/temp/firstFrameOfMergedVideo.png':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: png, rgb24(pc), 1080x1920, 25 tbr, 25 tbn, 25 tbc
Input #1, png_pipe, from '/storage/emulated/0/videoApp/temp/logo.png':
Duration: N/A, bitrate: N/A
Stream #1:0: Video: png, rgba(pc), 528x582, 25 tbr, 25 tbn, 25 tbc
[NULL @ 0xf265d800] Unable to find a suitable output format for ','
,: Invalid argument
如果我单独应用它们,它们就会起作用。
我是 ffmpeg 的新手,如有任何帮助,我们将不胜感激。
终于想通了
过滤器必须作为一个字符串传入字符串数组
例如 filterArray[2] = "-filter_complex" filterArray[3] ="rest of filter".
如果有人好奇,下面的代码片段最多可应用三个过滤器(如果存在于视频中)。这些滤镜可以是亮度变化(需要先应用,以便其他滤镜可以应用在上面),徽标图像的叠加层放置在右上角并按比例缩小到特定大小,两个文本叠加层放置一个在下面另一个在左下角。
public void applyFiltersToImage(String srcPath, String outPath, String logoPath, String name, String function, float brightness, ProgressListener progressListener) {
List<String> cmdList = new ArrayList<>();
cmdList.add("-i");
cmdList.add(srcPath);
if (logoPath != null) {
cmdList.add("-i");
cmdList.add(logoPath);
}
cmdList.add("-filter_complex");
StringBuilder filterBuilder = new StringBuilder();
if (brightness != 0) {
filterBuilder
.append("eq=contrast=1:brightness=")
.append(brightness)
.append(":saturation=1:gamma=1:gamma_r=1:gamma_g=1:gamma_b=1:gamma_weight=1[v]");
if (logoPath != null || name != null || function != null)
filterBuilder.append(";");
}
if (logoPath != null) {
filterBuilder
.append("[1:v]scale=h=-1:w=")
.append("100")
.append("[overlay_scaled],")
.append(brightness != 0 ? "[v]" : "[0:v]")
.append("[overlay_scaled]overlay=eval=init:x=W-")
.append("100")
.append("-W*0.1:y=W*0.1[v]");
if (name != null || function != null)
filterBuilder.append(";[v]");
}
if (name != null || function != null) {
if(brightness != 0 && logoPath == null)
filterBuilder.append("[v]");
filterBuilder
.append("drawtext=fontfile=")
.append("/system/fonts/Roboto-Regular.ttf")
.append(":text='")
.append(name)
.append("':fontcolor=white:fontsize=")
.append("60")
.append(":box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-(text_h*2)-(h*0.1):enable=\'between(t,0,2)\'")
.append(",drawtext=fontfile=")
.append("/system/fonts/Roboto-Regular.ttf")
.append(":text='")
.append(function)
.append("':fontcolor=white:fontsize=")
.append("30")
.append(":box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-text_h-(h*0.1)+25:enable=\'between(t,0,2)\'[v]");
}
cmdList.add(filterBuilder.toString());
cmdList.add("-map");
cmdList.add("[v]");
cmdList.add(outPath);
String[] cmd = new String[cmdList.size()];
for (int i = 0; i < cmdList.size(); i++) {
cmd[i] = cmdList.get(i);
}
executeCmd(cmd, progressListener, outPath);
}
我正在尝试使用 Android 中的 ffmpeg 向 png 文件添加三个过滤器(我正在使用 writing mind 库)。
到目前为止,我设法将 cmd 整合在一起:
-i /storage/emulated/0/videoApp/temp/firstFrameOfMergedVideo.png
-i /storage/emulated/0/videoApp/temp/logo.png
-filter_complex
第一个过滤器
[1:v]scale=h=-1:w=100[overlay_scaled],[0:v][overlay_scaled]overlay=eval=init:x=W-100-W*0.1:y=W*0.1,
第二个过滤器
drawtext=fontfile=/system/fonts/Roboto-Regular.ttf:text='xbsg':fontcolor=white:fontsize=60:box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-(text_h*2)-(h*0.1):enable='between(t,0,2)',
第三个过滤器
drawtext=fontfile=/system/fonts/Roboto-Regular.ttf:text='cbeh':fontcolor=white:fontsize=30:box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-text_h-(h*0.1)+25:enable='between(t,0,2)',
第四个过滤器
eq=contrast=1:brightness=0.26180276:saturation=1:gamma=1:gamma_r=1:gamma_g=1:gamma_b=1:gamma_weight=1
-c:a
copy
/storage/emulated/0/videoApp/temp/frameWithFilters.png
现在我正在尝试使用 ,
来分离过滤器,但我也尝试过 ;
它让我退缩:
Input #0, png_pipe, from '/storage/emulated/0/videoApp/temp/firstFrameOfMergedVideo.png':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: png, rgb24(pc), 1080x1920, 25 tbr, 25 tbn, 25 tbc
Input #1, png_pipe, from '/storage/emulated/0/videoApp/temp/logo.png':
Duration: N/A, bitrate: N/A
Stream #1:0: Video: png, rgba(pc), 528x582, 25 tbr, 25 tbn, 25 tbc
[NULL @ 0xf265d800] Unable to find a suitable output format for ','
,: Invalid argument
如果我单独应用它们,它们就会起作用。
我是 ffmpeg 的新手,如有任何帮助,我们将不胜感激。
终于想通了
过滤器必须作为一个字符串传入字符串数组 例如 filterArray[2] = "-filter_complex" filterArray[3] ="rest of filter".
如果有人好奇,下面的代码片段最多可应用三个过滤器(如果存在于视频中)。这些滤镜可以是亮度变化(需要先应用,以便其他滤镜可以应用在上面),徽标图像的叠加层放置在右上角并按比例缩小到特定大小,两个文本叠加层放置一个在下面另一个在左下角。
public void applyFiltersToImage(String srcPath, String outPath, String logoPath, String name, String function, float brightness, ProgressListener progressListener) {
List<String> cmdList = new ArrayList<>();
cmdList.add("-i");
cmdList.add(srcPath);
if (logoPath != null) {
cmdList.add("-i");
cmdList.add(logoPath);
}
cmdList.add("-filter_complex");
StringBuilder filterBuilder = new StringBuilder();
if (brightness != 0) {
filterBuilder
.append("eq=contrast=1:brightness=")
.append(brightness)
.append(":saturation=1:gamma=1:gamma_r=1:gamma_g=1:gamma_b=1:gamma_weight=1[v]");
if (logoPath != null || name != null || function != null)
filterBuilder.append(";");
}
if (logoPath != null) {
filterBuilder
.append("[1:v]scale=h=-1:w=")
.append("100")
.append("[overlay_scaled],")
.append(brightness != 0 ? "[v]" : "[0:v]")
.append("[overlay_scaled]overlay=eval=init:x=W-")
.append("100")
.append("-W*0.1:y=W*0.1[v]");
if (name != null || function != null)
filterBuilder.append(";[v]");
}
if (name != null || function != null) {
if(brightness != 0 && logoPath == null)
filterBuilder.append("[v]");
filterBuilder
.append("drawtext=fontfile=")
.append("/system/fonts/Roboto-Regular.ttf")
.append(":text='")
.append(name)
.append("':fontcolor=white:fontsize=")
.append("60")
.append(":box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-(text_h*2)-(h*0.1):enable=\'between(t,0,2)\'")
.append(",drawtext=fontfile=")
.append("/system/fonts/Roboto-Regular.ttf")
.append(":text='")
.append(function)
.append("':fontcolor=white:fontsize=")
.append("30")
.append(":box=1:boxcolor=0x7FFFD4@0.5:boxborderw=20:x=20:y=h-text_h-(h*0.1)+25:enable=\'between(t,0,2)\'[v]");
}
cmdList.add(filterBuilder.toString());
cmdList.add("-map");
cmdList.add("[v]");
cmdList.add(outPath);
String[] cmd = new String[cmdList.size()];
for (int i = 0; i < cmdList.size(); i++) {
cmd[i] = cmdList.get(i);
}
executeCmd(cmd, progressListener, outPath);
}