Skip to content

Added Support for Duration Objects. #417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions src/main/java/com/github/kokorin/jaffree/ffmpeg/BaseInOut.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.github.kokorin.jaffree.StreamType;
import com.github.kokorin.jaffree.process.ProcessHelper;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -63,7 +64,21 @@ public T setFormat(final String format) {
this.format = format;
return thisAsT();
}


/**
* When used as an input option, limit the duration of data read from the
* input file.
* <p>
* When used as an output option, stop writing the output after its
* duration reaches duration.
*
* @param duration duration as Duration instance
* @return this
*/
public T setDuration(Duration duration) {
return setDuration(duration.toMillis());
}

/**
* When used as an input option, limit the duration of data read from the
* input file.
Expand Down Expand Up @@ -96,7 +111,30 @@ public T setDuration(final Number duration, final TimeUnit timeUnit) {
long millis = (long) (duration.doubleValue() * timeUnit.toMillis(1));
return setDuration(millis);
}



/**
* When used as an input option, seeks in this input file to position.
* <p>
* Note that in most formats it is not possible to seek exactly, so ffmpeg
* will seek to the closest seek point before position.
* When transcoding and -accurate_seek is enabled (the default), this extra
* segment between the seek point and position will be decoded and
* discarded.
* <p>
* When doing stream copy or when -noaccurate_seek is used,
* it will be preserved.
* <p>
* When used as an output option (before an output url), decodes but
* discards input until the timestamps reach position.
*
* @param duration position as a Duration instance.
* @return this
*/
public T setPosition(Duration duration) {
return setPosition(duration.toMillis());
}

/**
* When used as an input option, seeks in this input file to position.
* <p>
Expand Down Expand Up @@ -145,6 +183,18 @@ public T setPosition(final Number position, final TimeUnit unit) {
long millis = (long) (position.doubleValue() * unit.toMillis(1));
return setPosition(millis);
}

/**
* Like the {@link #setPosition(long)} (-ss) option but relative to
* the "end of file".
* That is negative values are earlier in the file, 0 is at EOF.
*
* @param duration position as a Duration instance, relative to the EOF
* @return this
*/
public T setPositionEof(Duration duration) {
return setPositionEof(duration.toMillis());
}

/**
* Like the {@link #setPosition(long)} (-ss) option but relative to
Expand Down
38 changes: 38 additions & 0 deletions src/test/java/com/github/kokorin/jaffree/ffmpeg/FFmpegTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -211,6 +212,43 @@ public void testDuration() throws Exception {
outputDuration = getDuration(outputPath);
assertEquals(10.0, outputDuration, 0.1);
}

@Test
public void testDurationInstance() throws Exception {
Path tempDir = Files.createTempDirectory("jaffree");
Path outputPath = tempDir.resolve(Artifacts.VIDEO_MP4.getFileName());

FFmpegResult result = FFmpeg.atPath(Config.FFMPEG_BIN)
.addInput(UrlInput
.fromPath(Artifacts.VIDEO_MP4)
.setDuration(Duration.ofSeconds(10))
)
.addOutput(UrlOutput
.toPath(outputPath)
.copyAllCodecs())
.execute();

Assert.assertNotNull(result);

double outputDuration = getDuration(outputPath);
assertEquals(10.0, outputDuration, 0.1);

result = FFmpeg.atPath(Config.FFMPEG_BIN)
.addInput(UrlInput
.fromPath(Artifacts.VIDEO_MP4)
.setDuration(Duration.ofMinutes(1).dividedBy(6))
)
.setOverwriteOutput(true)
.addOutput(UrlOutput
.toPath(outputPath)
.copyAllCodecs())
.execute();

Assert.assertNotNull(result);

outputDuration = getDuration(outputPath);
assertEquals(10.0, outputDuration, 0.1);
}

@Test
public void testForceStopWithProgressListenerException() throws Exception {
Expand Down
Loading