use of org.fagu.fmv.ffmpeg.operation.InputProcessor in project fmv by f-agu.
the class FFReducer method reduceVideo.
/**
* @param metadatas
* @param srcFile
* @param movieMetadatas
* @param destFile
* @param consolePrefixMessage
* @param logger
* @throws IOException
*/
public void reduceVideo(MovieMetadatas metadatas, File srcFile, MovieMetadatas movieMetadatas, File destFile, String consolePrefixMessage, Logger logger) throws IOException {
FFMPEGExecutorBuilder builder = FFMPEGExecutorBuilder.create();
builder.hideBanner();
InputProcessor inputProcessor = builder.addMediaInputFile(srcFile);
builder.filter(AutoRotate.create(movieMetadatas));
org.fagu.fmv.mymedia.reduce.FFReducer.applyScaleIfNecessary(builder, movieMetadatas, Size.HD720, logger);
MovieMetadatas videoMetadatas = inputProcessor.getMovieMetadatas();
Collection<AudioStream> audioStreams = StreamOrder.sort(videoMetadatas.getAudioStreams());
OutputProcessor outputProcessor = builder.addMediaOutputFile(destFile);
outputProcessor.qualityScale(0);
// video
for (Stream stream : videoMetadatas.getVideoStreams()) {
logger.log("map[" + stream.index() + "] video: " + stream);
outputProcessor.map().streams(stream).input(inputProcessor);
}
// audio
for (Stream stream : audioStreams) {
logger.log("map[" + stream.index() + "] audio: " + stream);
outputProcessor.map().streams(stream).input(inputProcessor);
}
// subtitle
Collection<SubtitleStream> subtitleStreams = StreamOrder.sort(videoMetadatas.getSubtitleStreams());
for (Stream stream : subtitleStreams) {
logger.log("map[" + stream.index() + "] subtitle: " + stream);
outputProcessor.map().streams(stream).input(inputProcessor);
}
// -------------------------- codec -------------------------
outputProcessor.codec(H264.findRecommanded().strict(Strict.EXPERIMENTAL).quality(23));
// subtitle
if (videoMetadatas.contains(Type.AUDIO)) {
outputProcessor.codecCopy(Type.AUDIO);
}
// subtitle
if (videoMetadatas.contains(Type.SUBTITLE)) {
outputProcessor.codecCopy(Type.SUBTITLE);
}
outputProcessor.overwrite();
FFExecutor<Object> executor = builder.build();
executor.addListener(org.fagu.fmv.mymedia.reduce.FFReducer.createLogFFExecListener(logger));
OptionalInt countEstimateFrames = metadatas.getVideoStream().countEstimateFrames();
Progress progress = executor.getProgress();
if (countEstimateFrames.isPresent() && progress != null) {
textProgressBar = FFMpegProgressBar.with(progress).byFrame(countEstimateFrames.getAsInt()).fileSize(srcFile.length()).build().makeBar(consolePrefixMessage);
} else {
StringJoiner joiner = new StringJoiner(", ");
if (progress == null) {
joiner.add("progress not found");
}
if (!countEstimateFrames.isPresent()) {
joiner.add("nb frames nout found");
}
logger.log("No progress bar: " + joiner.toString());
}
executor.execute();
}
use of org.fagu.fmv.ffmpeg.operation.InputProcessor in project fmv by f-agu.
the class ConcatFadeExecutable method applyConcatFade.
/**
* @param builder
* @param inputProcessors
* @param toFile
* @param cache
* @throws IOException
*/
protected void applyConcatFade(FFMPEGExecutorBuilder builder, List<InputProcessor> inputProcessors, File toFile, Cache cache) throws IOException {
if (inputProcessors.size() != 2) {
throw new RuntimeException("Need 2 inputs ! : " + inputProcessors);
}
InputProcessor video1InputProcessor = inputProcessors.get(0);
InputProcessor video2InputProcessor = inputProcessors.get(1);
VideoStream videoStream1 = video1InputProcessor.getMovieMetadatas().getVideoStream();
VideoStream videoStream2 = video2InputProcessor.getMovieMetadatas().getVideoStream();
Time startTimeT1 = Time.valueOf(videoStream1.duration().get().toSeconds() - duration.toSeconds());
Duration duration0T1 = Duration.valueOf(startTimeT1.toSeconds());
Time startTimeT2 = Time.valueOf(videoStream2.duration().get().toSeconds() - duration.toSeconds());
Duration durationT2END = Duration.valueOf(startTimeT2.toSeconds());
// source 1: video
NullSourceVideo nullSourceVideo1 = NullSourceVideo.build().size(videoStream1.size()).duration(durationT2END);
Concat concat1V = Concat.create(builder, video1InputProcessor, FilterComplex.create(nullSourceVideo1)).countVideo(1).countAudio(0).countInputs(2);
// source 1: audio
AudioGenerator audioGenerator1 = AudioGenerator.build().silence().duration(durationT2END);
Concat concat1A = Concat.create(builder, video1InputProcessor, FilterComplex.create(audioGenerator1)).countVideo(0).countAudio(1).countInputs(2);
FilterComplex fadeAudio1 = FilterComplex.create(FadeAudio.out().startTime(startTimeT1).duration(duration)).addInput(concat1A);
// source 2: video
NullSourceVideo nullSourceVideo2 = NullSourceVideo.build().size(videoStream2.size()).duration(duration0T1);
Concat concat2V = Concat.create(builder, FilterComplex.create(nullSourceVideo2), video2InputProcessor).countVideo(1).countAudio(0).countInputs(2);
// source 2: audio
AudioGenerator audioGenerator2 = AudioGenerator.build().silence().duration(duration0T1);
Concat concat2A = Concat.create(builder, FilterComplex.create(audioGenerator2), video2InputProcessor).countVideo(0).countAudio(1).countInputs(2);
FilterComplex fadeAudio2 = FilterComplex.create(FadeAudio.in().startTime(startTimeT1).duration(duration)).addInput(concat2A);
// blend / merge video
SetSAR setSAR = SetSAR.toRatio("1");
Format formatRGBA = Format.with(PixelFormat.RGBA);
FilterComplex vfc1 = FilterComplex.create(setSAR, formatRGBA).addInput(concat1V);
FilterComplex vfc2 = FilterComplex.create(setSAR, formatRGBA).addInput(concat2V);
Blend blend = Blend.build().mode(Mode.ADDITION).repeatLast(true).opacity(1).exprFade(startTimeT1, duration);
Format formatYUV = Format.with(PixelFormat.YUVA422P10LE);
FilterComplex vfcBlend = FilterComplex.create(blend, formatYUV).addInput(vfc1).addInput(vfc2);
builder.filter(vfcBlend);
// merge audio
FilterComplex audioMix = AudioMix.build().duration(MixAudioDuration.SHORTEST).addInput(fadeAudio1).addInput(fadeAudio2);
builder.filter(audioMix);
outputProcessor(builder, toFile, cache);
}
use of org.fagu.fmv.ffmpeg.operation.InputProcessor in project fmv by f-agu.
the class ConcatFadeExecutable method execute.
/**
* @see org.fagu.fmv.core.exec.Executable#execute()
*/
@Override
public void execute(File toFile, Cache cache) throws IOException {
if (!hasChildren()) {
return;
}
FFMPEGExecutorBuilder builder = FFUtils.builder(getProject());
List<InputProcessor> inputProcessors = new ArrayList<>();
// executable
for (Executable executable : executables) {
File file = getProject().getFileCache().getFile(executable, cache);
InputProcessor inputProcessor = builder.addMediaInputFile(file);
// audioMix.addInput(inputProcessor);
inputProcessors.add(inputProcessor);
}
// source
for (Source source : sources) {
FilterInput filterInput = source.createAndAdd(builder);
if (filterInput instanceof InputProcessor) {
inputProcessors.add((InputProcessor) filterInput);
// MovieMetadatas movieMetadatas = ((InputProcessor)filterInput).getMovieMetadatas();
// if(movieMetadatas.contains(Type.AUDIO)) {
// audioMix.addInput(filterInput, audioStart);
// } else {
// throw new RuntimeException("Source is not an audio stream: " + source);
// }
} else {
throw new RuntimeException("Source is not a InputProcessor: " + source);
}
}
applyConcatFade(builder, inputProcessors, toFile, cache);
FFExecutor<Object> executor = builder.build();
executor.execute();
}
use of org.fagu.fmv.ffmpeg.operation.InputProcessor in project fmv by f-agu.
the class RipperTestCase method ffMPEGExecutorBuilder.
/**
* @return
* @throws IOException
*/
private FFMPEGExecutorBuilder ffMPEGExecutorBuilder() throws IOException {
FFMPEGExecutorBuilder builder = mock(FFMPEGExecutorBuilder.class);
doReturn(builder).when(builder).hideBanner();
doReturn(builder).when(builder).noStats();
InputProcessor inputProcessor = mock(InputProcessor.class);
doReturn(inputProcessor).when(builder).addMediaInputFile(any(File.class));
MovieMetadatas movieMetadatas = mock(MovieMetadatas.class);
doReturn(movieMetadatas).when(inputProcessor).getMovieMetadatas();
OutputProcessor outputProcessor = mock(OutputProcessor.class);
doReturn(outputProcessor).when(builder).addMediaOutputFile(any(File.class));
doReturn(outputProcessor).when(outputProcessor).codec(any(Coder.class));
return builder;
}
use of org.fagu.fmv.ffmpeg.operation.InputProcessor in project fmv by f-agu.
the class MockFFMPEGExecutorBuilder method mock.
/**
* @param movieMetadatasSupplier
* @param commandExecute
*/
public static void mock(Supplier<Function<String, MovieMetadatas>> movieMetadatasSupplier, final Consumer<String> commandExecute) {
FFMPEGExecutorBuilder.setFactory(() -> {
final FFExecutorFactory ffExecutorFactory = new FFExecutorFactory() {
@Override
public <R> FFExecutor<R> create(Operation<R, ?> operation, FFMPEGExecutorBuilder ffmpegExecutorBuilder) {
return new FFExecutor<R>(operation) {
/**
* @see org.fagu.fmv.ffmpeg.executor.FFExecutor#execute()
*/
@Override
public Executed<R> execute() throws IOException {
commandExecute.accept(getCommandLine());
return null;
}
};
}
};
Require require = new Require(false);
DefaultFFMPEGOperation<?> defaultFFMPEGOperation = new DefaultFFMPEGOperation<Object>(new FilterNaming(), require);
defaultFFMPEGOperation.getInputParameters().setInputProcessorFactory(new InputProcessorFactory() {
/**
* @see org.fagu.fmv.ffmpeg.operation.InputProcessorFactory#create(org.fagu.fmv.ffmpeg.operation.InputParameters,
* org.fagu.fmv.ffmpeg.operation.MediaInput, int, org.fagu.fmv.ffmpeg.require.Require)
*/
@Override
public InputProcessor create(InputParameters inputParameters, MediaInput input, int index, Require require) {
return new MyInputProcessor(movieMetadatasSupplier.get(), inputParameters, input, index, require);
}
});
return new MyFFMPEGExecutorBuilder(ffExecutorFactory, defaultFFMPEGOperation);
});
}
Aggregations