Skip to content

Commit

Permalink
Filter arguments escaping, fix #26. (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
kokorin authored Dec 30, 2021
1 parent 0a9bcc4 commit 0186c42
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 18 deletions.
24 changes: 16 additions & 8 deletions src/main/java/com/github/kokorin/jaffree/ffmpeg/GenericFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public GenericFilter addArgumentEscaped(final String key, final String value) {
*
* @param value value
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#toc-Notes-on-filtergraph-escaping">
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping">
* filtergraph escaping</a>
*/
public GenericFilter addArgument(final String value) {
Expand All @@ -125,7 +125,7 @@ public GenericFilter addArgument(final String value) {
*
* @param value value
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#toc-Notes-on-filtergraph-escaping">
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping">
* filtergraph escaping</a>
*/
public GenericFilter addArgumentEscaped(final String value) {
Expand All @@ -148,7 +148,7 @@ public GenericFilter addOutputLink(final String link) {
* Prints filter description according to ffmpeg filtergraph syntax.
*
* @return filter description
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#toc-Filtergraph-syntax-1">
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#Filtergraph-syntax-1">
* filtergraph syntax</a>
*/
@Override
Expand Down Expand Up @@ -180,12 +180,16 @@ public String getValue() {
}

/**
* A first level escaping affects the content of each filter option value, which may contain
* the special character {@code}:{@code} used to separate values, or one of
* the escaping characters {@code}\'{@code}.
* An escaping affects the content of each filter option value, which may contain the special
* character.
* <p>
* This method implements 1st and 2nd level escaping. 3rd level escaping (shell command) is done
* by Java Process API.
*
* @param value value to be escaped
* @return escaped value
* @see <a href="https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping">
* filtergraph escaping</a>
*/
static String escape(final String value) {
if (value == null) {
Expand All @@ -194,7 +198,11 @@ static String escape(final String value) {

return value
.replace("\\", "\\\\")
.replace(":", "\\:")
.replace("'", "\\'");
.replace(":", "\\\\:")
.replace(",", "\\,")
.replace("[", "\\[")
.replace("]", "\\]")
.replace(";", "\\;")
.replace("'", "\\\\\\'");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.github.kokorin.jaffree.Artifacts;
import com.github.kokorin.jaffree.Config;
import com.github.kokorin.jaffree.LogLevel;
import com.github.kokorin.jaffree.StreamType;
import com.github.kokorin.jaffree.ffprobe.FFprobe;
import com.github.kokorin.jaffree.ffprobe.FFprobeResult;
import com.github.kokorin.jaffree.ffprobe.Stream;
Expand All @@ -14,6 +16,8 @@
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertNotNull;

public class FFmpegFilterTest {

/**
Expand Down Expand Up @@ -108,14 +112,14 @@ public void testMosaic() throws Exception {
.addOutput(UrlOutput.toPath(outputPath))
.execute();

Assert.assertNotNull(result);
assertNotNull(result);

FFprobeResult probe = FFprobe.atPath(Config.FFMPEG_BIN)
.setInput(outputPath)
.setShowStreams(true)
.execute();

Assert.assertNotNull(probe);
assertNotNull(probe);

int width = 0;
int height = 0;
Expand Down Expand Up @@ -146,10 +150,14 @@ public void testConcatWithReencode() throws Exception {
Path outputPath = tempDir.resolve("concat.mp4");

FFmpegResult result = FFmpeg.atPath(Config.FFMPEG_BIN)
.addInput(UrlInput.fromPath(Artifacts.VIDEO_MP4).setDuration(5, TimeUnit.SECONDS))
.addInput(
UrlInput.fromPath(Artifacts.VIDEO_MKV).setPositionEof(-5, TimeUnit.SECONDS))

UrlInput.fromPath(Artifacts.VIDEO_MP4)
.setDuration(5, TimeUnit.SECONDS)
)
.addInput(
UrlInput.fromPath(Artifacts.VIDEO_MKV)
.setPositionEof(-5, TimeUnit.SECONDS)
)
.setComplexFilter(FilterGraph.of(
FilterChain.of(
Filter.fromInputLink("0:v")
Expand All @@ -174,19 +182,71 @@ public void testConcatWithReencode() throws Exception {
)
.execute();

Assert.assertNotNull(result);
assertNotNull(result);

FFprobeResult probe = FFprobe.atPath(Config.FFMPEG_BIN)
.setInput(outputPath)
.setShowStreams(true)
.execute();
assertNotNull(probe);

double duration = 0.0;
for (Stream stream : probe.getStreams()) {
duration = Math.max(duration, stream.getDuration());
}

Assert.assertNotNull(probe);
Assert.assertEquals(10.0, duration, 0.1);
}

@Test
public void drawTextWithSpecialCharacters() throws Exception {
Path tempDir = Files.createTempDirectory("jaffree");
Path outputPath = tempDir.resolve("draw_text.mp4");

FFmpegResult result = FFmpeg.atPath(Config.FFMPEG_BIN)
.addInput(
UrlInput.fromPath(Artifacts.VIDEO_MP4)
.setDuration(15, TimeUnit.SECONDS)
)
.setComplexFilter(
FilterGraph.of(
FilterChain.of(
Filter.withName("drawtext")
.addInputLink(StreamType.VIDEO)
.addArgument("text",
"this is a 'string': may contain one, or more," +
" special characters like: [ or ] or = or even ;")
.addArgument("box", "1")
.addArgument("boxborderw", "5")
.addArgument("boxcolor", "red")
.addArgument("fontsize", "24")
),
FilterChain.of(
Filter.withName("afade")
.addInputLink(StreamType.AUDIO)
.addArgument("t", "in")
.addArgument("ss", "0")
.addArgument("d", "10")
)
)
)
.addOutput(UrlOutput.toPath(outputPath))
.execute();


assertNotNull(result);

FFprobeResult probe = FFprobe.atPath(Config.FFMPEG_BIN)
.setInput(outputPath)
.setShowStreams(true)
.execute();
assertNotNull(probe);

double duration = 0.0;
for (Stream stream : probe.getStreams()) {
duration = Math.max(duration, stream.getDuration());
}

Assert.assertEquals(15.0, duration, 0.1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public void testGetValue2() throws Exception {
@Test
public void testEscape() throws Exception {
Assert.assertEquals("\\\\", GenericFilter.escape("\\"));
Assert.assertEquals("\\'", GenericFilter.escape("'"));
Assert.assertEquals("\\:", GenericFilter.escape(":"));
Assert.assertEquals("\\\\\\'", GenericFilter.escape("'"));
Assert.assertEquals("\\\\:", GenericFilter.escape(":"));

String text = "this is a 'string': may contain one, or more, special characters";
String expected = "this is a \\'string\\'\\: may contain one, or more, special characters";
String expected = "this is a \\\\\\'string\\\\\\'\\\\: may contain one\\, or more\\, special characters";
Assert.assertEquals(expected, GenericFilter.escape(text));
}

Expand Down

0 comments on commit 0186c42

Please sign in to comment.