All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.selcukes.video.FFmpegRecorder Maven / Gradle / Ivy

There is a newer version: 2.3.13
Show newest version
/*
 * Copyright (c) Ramesh Babu Prudhvi.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.github.selcukes.video;

import io.github.selcukes.collections.Clocks;
import io.github.selcukes.commons.Await;
import io.github.selcukes.commons.config.ConfigFactory;
import io.github.selcukes.commons.exception.RecorderException;
import io.github.selcukes.commons.exec.Shell;
import io.github.selcukes.commons.helper.FileHelper;
import io.github.selcukes.commons.helper.Preconditions;
import io.github.selcukes.commons.logging.Logger;
import io.github.selcukes.commons.logging.LoggerFactory;
import io.github.selcukes.commons.os.Platform;
import io.github.selcukes.video.config.DefaultVideoOptions;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;

import static io.github.selcukes.collections.Clocks.DATE_TIME_FILE_FORMAT;

class FFmpegRecorder implements VideoRecorder {
    private static final Logger logger = LoggerFactory.getLogger(FFmpegRecorder.class);
    private static final String FFMPEG = "ffmpeg";
    private static final String EXTENSION = ".mp4";
    private final DefaultVideoOptions videoConfig;
    private final Shell shell;
    private File tempFile;
    private String ffmpegFolderPath = "";

    public FFmpegRecorder() {
        shell = new Shell();
        this.videoConfig = VideoRecorder.videoConfig();
        if (ConfigFactory.getConfig().getVideo().getFfmpegPath() != null) {
            ffmpegFolderPath = ConfigFactory.getConfig().getVideo().getFfmpegPath();
        }
    }

    public void start() {

        tempFile = getFile("Video");
        String screenSize = getScreenSize();

        String command = ffmpegFolderPath + FFMPEG + " -y " +
                "-video_size " + screenSize +
                " -f " + videoConfig.getFfmpegFormat() +
                " -i " + videoConfig.getFfmpegDisplay() +
                " -an " +
                " -framerate " + videoConfig.getFrameRate() +
                " -pix_fmt " + videoConfig.getPixelFormat() + " " +
                tempFile.getAbsolutePath();
        shell.runCommandAsync(command);
        logger.info(() -> "Recording started to " + tempFile.getAbsolutePath());
    }

    @Override
    public File stopAndSave(final String filename) {
        stop();
        Preconditions.checkArgument(tempFile.exists(), "Video recording wasn't started");
        File videoFile = getFile(filename);
        if (ConfigFactory.getConfig().getVideo().isWatermark()) {
            File waterMark = FileHelper.getWaterMarkFile();
            String command = ffmpegFolderPath + FFMPEG + " -i " + tempFile.getAbsolutePath() +
                    " -i " + waterMark.getAbsolutePath() +
                    " -filter_complex \"overlay=x=(main_w-200):y=5\" " + videoFile.getAbsolutePath();
            shell.runCommand(command);
            tempFile.deleteOnExit();
            Await.until(1);
        } else {
            try {
                FileHelper.renameFile(tempFile, videoFile);
            } catch (RecorderException ex) {
                Await.until(2);
                FileHelper.renameFile(tempFile, videoFile);
            }
        }
        logger.info(() -> "Recording finished to " + videoFile.getAbsolutePath());
        return videoFile;
    }

    private void stop() {
        logger.info(() -> "Killing ffmpeg...");
        String killFFmpeg = "pkill -INT ffmpeg";
        if (Platform.isWindows()) {
            shell.sendCtrlC(ffmpegFolderPath);
        } else {
            shell.runCommand(killFFmpeg);
        }
        Await.until(2);
    }

    @Override
    public void stopAndDelete() {
        stop();
        logger.info(() -> "Deleting recorded video file...");
        tempFile.deleteOnExit();
    }

    private String getScreenSize() {
        Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
        return dimension.width + "x" + dimension.height;
    }

    private File getFile(String fileName) {
        File movieFolder = createMovieFolder();
        String name = fileName + "_recording_" + Clocks.dateTime(DATE_TIME_FILE_FORMAT);
        return new File(movieFolder + File.separator + name + EXTENSION);
    }

    private File createMovieFolder() {
        File movieFolder = new File(videoConfig.getVideoFolder());
        FileHelper.createDirectory(movieFolder);
        return movieFolder;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy