I'm trying to use ffmpeg for generating a video file from timelapse images. Somehow I didn't find out which codec resp. which parameters I have to use in ffmpeg, that the video file is playable with JavaFX's MediaPlayer
. I tried these codecs:
- libx264 (
ffmpeg -f image2 -i %05d.jpg -r 30 -filter:v
crop=4000:2250:0:0 -s 1920x1080 -vcodec libx264 -preset ultrafast -qp
0 Timelapse3.mp4
)
- mpeg4 (
ffmpeg -f image2 -i %05d.jpg -r 30 -filter:v
crop=4000:2250:0:0 -s 1920x1080 -vcodec mpeg4 -qscale 1
../Timelapse.avi
)
But they didn't work with JavaFX. What codec and parameter do I have to use for a high quality output?
The following worked for me if I have an input as mp4 (but it should work accordingly with other input formats, as in your case the image timelapse):
ffmpeg -i input.mp4 -vcodec h264 -vf scale=1920x1080 -an -pix_fmt yuv420p output.mp4
So the important parts are:
- changing the pix_fmt. Apparently the default one is not supported.
- and the resolution seems to be only working if it is lower than or equal to 1920x1080
- I don't need audio in my case! (if you need audio remove the
-an
or replace with working audio codec conversion)
The avi
container format isn't supported by JavaFX so won't work - your first example should however play ball ok - I've tried it and it works for me.
You could also try forcing the mp4 container with the same f
switch but just before the output file:
ffmpeg -f image2 -i %05d.jpg -r 30 -filter:v crop=4000:2250:0:0 -s 1920x1080 -vcodec mpeg4 -qscale 1 -f mp4 ../Timelapse.mp4
(Also try the above with libx264.)
Try this
Replace the file name in the quotes with your file name. The file name numbering should start with 0 then go to 1, 2, 3, 4 and so on
This is how my file names look
Mandibular hollow 1 micron.gizmofill0.gizmoslice.jpg
Mandibular hollow 1 micron.gizmofill17.gizmoslice.jpg
Mandibular hollow 1 micron.gizmofill16994.gizmoslice.jpg
My files range between 198kb and 47kb in size. I have about 18500 files. All the files combined are about 2.9GB. This will generate a movie file at 50 frames per second that is around 25MB
ffmpeg -framerate 50 -i "Mandibular hollow 1 micron.gizmofill%d.gizmoslice.jpg" -s 1638x1004 -c:v libx264 -pix_fmt yuv420p output.mp4
This controller code works for me
package javafxapplication13;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
/**
*
* @author kobus
*/
public class FXMLDocumentController implements Initializable {
@FXML
private MediaView mediaView;
@FXML
private void handleButtonAction(ActionEvent event) {
final File f = new File("C:/Users/kobus/Dropbox/JavaProjects/Gizmetor/temp/output.mp4");
Media media = new Media(f.toURI().toString());
MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
mediaPlayer.play();
mediaView.setMediaPlayer(mediaPlayer);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
This is the .fxml file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.media.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication13.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="Click Me!" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
<MediaView fx:id="mediaView" fitHeight="1005.0" fitWidth="1638.0" layoutX="14.0" layoutY="165.0" />
</children>
</AnchorPane>
Here is the application file
package javafxapplication13;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author kobus
*/
public class JavaFXApplication13 extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}