En esta aplicación Java, estoy tratando de convertir un video en pequeños clips.

Aquí está la clase de implementación para el mismo

package ffmpeg.clip.process; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Paths; import java.time.Duration; import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import ffmpeg.clip.utils.VideoConstant; import ffmpeg.clip.utils.VideoUtils; /* * @author Nitishkumar Singh * @Description: class will use ffmpeg to break an source video into clips */ public class VideoToClip { /* * Prevent from creating instance */ private VideoToClip() { } /** * Get Video Duration is milliseconds * * @Exception IOException - File does not exist VideoException- Video File have data issues */ static LocalTime getDuration(String sourceVideoFile) throws Exception { if (!Paths.get(sourceVideoFile).toFile().exists()) throw new Exception("File does not exist!!"); Process proc = new ProcessBuilder(VideoConstant.SHELL, VideoConstant.SHELL_COMMAND_STRING_ARGUMENT, String.format(VideoConstant.DURATION_COMMAND, sourceVideoFile)).start(); boolean errorOccured = (new BufferedReader(new InputStreamReader(proc.getErrorStream())).lines() .count() > VideoConstant.ZERO); String durationInSeconds = new BufferedReader(new InputStreamReader(proc.getInputStream())).lines() .collect(Collectors.joining(System.lineSeparator())); proc.destroy(); if (errorOccured || (durationInSeconds.length() == VideoConstant.ZERO)) throw new Exception("Video File have some issues!"); else return VideoUtils.parseHourMinuteSecondMillisecondFormat(durationInSeconds); } /** * Create Clips for Video Using Start and End Second * * @Exception IOException - Clip Creation Process Failed InterruptedException - Clip Creation task get"s failed */ static String toClipProcess(String sourceVideo, String outputDirectory, LocalTime start, LocalTime end, String fileExtension) throws IOException, InterruptedException, ExecutionException { String clipName = String.format(VideoConstant.CLIP_FILE_NAME, VideoUtils.getHourMinuteSecondMillisecondFormat(start), VideoUtils.getHourMinuteSecondMillisecondFormat(end), fileExtension); String command = String.format(VideoConstant.FFMPEG_OUTPUT_COMMAND, sourceVideo, VideoUtils.getHourMinuteSecondMillisecondFormat(start), VideoUtils.getHourMinuteSecondMillisecondFormat(end.minus(start.toNanoOfDay(), ChronoUnit.NANOS)), outputDirectory, clipName); LocalTime startTime = LocalTime.now(); System.out.println("Clip Name: " + clipName); System.out.println("FFMPEG Process Execution Started"); CompletableFuture<Process> completableFuture = CompletableFuture.supplyAsync(() -> { try { return executeProcess(command); } catch (InterruptedException | IOException ex) { throw new RuntimeException(ex); } }); completableFuture.get(); // remove LocalTime endTime = LocalTime.now(); System.out.println("Clip Name: " + clipName); System.out.println("FFMPEG Process Execution Finished"); System.out.println("Duration: " + Duration.between(startTime, endTime).toMillis() / 1000); return clipName; } /** * Create and Execute Process for each command */ static Process executeProcess(String command) throws InterruptedException, IOException { Process clipProcess = Runtime.getRuntime().exec(command); clipProcess.waitFor(); return clipProcess; } } 

La solución completa está disponible en Github . De hecho, estoy usando CompletableFuture y ejecuto el comando FFMPEG creando un proceso Java. El tiempo que lleva es demasiado. Para un video de 40 minutos, toma más de 49 minutos, en una máquina de 64 CPU. Estoy tratando de reducir el tamaño del núcleo a 8 o algo así, así como mejorar su rendimiento, ya que este tipo de rendimiento no será aceptable para ningún tipo de aplicación.

Actualización del 22 de enero de 2017
Una actualización, he cambiado el comando FFMPEG para crear clips y actualizado a FFMPEG 3, pero no hay ninguna mejora.

ffmpeg -y -i INPUT_FILE_PATH -ss TIME_STAMP -t DURATION_TO_CLIP OUTPUT_FILE_PATH

Comentarios

  • Publiqué algunos ejemplos usando JavaCV No ‘ probé con un video largo pero para videos cortos (es decir 5 minutos) el tiempo de procesamiento es de aproximadamente 1 minuto.

Respuesta

Esa es una restricción natural en el video En las máquinas modernas, 1 minuto de video de 720p se codifica aproximadamente en 1 minuto.

Puede ahorrar mucho tiempo si no necesita volver a codificar (es decir. cambiando el códec o el tamaño del video) usando la opción -codec copy ffmpeg.

También dijiste que tienes 64 núcleos, pero tu código usa solo 1 hilo para codificar. Utilice -threads 0 para permitir que ffmpeg elija por sí mismo.

Además, si necesita realizar esto en Java, proporcione Jaffree una oportunidad (soy un autor).

Comentarios

  • Si escribió Jaffree, por favor, dígalo explícitamente .
  • github.com/bramp/ffmpeg-cli-wrapper podría ser una mejor solución para usted.
  • Empecé Jaffree exactamente por varios problemas con ffmpeg-cli-wrapper.

Respuesta

Sé que esto es una vieja pregunta, pero creo que esto podría ser útil para los desarrolladores de Java.

Hay una bonita biblioteca llamada JavaCV que esta en vivo es un contenedor para múltiples bibliotecas C y C ++ como FFmpeg.

Esta es un ejemplo simple de cómo implementar un convertidor:

import org.bytedeco.javacpp.avcodec; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class PacketRecorderTest { private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd__hhmmSSS"); private static final int RECORD_LENGTH = 5000; private static final boolean AUDIO_ENABLED = false; public static void main(String[] args) throws FrameRecorder.Exception, FrameGrabber.Exception { String inputFile = "/home/usr/videos/VIDEO_FILE_NAME.mp4"; // Decodes-encodes String outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_frameRecord.mp4"; PacketRecorderTest.frameRecord(inputFile, outputFile); // copies codec (no need to re-encode) outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_packetRecord.mp4"; PacketRecorderTest.packetRecord(inputFile, outputFile); } public static void frameRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception { int audioChannel = AUDIO_ENABLED ? 1 : 0; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); grabber.start(); recorder.start(); Frame frame; long t1 = System.currentTimeMillis(); while ((frame = grabber.grabFrame(AUDIO_ENABLED, true, true, false)) != null) { recorder.record(frame); if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) { break; } } recorder.stop(); grabber.stop(); } public static void packetRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception { int audioChannel = AUDIO_ENABLED ? 1 : 0; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); grabber.start(); recorder.start(grabber.getFormatContext()); avcodec.AVPacket packet; long t1 = System.currentTimeMillis(); while ((packet = grabber.grabPacket()) != null) { recorder.recordPacket(packet); if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) { break; } } recorder.stop(); grabber.stop(); } } 

Esta implementación básica muestra cómo convertir un video usando un paquete FFmpeg o un Marco JavaCV .

Comentarios

  • Bienvenido a Code Review. Ha presentado una solución alternativa, pero no ‘ t revisó el código. Explique su razonamiento (cómo funciona su solución y por qué es mejor que la original) para que el autor y otros lectores puedan aprender de su proceso de pensamiento.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *