bramp / ffmpeg-cli-wrapper

Java wrapper around the FFmpeg command line tool
BSD 2-Clause "Simplified" License
1.72k stars 412 forks source link

Add FFmpegInputBuilder to support per input options #318

Closed Euklios closed 2 months ago

Euklios commented 8 months ago

Is your feature request related to a problem? Please describe. We currently don't allow per-input options; therefore, commands requiring multiple inputs aren't supported in many cases. For example the following command can't be constructed using this library: ffmpeg -f lavfi -i "testsrc=duration=10:size=1280x720:rate=30" -f lavfi -i "sine=frequency=1000:sample_rate=48000:duration=10" -c:a aac -c:v h264 output.mp4.

Describe the solution you'd like An FFmpegInputBuilder to construct inputs and allow parameters for individual inputs.

Describe alternatives you've considered The alternative would be to hack around with addExtraArgs. However, that would undermine the purpose of this library.

Related:

Euklios commented 8 months ago

This is mainly focused towards fixing EncodingOptions and making it easier to update in the future. But it should also adding new arguments and flags easier.

AlexanderSchuetz97 commented 3 months ago

I am inrested in this too. I currently use addExtraOptions to pass pass input options for decoding rawvideo, like videosize and pixel format.

Euklios commented 3 months ago

@AlexanderSchuetz97 Thank you for the feedback! If possible, could you share some example commands I can use for tests?

Euklios commented 3 months ago

For anyone interested, I created PR #339 for this feature.

AlexanderSchuetz97 commented 3 months ago

i forgot about giving you examples today. Will do so on monday hopefully.

Euklios commented 3 months ago

No problem, any form of help is appreciated

AlexanderSchuetz97 commented 3 months ago

These are the 2 Main occurrences of "addExtraArgs" for an Input in the code-base of my current Project. One is the raw video use case, the other is -strict 2 which I also need for ffprobe. It allows ffmpeg to decode vvc/h266 videos.

Also FYI, add an option to disable B frames please. (-bf 0) FFmpeg outputs them by default and 99% of devices that must play the output cannot handle them.

FFmpegBuilder builder = new FFmpegBuilder()
        .addExtraArgs("-video_size", size.getWidth() +"x"+size.getHeight())
        .addExtraArgs("-f", "rawvideo")
        .addExtraArgs("-r", Fraction.getFraction(fps).toString())
        .addExtraArgs("-pix_fmt", "bgr24")
        .addInput("unix://" + socketFile.toAbsolutePath())
        .addOutput(output.getAbsolutePath())
        .addExtraArgs("-bf", "0")
        .setVideoCodec(codec)
        .setFormat(format)
        .disableAudio()
        .done();

FFmpegOutputBuilder builder = mpeg.builder()
        .addExtraArgs("-strict", "-2")
        .addInput(input.getAbsolutePath())
        .addOutput(output.getAbsolutePath())
        .setVideoCodec(videoCodec)
        .setAudioCodec(audioCodec)
        .addExtraArgs("-bf", "0")
        .setFormat(format);

Just FYI This is what I had to do to get your FFProbe to recognize vvc/h266 videos

public class FFProbeWrapper extends FFprobe {

    private static final Map<String, String> VERSION_MAP = new ConcurrentHashMap<>();

    public FFProbeWrapper(@Nonnull String path) throws IOException {
        super(path,new RunProcessFunction() {
            @Override
            public Process run(List<String> args) throws IOException {
                if (args.isEmpty()) {
                    return super.run(args);
                }
                List<String> ar = new ArrayList<>();
                ar.add(args.getFirst());
                ar.add("-strict");
                ar.add("-2");
                ar.addAll(args.subList(1, args.size()));
                return super.run(ar);
            }
        });
    }

    @Nonnull
    @Override
    public synchronized String version() throws IOException {
        String s = VERSION_MAP.get(this.getPath());
        if (s != null) {
            return s;
        }

        String v =  super.version();
        VERSION_MAP.put(this.getPath(), v);
        return v;
    }
}

If you need a H266 testfile I can provide one.

Euklios commented 2 months ago

I've extracted the two issues #345 and #346 based on this. Strictness -2 matches with experimental, so to my understanding the flag is just not at the right position (on the right builder)